Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-s7comm.c
Line
Count
Source
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 <epan/tfs.h>
19
#include <wsutil/array.h>
20
#include <wsutil/strtoi.h>
21
#include <epan/expert.h>
22
23
#include "packet-s7comm.h"
24
#include "packet-s7comm_szl_ids.h"
25
26
838
#define PROTO_TAG_S7COMM                    "S7COMM"
27
28
/* Min. telegram length for heuristic check */
29
3.18k
#define S7COMM_MIN_TELEGRAM_LENGTH          10
30
31
/* Protocol identifier */
32
2.39k
#define S7COMM_PROT_ID                      0x32
33
34
/* Wireshark ID of the S7COMM protocol */
35
static int proto_s7comm;
36
37
/* Forward declarations */
38
void proto_reg_handoff_s7comm(void);
39
void proto_register_s7comm (void);
40
static uint32_t s7comm_decode_ud_tis_data(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint8_t type, uint8_t subfunc, uint16_t td_size, uint32_t offset);
41
42
/**************************************************************************
43
 * PDU types
44
 */
45
57
#define S7COMM_ROSCTR_JOB                   0x01
46
#define S7COMM_ROSCTR_ACK                   0x02
47
44
#define S7COMM_ROSCTR_ACK_DATA              0x03
48
793
#define S7COMM_ROSCTR_USERDATA              0x07
49
50
static const value_string rosctr_names[] = {
51
    { S7COMM_ROSCTR_JOB,                    "Job" },        /* Request: job with acknowledgement */
52
    { S7COMM_ROSCTR_ACK,                    "Ack" },        /* acknowledgement without additional field */
53
    { S7COMM_ROSCTR_ACK_DATA,               "Ack_Data" },   /* Response: acknowledgement with additional field */
54
    { S7COMM_ROSCTR_USERDATA,               "Userdata" },
55
    { 0,                                    NULL }
56
};
57
/**************************************************************************
58
 * Error classes in header
59
 */
60
#define S7COMM_ERRCLS_NONE                  0x00
61
#define S7COMM_ERRCLS_APPREL                0x81
62
#define S7COMM_ERRCLS_OBJDEF                0x82
63
#define S7COMM_ERRCLS_RESOURCE              0x83
64
#define S7COMM_ERRCLS_SERVICE               0x84
65
#define S7COMM_ERRCLS_SUPPLIES              0x85
66
#define S7COMM_ERRCLS_ACCESS                0x87
67
68
static const value_string errcls_names[] = {
69
    { S7COMM_ERRCLS_NONE,                   "No error" },
70
    { S7COMM_ERRCLS_APPREL,                 "Application relationship" },
71
    { S7COMM_ERRCLS_OBJDEF,                 "Object definition" },
72
    { S7COMM_ERRCLS_RESOURCE,               "No resources available" },
73
    { S7COMM_ERRCLS_SERVICE,                "Error on service processing" },
74
    { S7COMM_ERRCLS_SUPPLIES,               "Error on supplies" },
75
    { S7COMM_ERRCLS_ACCESS,                 "Access error" },
76
    { 0,                                    NULL }
77
};
78
79
/**************************************************************************
80
 * Error code in parameter part
81
 */
82
83
static const value_string param_errcode_names[] = {
84
    { 0x0000,                               "No error" },
85
    { 0x0110,                               "Invalid block number" },
86
    { 0x0111,                               "Invalid request length" },
87
    { 0x0112,                               "Invalid parameter" },
88
    { 0x0113,                               "Invalid block type" },
89
    { 0x0114,                               "Block not found" },
90
    { 0x0115,                               "Block already exists" },
91
    { 0x0116,                               "Block is write-protected" },
92
    { 0x0117,                               "The block/operating system update is too large" },
93
    { 0x0118,                               "Invalid block number" },
94
    { 0x0119,                               "Incorrect password entered" },
95
    { 0x011A,                               "PG resource error" },
96
    { 0x011B,                               "PLC resource error" },
97
    { 0x011C,                               "Protocol error" },
98
    { 0x011D,                               "Too many blocks (module-related restriction)" },
99
    { 0x011E,                               "There is no longer a connection to the database, or S7DOS handle is invalid" },
100
    { 0x011F,                               "Result buffer too small" },
101
    { 0x0120,                               "End of block list" },
102
    { 0x0140,                               "Insufficient memory available" },
103
    { 0x0141,                               "Job cannot be processed because of a lack of resources" },
104
    { 0x8001,                               "The requested service cannot be performed while the block is in the current status" },
105
    { 0x8003,                               "S7 protocol error: Error occurred while transferring the block" },
106
    { 0x8100,                               "Application, general error: Service unknown to remote module" },
107
    { 0x8104,                               "This service is not implemented on the module or a frame error was reported" },
108
    { 0x8204,                               "The type specification for the object is inconsistent" },
109
    { 0x8205,                               "A copied block already exists and is not linked" },
110
    { 0x8301,                               "Insufficient memory space or work memory on the module, or specified storage medium not accessible" },
111
    { 0x8302,                               "Too few resources available or the processor resources are not available" },
112
    { 0x8304,                               "No further parallel upload possible. There is a resource bottleneck" },
113
    { 0x8305,                               "Function not available" },
114
    { 0x8306,                               "Insufficient work memory (for copying, linking, loading AWP)" },
115
    { 0x8307,                               "Not enough retentive work memory (for copying, linking, loading AWP)" },
116
    { 0x8401,                               "S7 protocol error: Invalid service sequence (for example, loading or uploading a block)" },
117
    { 0x8402,                               "Service cannot execute owing to status of the addressed object" },
118
    { 0x8404,                               "S7 protocol: The function cannot be performed" },
119
    { 0x8405,                               "Remote block is in DISABLE state (CFB). The function cannot be performed" },
120
    { 0x8500,                               "S7 protocol error: Wrong frames" },
121
    { 0x8503,                               "Alarm from the module: Service canceled prematurely" },
122
    { 0x8701,                               "Error addressing the object on the communications partner (for example, area length error)" },
123
    { 0x8702,                               "The requested service is not supported by the module" },
124
    { 0x8703,                               "Access to object refused" },
125
    { 0x8704,                               "Access error: Object damaged" },
126
    { 0xD001,                               "Protocol error: Illegal job number" },
127
    { 0xD002,                               "Parameter error: Illegal job variant" },
128
    { 0xD003,                               "Parameter error: Debugging function not supported by module" },
129
    { 0xD004,                               "Parameter error: Illegal job status" },
130
    { 0xD005,                               "Parameter error: Illegal job termination" },
131
    { 0xD006,                               "Parameter error: Illegal link disconnection ID" },
132
    { 0xD007,                               "Parameter error: Illegal number of buffer elements" },
133
    { 0xD008,                               "Parameter error: Illegal scan rate" },
134
    { 0xD009,                               "Parameter error: Illegal number of executions" },
135
    { 0xD00A,                               "Parameter error: Illegal trigger event" },
136
    { 0xD00B,                               "Parameter error: Illegal trigger condition" },
137
    { 0xD011,                               "Parameter error in path of the call environment: Block does not exist" },
138
    { 0xD012,                               "Parameter error: Wrong address in block" },
139
    { 0xD014,                               "Parameter error: Block being deleted/overwritten" },
140
    { 0xD015,                               "Parameter error: Illegal tag address" },
141
    { 0xD016,                               "Parameter error: Test jobs not possible, because of errors in user program" },
142
    { 0xD017,                               "Parameter error: Illegal trigger number" },
143
    { 0xD025,                               "Parameter error: Invalid path" },
144
    { 0xD026,                               "Parameter error: Illegal access type" },
145
    { 0xD027,                               "Parameter error: This number of data blocks is not permitted" },
146
    { 0xD031,                               "Internal protocol error" },
147
    { 0xD032,                               "Parameter error: Wrong result buffer length" },
148
    { 0xD033,                               "Protocol error: Wrong job length" },
149
    { 0xD03F,                               "Coding error: Error in parameter section (for example, reserve bytes not equal to 0)" },
150
    { 0xD041,                               "Data error: Illegal status list ID" },
151
    { 0xD042,                               "Data error: Illegal tag address" },
152
    { 0xD043,                               "Data error: Referenced job not found, check job data" },
153
    { 0xD044,                               "Data error: Illegal tag value, check job data" },
154
    { 0xD045,                               "Data error: Exiting the ODIS control is not allowed in HOLD" },
155
    { 0xD046,                               "Data error: Illegal measuring stage during run-time measurement" },
156
    { 0xD047,                               "Data error: Illegal hierarchy in 'Read job list'" },
157
    { 0xD048,                               "Data error: Illegal deletion ID in 'Delete job'" },
158
    { 0xD049,                               "Invalid substitute ID in 'Replace job'" },
159
    { 0xD04A,                               "Error executing 'program status'" },
160
    { 0xD05F,                               "Coding error: Error in data section (for example, reserve bytes not equal to 0, ...)" },
161
    { 0xD061,                               "Resource error: No memory space for job" },
162
    { 0xD062,                               "Resource error: Job list full" },
163
    { 0xD063,                               "Resource error: Trigger event occupied" },
164
    { 0xD064,                               "Resource error: Not enough memory space for one result buffer element" },
165
    { 0xD065,                               "Resource error: Not enough memory space for several  result buffer elements" },
166
    { 0xD066,                               "Resource error: The timer available for run-time measurement is occupied by another job" },
167
    { 0xD067,                               "Resource error: Too many 'modify tag' jobs active (in particular multi-processor operation)" },
168
    { 0xD081,                               "Function not permitted in current mode" },
169
    { 0xD082,                               "Mode error: Cannot exit HOLD mode" },
170
    { 0xD0A1,                               "Function not permitted in current protection level" },
171
    { 0xD0A2,                               "Function not possible at present, because a function is running that modifies memory" },
172
    { 0xD0A3,                               "Too many 'modify tag' jobs active on the I/O (in particular multi-processor operation)" },
173
    { 0xD0A4,                               "'Forcing' has already been established" },
174
    { 0xD0A5,                               "Referenced job not found" },
175
    { 0xD0A6,                               "Job cannot be disabled/enabled" },
176
    { 0xD0A7,                               "Job cannot be deleted, for example because it is currently being read" },
177
    { 0xD0A8,                               "Job cannot be replaced, for example because it is currently being read or deleted" },
178
    { 0xD0A9,                               "Job cannot be read, for example because it is currently being deleted" },
179
    { 0xD0AA,                               "Time limit exceeded in processing operation" },
180
    { 0xD0AB,                               "Invalid job parameters in process operation" },
181
    { 0xD0AC,                               "Invalid job data in process operation" },
182
    { 0xD0AD,                               "Operating mode already set" },
183
    { 0xD0AE,                               "The job was set up over a different connection and can only be handled over this connection" },
184
    { 0xD0C1,                               "At least one error has been detected while accessing the tag(s)" },
185
    { 0xD0C2,                               "Change to STOP/HOLD mode" },
186
    { 0xD0C3,                               "At least one error was detected while accessing the tag(s). Mode change to STOP/HOLD" },
187
    { 0xD0C4,                               "Timeout during run-time measurement" },
188
    { 0xD0C5,                               "Display of block stack inconsistent, because blocks were deleted/reloaded" },
189
    { 0xD0C6,                               "Job was automatically deleted as the jobs it referenced have been deleted" },
190
    { 0xD0C7,                               "The job was automatically deleted because STOP mode was exited" },
191
    { 0xD0C8,                               "'Block status' aborted because of inconsistencies between test job and running program" },
192
    { 0xD0C9,                               "Exit the status area by resetting OB90" },
193
    { 0xD0CA,                               "Exiting the status range by resetting OB90 and access error reading tags before exiting" },
194
    { 0xD0CB,                               "The output disable for the peripheral outputs has been activated again" },
195
    { 0xD0CC,                               "The amount of data for the debugging functions is restricted by the time limit" },
196
    { 0xD201,                               "Syntax error in block name" },
197
    { 0xD202,                               "Syntax error in function parameters" },
198
    { 0xD205,                               "Linked block already exists in RAM: Conditional copying is not possible" },
199
    { 0xD206,                               "Linked block already exists in EPROM: Conditional copying is not possible" },
200
    { 0xD208,                               "Maximum number of copied (not linked) blocks on module exceeded" },
201
    { 0xD209,                               "(At least) one of the given blocks not found on the module" },
202
    { 0xD20A,                               "The maximum number of blocks that can be linked with one job was exceeded" },
203
    { 0xD20B,                               "The maximum number of blocks that can be deleted with one job was exceeded" },
204
    { 0xD20C,                               "OB cannot be copied because the associated priority class does not exist" },
205
    { 0xD20D,                               "SDB cannot be interpreted (for example, unknown number)" },
206
    { 0xD20E,                               "No (further) block available" },
207
    { 0xD20F,                               "Module-specific maximum block size exceeded" },
208
    { 0xD210,                               "Invalid block number" },
209
    { 0xD212,                               "Incorrect header attribute (run-time relevant)" },
210
    { 0xD213,                               "Too many SDBs. Note the restrictions on the module being used" },
211
    { 0xD216,                               "Invalid user program - reset module" },
212
    { 0xD217,                               "Protection level specified in module properties not permitted" },
213
    { 0xD218,                               "Incorrect attribute (active/passive)" },
214
    { 0xD219,                               "Incorrect block lengths (for example, incorrect length of first section or of the whole block)" },
215
    { 0xD21A,                               "Incorrect local data length or write-protection code faulty" },
216
    { 0xD21B,                               "Module cannot compress or compression was interrupted early" },
217
    { 0xD21D,                               "The volume of dynamic project data transferred is illegal" },
218
    { 0xD21E,                               "Unable to assign parameters to a module (such as FM, CP). The system data could not be linked" },
219
    { 0xD220,                               "Invalid programming language. Note the restrictions on the module being used" },
220
    { 0xD221,                               "The system data for connections or routing are not valid" },
221
    { 0xD222,                               "The system data of the global data definition contain invalid parameters" },
222
    { 0xD223,                               "Error in instance data block for communication function block or maximum number of instance DBs exceeded" },
223
    { 0xD224,                               "The SCAN system data block contains invalid parameters" },
224
    { 0xD225,                               "The DP system data block contains invalid parameters" },
225
    { 0xD226,                               "A structural error occurred in a block" },
226
    { 0xD230,                               "A structural error occurred in a block" },
227
    { 0xD231,                               "At least one loaded OB cannot be copied because the associated priority class does not exist" },
228
    { 0xD232,                               "At least one block number of a loaded block is illegal" },
229
    { 0xD234,                               "Block exists twice in the specified memory medium or in the job" },
230
    { 0xD235,                               "The block contains an incorrect checksum" },
231
    { 0xD236,                               "The block does not contain a checksum" },
232
    { 0xD237,                               "You are about to load the block twice, i.e. a block with the same time stamp already exists on the CPU" },
233
    { 0xD238,                               "At least one of the blocks specified is not a DB" },
234
    { 0xD239,                               "At least one of the DBs specified is not available as a linked variant in the load memory" },
235
    { 0xD23A,                               "At least one of the specified DBs is considerably different from the copied and linked variant" },
236
    { 0xD240,                               "Coordination rules violated" },
237
    { 0xD241,                               "The function is not permitted in the current protection level" },
238
    { 0xD242,                               "Protection violation while processing F blocks" },
239
    { 0xD250,                               "Update and module ID or version do not match" },
240
    { 0xD251,                               "Incorrect sequence of operating system components" },
241
    { 0xD252,                               "Checksum error" },
242
    { 0xD253,                               "No executable loader available; update only possible using a memory card" },
243
    { 0xD254,                               "Storage error in operating system" },
244
    { 0xD280,                               "Error compiling block in S7-300 CPU" },
245
    { 0xD2A1,                               "Another block function or a trigger on a block is active" },
246
    { 0xD2A2,                               "A trigger is active on a block. Complete the debugging function first" },
247
    { 0xD2A3,                               "The block is not active (linked), the block is occupied or the block is currently marked for deletion" },
248
    { 0xD2A4,                               "The block is already being processed by another block function" },
249
    { 0xD2A6,                               "It is not possible to save and change the user program simultaneously" },
250
    { 0xD2A7,                               "The block has the attribute 'unlinked' or is not processed" },
251
    { 0xD2A8,                               "An active debugging function is preventing parameters from being assigned to the CPU" },
252
    { 0xD2A9,                               "New parameters are being assigned to the CPU" },
253
    { 0xD2AA,                               "New parameters are currently being assigned to the modules" },
254
    { 0xD2AB,                               "The dynamic configuration limits are currently being changed" },
255
    { 0xD2AC,                               "A running active or deactivate assignment (SFC 12) is temporarily preventing R-KiR process" },
256
    { 0xD2B0,                               "An error occurred while configuring in RUN (CiR)" },
257
    { 0xD2C0,                               "The maximum number of technological objects has been exceeded" },
258
    { 0xD2C1,                               "The same technology data block already exists on the module" },
259
    { 0xD2C2,                               "Downloading the user program or downloading the hardware configuration is not possible" },
260
    { 0xD401,                               "Information function unavailable" },
261
    { 0xD402,                               "Information function unavailable" },
262
    { 0xD403,                               "Service has already been logged on/off (Diagnostics/PMC)" },
263
    { 0xD404,                               "Maximum number of nodes reached. No more logons possible for diagnostics/PMC" },
264
    { 0xD405,                               "Service not supported or syntax error in function parameters" },
265
    { 0xD406,                               "Required information currently unavailable" },
266
    { 0xD407,                               "Diagnostics error occurred" },
267
    { 0xD408,                               "Update aborted" },
268
    { 0xD409,                               "Error on DP bus" },
269
    { 0xD601,                               "Syntax error in function parameter" },
270
    { 0xD602,                               "Incorrect password entered" },
271
    { 0xD603,                               "The connection has already been legitimized" },
272
    { 0xD604,                               "The connection has already been enabled" },
273
    { 0xD605,                               "Legitimization not possible because password does not exist" },
274
    { 0xD801,                               "At least one tag address is invalid" },
275
    { 0xD802,                               "Specified job does not exist" },
276
    { 0xD803,                               "Illegal job status" },
277
    { 0xD804,                               "Illegal cycle time (illegal time base or multiple)" },
278
    { 0xD805,                               "No more cyclic read jobs can be set up" },
279
    { 0xD806,                               "The referenced job is in a state in which the requested function cannot be performed" },
280
    { 0xD807,                               "Function aborted due to overload, meaning executing the read cycle takes longer than the set scan cycle time" },
281
    { 0xDC01,                               "Date and/or time invalid" },
282
    { 0xE201,                               "CPU is already the master" },
283
    { 0xE202,                               "Connect and update not possible due to different user program in flash module" },
284
    { 0xE203,                               "Connect and update not possible due to different firmware" },
285
    { 0xE204,                               "Connect and update not possible due to different memory configuration" },
286
    { 0xE205,                               "Connect/update aborted due to synchronization error" },
287
    { 0xE206,                               "Connect/update denied due to coordination violation" },
288
    { 0xEF01,                               "S7 protocol error: Error at ID2; only 00H permitted in job" },
289
    { 0xEF02,                               "S7 protocol error: Error at ID2; set of resources does not exist" },
290
    { 0,                                    NULL }
291
};
292
static value_string_ext param_errcode_names_ext = VALUE_STRING_EXT_INIT(param_errcode_names);
293
294
/**************************************************************************
295
 * Function codes in parameter part
296
 */
297
#define S7COMM_SERV_CPU                     0x00
298
793
#define S7COMM_SERV_MODETRANS               0x01
299
0
#define S7COMM_SERV_SETUPCOMM               0xF0
300
7
#define S7COMM_SERV_READVAR                 0x04
301
16
#define S7COMM_SERV_WRITEVAR                0x05
302
303
0
#define S7COMM_FUNCREQUESTDOWNLOAD          0x1A
304
2
#define S7COMM_FUNCDOWNLOADBLOCK            0x1B
305
4
#define S7COMM_FUNCDOWNLOADENDED            0x1C
306
1
#define S7COMM_FUNCSTARTUPLOAD              0x1D
307
1
#define S7COMM_FUNCUPLOAD                   0x1E
308
10
#define S7COMM_FUNCENDUPLOAD                0x1F
309
0
#define S7COMM_FUNCPISERVICE                0x28
310
0
#define S7COMM_FUNC_PLC_STOP                0x29
311
312
4
#define S7COMM_FUNC_INVALID                 0xFF
313
314
static const value_string param_functionnames[] = {
315
    { S7COMM_SERV_CPU,                      "CPU services" },
316
    { S7COMM_SERV_MODETRANS,                "Mode transition" },
317
    { S7COMM_SERV_SETUPCOMM,                "Setup communication" },
318
    { S7COMM_SERV_READVAR,                  "Read Var" },
319
    { S7COMM_SERV_WRITEVAR,                 "Write Var" },
320
    /* Block management services */
321
    { S7COMM_FUNCREQUESTDOWNLOAD,           "Request download" },
322
    { S7COMM_FUNCDOWNLOADBLOCK,             "Download block" },
323
    { S7COMM_FUNCDOWNLOADENDED,             "Download ended" },
324
    { S7COMM_FUNCSTARTUPLOAD,               "Start upload" },
325
    { S7COMM_FUNCUPLOAD,                    "Upload" },
326
    { S7COMM_FUNCENDUPLOAD,                 "End upload" },
327
    { S7COMM_FUNCPISERVICE,                 "PI-Service" },
328
    { S7COMM_FUNC_PLC_STOP,                 "PLC Stop" },
329
    { 0,                                    NULL }
330
};
331
/**************************************************************************
332
 * Area names
333
 */
334
0
#define S7COMM_AREA_DATARECORD              0x01        /* Data record, used with RDREC or firmware updates on CP */
335
#define S7COMM_AREA_SYSINFO                 0x03        /* System info of 200 family */
336
#define S7COMM_AREA_SYSFLAGS                0x05        /* System flags of 200 family */
337
#define S7COMM_AREA_ANAIN                   0x06        /* analog inputs of 200 family */
338
#define S7COMM_AREA_ANAOUT                  0x07        /* analog outputs of 200 family */
339
#define S7COMM_AREA_P                       0x80        /* direct peripheral access */
340
#define S7COMM_AREA_INPUTS                  0x81
341
#define S7COMM_AREA_OUTPUTS                 0x82
342
#define S7COMM_AREA_FLAGS                   0x83
343
0
#define S7COMM_AREA_DB                      0x84        /* data blocks */
344
0
#define S7COMM_AREA_DI                      0x85        /* instance data blocks */
345
#define S7COMM_AREA_LOCAL                   0x86        /* local data (should not be accessible over network) */
346
#define S7COMM_AREA_V                       0x87        /* previous (Vorgaenger) local data (should not be accessible over network)  */
347
0
#define S7COMM_AREA_COUNTER                 28          /* S7 counters */
348
0
#define S7COMM_AREA_TIMER                   29          /* S7 timers */
349
#define S7COMM_AREA_COUNTER200              30          /* IEC counters (200 family) */
350
#define S7COMM_AREA_TIMER200                31          /* IEC timers (200 family) */
351
352
static const value_string item_areanames[] = {
353
    { S7COMM_AREA_DATARECORD,               "Data record" },
354
    { S7COMM_AREA_SYSINFO,                  "System info of 200 family" },
355
    { S7COMM_AREA_SYSFLAGS,                 "System flags of 200 family" },
356
    { S7COMM_AREA_ANAIN,                    "Analog inputs of 200 family" },
357
    { S7COMM_AREA_ANAOUT,                   "Analog outputs of 200 family" },
358
    { S7COMM_AREA_P,                        "Direct peripheral access (P)" },
359
    { S7COMM_AREA_INPUTS,                   "Inputs (I)" },
360
    { S7COMM_AREA_OUTPUTS,                  "Outputs (Q)" },
361
    { S7COMM_AREA_FLAGS,                    "Flags (M)" },
362
    { S7COMM_AREA_DB,                       "Data blocks (DB)" },
363
    { S7COMM_AREA_DI,                       "Instance data blocks (DI)" },
364
    { S7COMM_AREA_LOCAL,                    "Local data (L)" },
365
    { S7COMM_AREA_V,                        "Unknown yet (V)" },
366
    { S7COMM_AREA_COUNTER,                  "S7 counters (C)" },
367
    { S7COMM_AREA_TIMER,                    "S7 timers (T)" },
368
    { S7COMM_AREA_COUNTER200,               "IEC counters (200 family)" },
369
    { S7COMM_AREA_TIMER200,                 "IEC timers (200 family)" },
370
    { 0,                                    NULL }
371
};
372
373
static const value_string item_areanames_short[] = {
374
    { S7COMM_AREA_DATARECORD,               "RECORD" },
375
    { S7COMM_AREA_SYSINFO,                  "SI200" },
376
    { S7COMM_AREA_SYSFLAGS,                 "SF200" },
377
    { S7COMM_AREA_ANAIN,                    "AI200" },
378
    { S7COMM_AREA_ANAOUT,                   "AO" },
379
    { S7COMM_AREA_P,                        "P" },
380
    { S7COMM_AREA_INPUTS,                   "I" },
381
    { S7COMM_AREA_OUTPUTS,                  "Q" },
382
    { S7COMM_AREA_FLAGS,                    "M" },
383
    { S7COMM_AREA_DB,                       "DB" },
384
    { S7COMM_AREA_DI,                       "DI" },
385
    { S7COMM_AREA_LOCAL,                    "L" },
386
    { S7COMM_AREA_V,                        "V" },
387
    { S7COMM_AREA_COUNTER,                  "C" },
388
    { S7COMM_AREA_TIMER,                    "T" },
389
    { S7COMM_AREA_COUNTER200,               "C200" },
390
    { S7COMM_AREA_TIMER200,                 "T200" },
391
    { 0,                                    NULL }
392
};
393
/**************************************************************************
394
 * Transport sizes in item data
395
 */
396
    /* types of 1 byte length */
397
#define S7COMM_TRANSPORT_SIZE_BIT           1
398
#define S7COMM_TRANSPORT_SIZE_BYTE          2
399
#define S7COMM_TRANSPORT_SIZE_CHAR          3
400
    /* types of 2 bytes length */
401
#define S7COMM_TRANSPORT_SIZE_WORD          4
402
#define S7COMM_TRANSPORT_SIZE_INT           5
403
    /* types of 4 bytes length */
404
#define S7COMM_TRANSPORT_SIZE_DWORD         6
405
#define S7COMM_TRANSPORT_SIZE_DINT          7
406
#define S7COMM_TRANSPORT_SIZE_REAL          8
407
    /* Special types */
408
#define S7COMM_TRANSPORT_SIZE_DATE          9
409
#define S7COMM_TRANSPORT_SIZE_TOD           10
410
#define S7COMM_TRANSPORT_SIZE_TIME          11
411
#define S7COMM_TRANSPORT_SIZE_S5TIME        12
412
#define S7COMM_TRANSPORT_SIZE_DT            15
413
    /* Timer or counter */
414
#define S7COMM_TRANSPORT_SIZE_COUNTER       28
415
#define S7COMM_TRANSPORT_SIZE_TIMER         29
416
#define S7COMM_TRANSPORT_SIZE_IEC_COUNTER   30
417
#define S7COMM_TRANSPORT_SIZE_IEC_TIMER     31
418
#define S7COMM_TRANSPORT_SIZE_HS_COUNTER    32
419
static const value_string item_transportsizenames[] = {
420
    { S7COMM_TRANSPORT_SIZE_BIT,            "BIT" },
421
    { S7COMM_TRANSPORT_SIZE_BYTE,           "BYTE" },
422
    { S7COMM_TRANSPORT_SIZE_CHAR,           "CHAR" },
423
    { S7COMM_TRANSPORT_SIZE_WORD,           "WORD" },
424
    { S7COMM_TRANSPORT_SIZE_INT,            "INT" },
425
    { S7COMM_TRANSPORT_SIZE_DWORD,          "DWORD" },
426
    { S7COMM_TRANSPORT_SIZE_DINT,           "DINT" },
427
    { S7COMM_TRANSPORT_SIZE_REAL,           "REAL" },
428
    { S7COMM_TRANSPORT_SIZE_TOD,            "TOD" },
429
    { S7COMM_TRANSPORT_SIZE_TIME,           "TIME" },
430
    { S7COMM_TRANSPORT_SIZE_S5TIME,         "S5TIME" },
431
    { S7COMM_TRANSPORT_SIZE_DT,             "DATE_AND_TIME" },
432
    { S7COMM_TRANSPORT_SIZE_COUNTER,        "COUNTER" },
433
    { S7COMM_TRANSPORT_SIZE_TIMER,          "TIMER" },
434
    { S7COMM_TRANSPORT_SIZE_IEC_COUNTER,    "IEC TIMER" },
435
    { S7COMM_TRANSPORT_SIZE_IEC_TIMER,      "IEC COUNTER" },
436
    { S7COMM_TRANSPORT_SIZE_HS_COUNTER,     "HS COUNTER" },
437
    { 0,                                    NULL }
438
};
439
440
/**************************************************************************
441
 * Syntax Ids of variable specification
442
 */
443
0
#define S7COMM_SYNTAXID_S7ANY               0x10        /* Address data S7-Any pointer-like DB1.DBX10.2 */
444
#define S7COMM_SYNTAXID_SHORT               0x11
445
762
#define S7COMM_SYNTAXID_EXT                 0x12
446
788
#define S7COMM_SYNTAXID_PBC_ID              0x13        /* R_ID for PBC */
447
0
#define S7COMM_SYNTAXID_ALARM_LOCKFREESET   0x15        /* Alarm lock/free dataset */
448
0
#define S7COMM_SYNTAXID_ALARM_INDSET        0x16        /* Alarm indication dataset */
449
0
#define S7COMM_SYNTAXID_ALARM_ACKSET        0x19        /* Alarm acknowledge message dataset */
450
0
#define S7COMM_SYNTAXID_ALARM_QUERYREQSET   0x1a        /* Alarm query request dataset */
451
0
#define S7COMM_SYNTAXID_NOTIFY_INDSET       0x1c        /* Notify indication dataset */
452
0
#define S7COMM_SYNTAXID_NCK                 0x82        /* Sinumerik NCK HMI access (current units) */
453
0
#define S7COMM_SYNTAXID_NCK_METRIC          0x83        /* Sinumerik NCK HMI access metric units */
454
0
#define S7COMM_SYNTAXID_NCK_INCH            0x84        /* Sinumerik NCK HMI access inch */
455
0
#define S7COMM_SYNTAXID_DRIVEESANY          0xa2        /* seen on Drive ES Starter with routing over S7 */
456
0
#define S7COMM_SYNTAXID_1200SYM             0xb2        /* Symbolic address mode of S7-1200 */
457
0
#define S7COMM_SYNTAXID_DBREAD              0xb0        /* Kind of DB block read, seen only at an S7-400 */
458
459
static const value_string item_syntaxid_names[] = {
460
    { S7COMM_SYNTAXID_S7ANY,                "S7ANY" },
461
    { S7COMM_SYNTAXID_SHORT,                "ParameterShort" },
462
    { S7COMM_SYNTAXID_EXT,                  "ParameterExtended" },
463
    { S7COMM_SYNTAXID_PBC_ID,               "PBC-R_ID" },
464
    { S7COMM_SYNTAXID_ALARM_LOCKFREESET,    "ALARM_LOCKFREE" },
465
    { S7COMM_SYNTAXID_ALARM_INDSET,         "ALARM_IND" },
466
    { S7COMM_SYNTAXID_ALARM_ACKSET,         "ALARM_ACK" },
467
    { S7COMM_SYNTAXID_ALARM_QUERYREQSET,    "ALARM_QUERYREQ" },
468
    { S7COMM_SYNTAXID_NOTIFY_INDSET,        "NOTIFY_IND" },
469
    { S7COMM_SYNTAXID_NCK,                  "NCK" },
470
    { S7COMM_SYNTAXID_NCK_METRIC,           "NCK_M" },
471
    { S7COMM_SYNTAXID_NCK_INCH,             "NCK_I" },
472
    { S7COMM_SYNTAXID_DRIVEESANY,           "DRIVEESANY" },
473
    { S7COMM_SYNTAXID_1200SYM,              "1200SYM" },
474
    { S7COMM_SYNTAXID_DBREAD,               "DBREAD" },
475
    { 0,                                    NULL }
476
};
477
478
/**************************************************************************
479
 * Transport sizes in data
480
 */
481
0
#define S7COMM_DATA_TRANSPORT_SIZE_NULL     0
482
254
#define S7COMM_DATA_TRANSPORT_SIZE_BBIT     3           /* bit access, len is in bits */
483
550
#define S7COMM_DATA_TRANSPORT_SIZE_BBYTE    4           /* byte/word/dword access, len is in bits */
484
267
#define S7COMM_DATA_TRANSPORT_SIZE_BINT     5           /* integer access, len is in bits */
485
#define S7COMM_DATA_TRANSPORT_SIZE_BDINT    6           /* integer access, len is in bytes */
486
#define S7COMM_DATA_TRANSPORT_SIZE_BREAL    7           /* real access, len is in bytes */
487
#define S7COMM_DATA_TRANSPORT_SIZE_BSTR     9           /* octet string, len is in bytes */
488
56
#define S7COMM_DATA_TRANSPORT_SIZE_NCKADDR1 17          /* NCK address description, fixed length */
489
28
#define S7COMM_DATA_TRANSPORT_SIZE_NCKADDR2 18          /* NCK address description, fixed length */
490
491
static const value_string data_transportsizenames[] = {
492
    { S7COMM_DATA_TRANSPORT_SIZE_NULL,      "NULL" },
493
    { S7COMM_DATA_TRANSPORT_SIZE_BBIT,      "BIT" },
494
    { S7COMM_DATA_TRANSPORT_SIZE_BBYTE,     "BYTE/WORD/DWORD" },
495
    { S7COMM_DATA_TRANSPORT_SIZE_BINT,      "INTEGER" },
496
    { S7COMM_DATA_TRANSPORT_SIZE_BDINT,     "DINTEGER" },
497
    { S7COMM_DATA_TRANSPORT_SIZE_BREAL,     "REAL" },
498
    { S7COMM_DATA_TRANSPORT_SIZE_BSTR,      "OCTET STRING" },
499
    { S7COMM_DATA_TRANSPORT_SIZE_NCKADDR1,  "NCK ADDRESS1" },
500
    { S7COMM_DATA_TRANSPORT_SIZE_NCKADDR2,  "NCK ADDRESS2" },
501
    { 0,                                    NULL }
502
};
503
/**************************************************************************
504
 * Returnvalues of an item response
505
 */
506
507
const value_string s7comm_item_return_valuenames[] = {
508
    { S7COMM_ITEM_RETVAL_RESERVED,              "Reserved" },
509
    { S7COMM_ITEM_RETVAL_DATA_HW_FAULT,         "Hardware error" },
510
    { S7COMM_ITEM_RETVAL_DATA_ACCESS_FAULT,     "Accessing the object not allowed" },
511
    { S7COMM_ITEM_RETVAL_DATA_OUTOFRANGE,       "Invalid address" },
512
    { S7COMM_ITEM_RETVAL_DATA_NOT_SUP,          "Data type not supported" },
513
    { S7COMM_ITEM_RETVAL_DATA_SIZEMISMATCH,     "Data type inconsistent" },
514
    { S7COMM_ITEM_RETVAL_DATA_ERR,              "Object does not exist" },
515
    { S7COMM_ITEM_RETVAL_DATA_OK,               "Success" },
516
    { 0,                                        NULL }
517
};
518
/**************************************************************************
519
 * Block Types, used when blocktype is transferred as string
520
 */
521
0
#define S7COMM_BLOCKTYPE_OB                 0x3038      /* '08' */
522
#define S7COMM_BLOCKTYPE_CMOD               0x3039      /* '09' */
523
#define S7COMM_BLOCKTYPE_DB                 0x3041      /* '0A' */
524
#define S7COMM_BLOCKTYPE_SDB                0x3042      /* '0B' */
525
#define S7COMM_BLOCKTYPE_FC                 0x3043      /* '0C' */
526
#define S7COMM_BLOCKTYPE_SFC                0x3044      /* '0D' */
527
#define S7COMM_BLOCKTYPE_FB                 0x3045      /* '0E' */
528
0
#define S7COMM_BLOCKTYPE_SFB                0x3046      /* '0F' */
529
530
static const value_string blocktype_names[] = {
531
    { S7COMM_BLOCKTYPE_OB,                  "OB" },
532
    { S7COMM_BLOCKTYPE_CMOD,                "CMod" },
533
    { S7COMM_BLOCKTYPE_DB,                  "DB" },
534
    { S7COMM_BLOCKTYPE_SDB,                 "SDB" },
535
    { S7COMM_BLOCKTYPE_FC,                  "FC" },
536
    { S7COMM_BLOCKTYPE_SFC,                 "SFC" },
537
    { S7COMM_BLOCKTYPE_FB,                  "FB" },
538
    { S7COMM_BLOCKTYPE_SFB,                 "SFB" },
539
    { 0,                                    NULL }
540
};
541
542
543
static const value_string blocktype_attribute1_names[] = {
544
    { '_',                                  "Complete Module" },
545
    { '$',                                  "Module header for up-loading" },
546
    { 0,                                    NULL }
547
};
548
549
static const value_string blocktype_attribute2_names[] = {
550
    { 'P',                                  "Passive (copied, but not chained) module" },
551
    { 'A',                                  "Active embedded module" },
552
    { 'B',                                  "Active as well as passive module" },
553
    { 0,                                    NULL }
554
};
555
556
/**************************************************************************
557
 * Subblk types
558
 */
559
#define S7COMM_SUBBLKTYPE_NONE              0x00
560
133
#define S7COMM_SUBBLKTYPE_OB                0x08
561
#define S7COMM_SUBBLKTYPE_DB                0x0a
562
#define S7COMM_SUBBLKTYPE_SDB               0x0b
563
#define S7COMM_SUBBLKTYPE_FC                0x0c
564
#define S7COMM_SUBBLKTYPE_SFC               0x0d
565
#define S7COMM_SUBBLKTYPE_FB                0x0e
566
#define S7COMM_SUBBLKTYPE_SFB               0x0f
567
568
static const value_string subblktype_names[] = {
569
    { S7COMM_SUBBLKTYPE_NONE,               "Not set" },
570
    { S7COMM_SUBBLKTYPE_OB,                 "OB" },
571
    { S7COMM_SUBBLKTYPE_DB,                 "DB" },
572
    { S7COMM_SUBBLKTYPE_SDB,                "SDB" },
573
    { S7COMM_SUBBLKTYPE_FC,                 "FC" },
574
    { S7COMM_SUBBLKTYPE_SFC,                "SFC" },
575
    { S7COMM_SUBBLKTYPE_FB,                 "FB" },
576
    { S7COMM_SUBBLKTYPE_SFB,                "SFB" },
577
    { 0,                                    NULL }
578
};
579
580
/**************************************************************************
581
 * Block security
582
 */
583
#define S7COMM_BLOCKSECURITY_OFF            0
584
#define S7COMM_BLOCKSECURITY_KNOWHOWPROTECT 3
585
586
static const value_string blocksecurity_names[] = {
587
    { S7COMM_BLOCKSECURITY_OFF,             "None" },
588
    { S7COMM_BLOCKSECURITY_KNOWHOWPROTECT,  "Know How Protect" },
589
    { 0,                                    NULL }
590
};
591
/**************************************************************************
592
 * Block Languages
593
 */
594
static const value_string blocklanguage_names[] = {
595
    { 0x00,                                 "Not defined" },
596
    { 0x01,                                 "AWL" },
597
    { 0x02,                                 "KOP" },
598
    { 0x03,                                 "FUP" },
599
    { 0x04,                                 "SCL" },
600
    { 0x05,                                 "DB" },
601
    { 0x06,                                 "GRAPH" },
602
    { 0x07,                                 "SDB" },
603
    { 0x08,                                 "CPU-DB" },                     /* DB was created from Plc programm (CREAT_DB) */
604
    { 0x11,                                 "SDB (after overall reset)" },  /* another SDB, don't know what it means, in SDB 1 and SDB 2, uncertain*/
605
    { 0x12,                                 "SDB (Routing)" },              /* another SDB, in SDB 999 and SDB 1000 (routing information), uncertain */
606
    { 0x29,                                 "ENCRYPT" },                    /* block is encrypted with S7-Block-Privacy */
607
    { 0,                                    NULL }
608
};
609
610
/**************************************************************************
611
 * Names of types in userdata parameter part
612
 */
613
614
static const value_string userdata_type_names[] = {
615
    { S7COMM_UD_TYPE_IND,                   "Indication" },
616
    { S7COMM_UD_TYPE_REQ,                   "Request" },
617
    { S7COMM_UD_TYPE_RES,                   "Response" },
618
    { 0,                                    NULL }
619
};
620
621
/**************************************************************************
622
 * Subfunctions only used in Sinumerik NC file download
623
 */
624
51
#define S7COMM_NCPRG_FUNCREQUESTDOWNLOAD    1
625
132
#define S7COMM_NCPRG_FUNCDOWNLOADBLOCK      2
626
23
#define S7COMM_NCPRG_FUNCCONTDOWNLOAD       3
627
#define S7COMM_NCPRG_FUNCDOWNLOADENDED      4
628
121
#define S7COMM_NCPRG_FUNCSTARTUPLOAD        6
629
92
#define S7COMM_NCPRG_FUNCUPLOAD             7
630
46
#define S7COMM_NCPRG_FUNCCONTUPLOAD         8
631
632
static const value_string userdata_ncprg_subfunc_names[] = {
633
    { S7COMM_NCPRG_FUNCREQUESTDOWNLOAD,     "Request download" },
634
    { S7COMM_NCPRG_FUNCDOWNLOADBLOCK,       "Download block" },
635
    { S7COMM_NCPRG_FUNCCONTDOWNLOAD,        "Continue download" },
636
    { S7COMM_NCPRG_FUNCDOWNLOADENDED,       "Download ended" },
637
    { S7COMM_NCPRG_FUNCSTARTUPLOAD,         "Start upload" },
638
    { S7COMM_NCPRG_FUNCUPLOAD,              "Upload" },
639
    { S7COMM_NCPRG_FUNCCONTUPLOAD,          "Continue upload" },
640
    { 0,                                    NULL }
641
};
642
643
/**************************************************************************
644
 * Subfunctions for Data Record Routing to Profibus
645
 */
646
#define S7COMM_DRR_FUNCINIT                 1
647
#define S7COMM_DRR_FUNCFINISH               2
648
#define S7COMM_DRR_FUNCDATA                 3
649
650
static const value_string userdata_drr_subfunc_names[] = {
651
    { S7COMM_DRR_FUNCINIT,                  "DRR Init" },
652
    { S7COMM_DRR_FUNCFINISH,                "DRR Finish" },
653
    { S7COMM_DRR_FUNCDATA,                  "DRR Data" },
654
    { 0,                                    NULL }
655
};
656
657
/**************************************************************************
658
 * Userdata Parameter, last data unit
659
 */
660
1.28k
#define S7COMM_UD_LASTDATAUNIT_YES          0x00
661
643
#define S7COMM_UD_LASTDATAUNIT_NO           0x01
662
663
static const value_string userdata_lastdataunit_names[] = {
664
    { S7COMM_UD_LASTDATAUNIT_YES,           "Yes" },
665
    { S7COMM_UD_LASTDATAUNIT_NO,            "No" },
666
    { 0,                                    NULL }
667
};
668
669
/**************************************************************************
670
 * Names of Function groups in userdata parameter part
671
 */
672
599
#define S7COMM_UD_FUNCGROUP_TIS             0x01
673
90
#define S7COMM_UD_FUNCGROUP_CYCLIC          0x02
674
20
#define S7COMM_UD_FUNCGROUP_BLOCK           0x03
675
392
#define S7COMM_UD_FUNCGROUP_CPU             0x04
676
8
#define S7COMM_UD_FUNCGROUP_SEC             0x05                    /* Security functions e.g. plc password */
677
88
#define S7COMM_UD_FUNCGROUP_PBC_BSEND       0x06                    /* PBC = Programmable Block Communication (PBK in german) */
678
18
#define S7COMM_UD_FUNCGROUP_TIME            0x07
679
306
#define S7COMM_UD_FUNCGROUP_NCPRG           0x3f
680
11
#define S7COMM_UD_FUNCGROUP_DRR             0x20
681
682
static const value_string userdata_functiongroup_names[] = {
683
    { S7COMM_UD_FUNCGROUP_TIS,              "Programmer commands" },
684
    { S7COMM_UD_FUNCGROUP_CYCLIC,           "Cyclic services" },    /* to read data from plc without a request */
685
    { S7COMM_UD_FUNCGROUP_BLOCK,            "Block functions" },
686
    { S7COMM_UD_FUNCGROUP_CPU,              "CPU functions" },
687
    { S7COMM_UD_FUNCGROUP_SEC,              "Security" },
688
    { S7COMM_UD_FUNCGROUP_PBC_BSEND,        "PBC BSEND" },
689
    { S7COMM_UD_FUNCGROUP_TIME,             "Time functions" },
690
    { S7COMM_UD_FUNCGROUP_NCPRG,            "NC programming" },
691
    { S7COMM_UD_FUNCGROUP_DRR,              "DR Routing" },
692
    { 0,                                    NULL }
693
};
694
695
/**************************************************************************
696
 * Variable status: Area of data request
697
 *
698
 * Low       Hi
699
 * 0=M       0=BOOL
700
 * 1=E       1=BYTE
701
 * 2=A       2=WORD
702
 * 3=PEx     3=DWORD
703
 * 7=DB
704
 * 54=TIMER
705
 * 64=COUNTER
706
 */
707
889
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MX      0x00
708
139
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MB      0x01
709
121
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MW      0x02
710
116
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MD      0x03
711
36
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EX      0x10
712
15
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EB      0x11
713
139
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EW      0x12
714
21
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_ED      0x13
715
49
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AX      0x20
716
38
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AB      0x21
717
4
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AW      0x22
718
43
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AD      0x23
719
103
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PEB     0x31
720
104
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PEW     0x32
721
106
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PED     0x33
722
55
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBX     0x70
723
19
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBB     0x71
724
57
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBW     0x72
725
11
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBD     0x73
726
63
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_T       0x54
727
37
#define S7COMM_UD_SUBF_TIS_VARSTAT_AREA_C       0x64
728
729
static const value_string userdata_tis_varstat_area_names[] = {
730
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MX,       "MX" },
731
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MB,       "MB" },
732
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MW,       "MW" },
733
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MD,       "MD" },
734
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EB,       "IB" },
735
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EX,       "IX" },
736
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EW,       "IW" },
737
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_ED,       "ID" },
738
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AX,       "QX" },
739
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AB,       "QB" },
740
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AW,       "QW" },
741
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AD,       "QD" },
742
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PEB,      "PIB" },
743
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PEW,      "PIW" },
744
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PED,      "PID" },
745
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBX,      "DBX" },
746
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBB,      "DBB" },
747
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBW,      "DBW" },
748
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBD,      "DBD" },
749
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_T,        "TIMER" },
750
    { S7COMM_UD_SUBF_TIS_VARSTAT_AREA_C,        "COUNTER" },
751
    { 0,                                        NULL }
752
};
753
754
/**************************************************************************
755
 * Names of userdata subfunctions in group 1 (Programmer commands)
756
 * In szl dataset 0x0132/2 these are defined as "Test and installation functions TIS".
757
 * The methods supported by the CPU are listed in the funkt_n bits.
758
 */
759
33
#define S7COMM_UD_SUBF_TIS_BLOCKSTAT        0x01
760
40
#define S7COMM_UD_SUBF_TIS_VARSTAT          0x02
761
2
#define S7COMM_UD_SUBF_TIS_OUTISTACK        0x03
762
9
#define S7COMM_UD_SUBF_TIS_OUTBSTACK        0x04
763
0
#define S7COMM_UD_SUBF_TIS_OUTLSTACK        0x05
764
#define S7COMM_UD_SUBF_TIS_TIMEMEAS         0x06
765
#define S7COMM_UD_SUBF_TIS_FORCESEL         0x07
766
18
#define S7COMM_UD_SUBF_TIS_MODVAR           0x08
767
97
#define S7COMM_UD_SUBF_TIS_FORCE            0x09
768
0
#define S7COMM_UD_SUBF_TIS_BREAKPOINT       0x0a
769
9
#define S7COMM_UD_SUBF_TIS_EXITHOLD         0x0b
770
#define S7COMM_UD_SUBF_TIS_MEMORYRES        0x0c
771
2
#define S7COMM_UD_SUBF_TIS_DISABLEJOB       0x0d
772
1
#define S7COMM_UD_SUBF_TIS_ENABLEJOB        0x0e
773
1
#define S7COMM_UD_SUBF_TIS_DELETEJOB        0x0f
774
1
#define S7COMM_UD_SUBF_TIS_READJOBLIST      0x10
775
26
#define S7COMM_UD_SUBF_TIS_READJOB          0x11
776
39
#define S7COMM_UD_SUBF_TIS_REPLACEJOB       0x12
777
3.29k
#define S7COMM_UD_SUBF_TIS_BLOCKSTAT2       0x13
778
#define S7COMM_UD_SUBF_TIS_FLASHLED         0x16
779
780
static const value_string userdata_tis_subfunc_names[] = {
781
    { S7COMM_UD_SUBF_TIS_BLOCKSTAT,         "Block status" },
782
    { S7COMM_UD_SUBF_TIS_VARSTAT,           "Variable status" },
783
    { S7COMM_UD_SUBF_TIS_OUTISTACK,         "Output ISTACK" },
784
    { S7COMM_UD_SUBF_TIS_OUTBSTACK,         "Output BSTACK" },
785
    { S7COMM_UD_SUBF_TIS_OUTLSTACK,         "Output LSTACK" },
786
    { S7COMM_UD_SUBF_TIS_TIMEMEAS,          "Time measurement from to" },       /* never seen yet */
787
    { S7COMM_UD_SUBF_TIS_FORCESEL,          "Force selection" },
788
    { S7COMM_UD_SUBF_TIS_MODVAR,            "Modify variable" },
789
    { S7COMM_UD_SUBF_TIS_FORCE,             "Force" },
790
    { S7COMM_UD_SUBF_TIS_BREAKPOINT,        "Breakpoint" },
791
    { S7COMM_UD_SUBF_TIS_EXITHOLD,          "Exit HOLD" },
792
    { S7COMM_UD_SUBF_TIS_MEMORYRES,         "Memory reset" },
793
    { S7COMM_UD_SUBF_TIS_DISABLEJOB,        "Disable job" },
794
    { S7COMM_UD_SUBF_TIS_ENABLEJOB,         "Enable job" },
795
    { S7COMM_UD_SUBF_TIS_DELETEJOB,         "Delete job" },
796
    { S7COMM_UD_SUBF_TIS_READJOBLIST,       "Read job list" },
797
    { S7COMM_UD_SUBF_TIS_READJOB,           "Read job" },
798
    { S7COMM_UD_SUBF_TIS_REPLACEJOB,        "Replace job" },
799
    { S7COMM_UD_SUBF_TIS_BLOCKSTAT2,        "Block status v2" },
800
    { S7COMM_UD_SUBF_TIS_FLASHLED,          "Flash LED" },
801
    { 0,                                    NULL }
802
};
803
804
/**************************************************************************
805
 * Variable status: Trigger point
806
 */
807
static const value_string userdata_varstat_trgevent_names[] = {
808
    { 0x0000,                               "Immediately" },
809
    { 0x0100,                               "System Trigger" },
810
    { 0x0200,                               "System checkpoint main cycle start" },
811
    { 0x0300,                               "System checkpoint main cycle end" },
812
    { 0x0400,                               "Mode transition RUN-STOP" },
813
    { 0x0500,                               "After code address" },
814
    { 0x0600,                               "Code address area" },
815
    { 0x0601,                               "Code address area with call environment" },  /* Call conditions like opened DB/DI or called block */
816
    { 0x0700,                               "Data address" },
817
    { 0x0800,                               "Data address area" },
818
    { 0x0900,                               "Local data address" },
819
    { 0x0a00,                               "Local data address area" },
820
    { 0x0b00,                               "Range trigger" },
821
    { 0x0c00,                               "Before code address" },
822
    { 0,                                    NULL }
823
};
824
825
/**************************************************************************
826
 * Names of userdata subfunctions in group 2 (cyclic data)
827
 */
828
27
#define S7COMM_UD_SUBF_CYCLIC_TRANSF        0x01
829
0
#define S7COMM_UD_SUBF_CYCLIC_UNSUBSCRIBE   0x04
830
27
#define S7COMM_UD_SUBF_CYCLIC_CHANGE        0x05
831
0
#define S7COMM_UD_SUBF_CYCLIC_CHANGE_MOD    0x07
832
0
#define S7COMM_UD_SUBF_CYCLIC_RDREC         0x08
833
834
static const value_string userdata_cyclic_subfunc_names[] = {
835
    { S7COMM_UD_SUBF_CYCLIC_TRANSF,         "Cyclic transfer" },
836
    { S7COMM_UD_SUBF_CYCLIC_UNSUBSCRIBE,    "Unsubscribe" },
837
    { S7COMM_UD_SUBF_CYCLIC_CHANGE,         "Change driven transfer" },
838
    { S7COMM_UD_SUBF_CYCLIC_CHANGE_MOD,     "Change driven transfer modify" },
839
    { S7COMM_UD_SUBF_CYCLIC_RDREC,          "RDREC" },
840
    { 0,                                    NULL }
841
};
842
843
/**************************************************************************
844
 * Timebase for cyclic services
845
 */
846
static const value_string cycl_interval_timebase_names[] = {
847
    { 0,                                    "100 milliseconds" },
848
    { 1,                                    "1 second" },
849
    { 2,                                    "10 seconds" },
850
    { 0,                                    NULL }
851
};
852
853
/**************************************************************************
854
 * Names of userdata subfunctions in group 3 (Block functions)
855
 */
856
0
#define S7COMM_UD_SUBF_BLOCK_LIST           0x01
857
0
#define S7COMM_UD_SUBF_BLOCK_LISTTYPE       0x02
858
4
#define S7COMM_UD_SUBF_BLOCK_BLOCKINFO      0x03
859
860
static const value_string userdata_block_subfunc_names[] = {
861
    { S7COMM_UD_SUBF_BLOCK_LIST,            "List blocks" },
862
    { S7COMM_UD_SUBF_BLOCK_LISTTYPE,        "List blocks of type" },
863
    { S7COMM_UD_SUBF_BLOCK_BLOCKINFO,       "Get block info" },
864
    { 0,                                    NULL }
865
};
866
867
/**************************************************************************
868
 * Names of userdata subfunctions in group 4 (CPU functions)
869
 */
870
58
#define S7COMM_UD_SUBF_CPU_SCAN_IND         0x09
871
130
#define S7COMM_UD_SUBF_CPU_AR_SEND_IND      0x10
872
873
static const value_string userdata_cpu_subfunc_names[] = {
874
    { S7COMM_UD_SUBF_CPU_READSZL,           "Read SZL" },
875
    { S7COMM_UD_SUBF_CPU_MSGS,              "Message service" },                /* Header constant is also different here */
876
    { S7COMM_UD_SUBF_CPU_DIAGMSG,           "Diagnostic message" },             /* Diagnostic message from PLC */
877
    { S7COMM_UD_SUBF_CPU_ALARM8_IND,        "ALARM_8 indication" },             /* PLC is indicating an ALARM message, using ALARM_8 SFBs */
878
    { S7COMM_UD_SUBF_CPU_NOTIFY_IND,        "NOTIFY indication" },              /* PLC is indicating a NOTIFY message, using NOTIFY SFBs */
879
    { S7COMM_UD_SUBF_CPU_ALARM8LOCK,        "ALARM_8 lock" },                   /* Lock an ALARM message from HMI/SCADA */
880
    { S7COMM_UD_SUBF_CPU_ALARM8UNLOCK,      "ALARM_8 unlock" },                 /* Unlock an ALARM message from HMI/SCADA */
881
    { S7COMM_UD_SUBF_CPU_SCAN_IND,          "SCAN indication" },                /* PLC is indicating a SCAN message */
882
    { S7COMM_UD_SUBF_CPU_AR_SEND_IND,       "AR_SEND indication" },             /* PLC is indicating a AR_SEND message */
883
    { S7COMM_UD_SUBF_CPU_ALARMS_IND,        "ALARM_S indication" },             /* PLC is indicating an ALARM message, using ALARM_S/ALARM_D SFCs */
884
    { S7COMM_UD_SUBF_CPU_ALARMSQ_IND,       "ALARM_SQ indication" },            /* PLC is indicating an ALARM message, using ALARM_SQ/ALARM_DQ SFCs */
885
    { S7COMM_UD_SUBF_CPU_ALARMQUERY,        "ALARM query" },                    /* HMI/SCADA query of ALARMs */
886
    { S7COMM_UD_SUBF_CPU_ALARMACK,          "ALARM ack" },                      /* Alarm was acknowledged in HMI/SCADA */
887
    { S7COMM_UD_SUBF_CPU_ALARMACK_IND,      "ALARM ack indication" },           /* Alarm acknowledge indication from CPU to HMI */
888
    { S7COMM_UD_SUBF_CPU_ALARM8LOCK_IND,    "ALARM lock indication" },          /* Alarm lock indication from CPU to HMI */
889
    { S7COMM_UD_SUBF_CPU_ALARM8UNLOCK_IND,  "ALARM unlock indication" },        /* Alarm unlock indication from CPU to HMI */
890
    { S7COMM_UD_SUBF_CPU_NOTIFY8_IND,       "NOTIFY_8 indication" },
891
    { 0,                                    NULL }
892
};
893
894
/**************************************************************************
895
 * Names of userdata subfunctions in group 5 (Security?)
896
 */
897
#define S7COMM_UD_SUBF_SEC_PASSWD           0x01
898
899
static const value_string userdata_sec_subfunc_names[] = {
900
    { S7COMM_UD_SUBF_SEC_PASSWD,            "PLC password" },
901
    { 0,                                    NULL }
902
};
903
904
/**************************************************************************
905
 * Names of userdata subfunctions in group 7 (Time functions)
906
 */
907
4
#define S7COMM_UD_SUBF_TIME_READ            0x01
908
0
#define S7COMM_UD_SUBF_TIME_SET             0x02
909
4
#define S7COMM_UD_SUBF_TIME_READF           0x03
910
0
#define S7COMM_UD_SUBF_TIME_SET2            0x04
911
912
static const value_string userdata_time_subfunc_names[] = {
913
    { S7COMM_UD_SUBF_TIME_READ,             "Read clock" },
914
    { S7COMM_UD_SUBF_TIME_SET,              "Set clock" },
915
    { S7COMM_UD_SUBF_TIME_READF,            "Read clock (following)" },
916
    { S7COMM_UD_SUBF_TIME_SET2,             "Set clock" },
917
    { 0,                                    NULL }
918
};
919
920
/*******************************************************************************************************
921
 * Weekday names in DATE_AND_TIME
922
 */
923
static const value_string weekdaynames[] = {
924
    { 0,                                    "Undefined" },
925
    { 1,                                    "Sunday" },
926
    { 2,                                    "Monday" },
927
    { 3,                                    "Tuesday" },
928
    { 4,                                    "Wednesday" },
929
    { 5,                                    "Thursday" },
930
    { 6,                                    "Friday" },
931
    { 7,                                    "Saturday" },
932
    { 0,                                    NULL }
933
};
934
935
/**************************************************************************
936
 **************************************************************************/
937
938
/**************************************************************************
939
 * Flags for LID access
940
 */
941
#define S7COMM_TIA1200_VAR_ENCAPS_LID       0x2
942
#define S7COMM_TIA1200_VAR_ENCAPS_IDX       0x3
943
#define S7COMM_TIA1200_VAR_OBTAIN_LID       0x4
944
#define S7COMM_TIA1200_VAR_OBTAIN_IDX       0x5
945
#define S7COMM_TIA1200_VAR_PART_START       0x6
946
#define S7COMM_TIA1200_VAR_PART_LEN         0x7
947
948
static const value_string tia1200_var_lid_flag_names[] = {
949
    { S7COMM_TIA1200_VAR_ENCAPS_LID,        "Encapsulated LID" },
950
    { S7COMM_TIA1200_VAR_ENCAPS_IDX,        "Encapsulated Index" },
951
    { S7COMM_TIA1200_VAR_OBTAIN_LID,        "Obtain by LID" },
952
    { S7COMM_TIA1200_VAR_OBTAIN_IDX,        "Obtain by Index" },
953
    { S7COMM_TIA1200_VAR_PART_START,        "Part Start Address" },
954
    { S7COMM_TIA1200_VAR_PART_LEN,          "Part Length" },
955
    { 0,                                    NULL }
956
};
957
958
/**************************************************************************
959
 * TIA 1200 Area Names for variable access
960
 */
961
0
#define S7COMM_TIA1200_VAR_ITEM_AREA1_DB    0x8a0e              /* Reading DB, 2 byte DB-Number following */
962
0
#define S7COMM_TIA1200_VAR_ITEM_AREA1_IQMCT 0x0000              /* Reading I/Q/M/C/T, 2 Byte detail area following */
963
964
static const value_string tia1200_var_item_area1_names[] = {
965
    { S7COMM_TIA1200_VAR_ITEM_AREA1_DB,     "DB" },
966
    { S7COMM_TIA1200_VAR_ITEM_AREA1_IQMCT,  "IQMCT" },
967
    { 0,                                    NULL }
968
};
969
970
#define S7COMM_TIA1200_VAR_ITEM_AREA2_I     0x50
971
#define S7COMM_TIA1200_VAR_ITEM_AREA2_Q     0x51
972
#define S7COMM_TIA1200_VAR_ITEM_AREA2_M     0x52
973
#define S7COMM_TIA1200_VAR_ITEM_AREA2_C     0x53
974
#define S7COMM_TIA1200_VAR_ITEM_AREA2_T     0x54
975
976
static const value_string tia1200_var_item_area2_names[] = {
977
    { S7COMM_TIA1200_VAR_ITEM_AREA2_I,      "Inputs (I)" },
978
    { S7COMM_TIA1200_VAR_ITEM_AREA2_Q,      "Outputs (Q)" },
979
    { S7COMM_TIA1200_VAR_ITEM_AREA2_M,      "Flags (M)" },
980
    { S7COMM_TIA1200_VAR_ITEM_AREA2_C,      "Counter (C)" },
981
    { S7COMM_TIA1200_VAR_ITEM_AREA2_T,      "Timer (T)" },
982
    { 0,                                    NULL }
983
};
984
985
/**************************************************************************
986
 * NCK areas
987
 */
988
#define S7COMM_NCK_AREA_N_NCK               0
989
#define S7COMM_NCK_AREA_B_MODEGROUP         1
990
#define S7COMM_NCK_AREA_C_CHANNEL           2
991
#define S7COMM_NCK_AREA_A_AXIS              3
992
#define S7COMM_NCK_AREA_T_TOOL              4
993
#define S7COMM_NCK_AREA_V_FEEDDRIVE         5
994
#define S7COMM_NCK_AREA_H_MAINDRIVE         6
995
#define S7COMM_NCK_AREA_M_MMC               7
996
997
static const value_string nck_area_names[] = {
998
    { S7COMM_NCK_AREA_N_NCK,                "N - NCK" },
999
    { S7COMM_NCK_AREA_B_MODEGROUP,          "B - Mode group" },
1000
    { S7COMM_NCK_AREA_C_CHANNEL,            "C - Channel" },
1001
    { S7COMM_NCK_AREA_A_AXIS,               "A - Axis" },
1002
    { S7COMM_NCK_AREA_T_TOOL,               "T - Tool" },
1003
    { S7COMM_NCK_AREA_V_FEEDDRIVE,          "V - Feed drive" },
1004
    { S7COMM_NCK_AREA_H_MAINDRIVE,          "M - Main drive" },
1005
    { S7COMM_NCK_AREA_M_MMC,                "M - MMC" },
1006
    { 0,                                    NULL }
1007
};
1008
1009
static const value_string nck_module_names[] = {
1010
    { 0x10,                                 "Y - Global system data" },
1011
    { 0x11,                                 "YNCFL - NCK instruction groups" },
1012
    { 0x12,                                 "FU - NCU global settable frames" },
1013
    { 0x13,                                 "FA - Active NCU global frames" },
1014
    { 0x14,                                 "TO - Tool data" },
1015
    { 0x15,                                 "RP - Arithmetic parameters" },
1016
    { 0x16,                                 "SE - Setting data" },
1017
    { 0x17,                                 "SGUD - SGUD-Block" },
1018
    { 0x18,                                 "LUD - Local userdata" },
1019
    { 0x19,                                 "TC - Toolholder parameters" },
1020
    { 0x1a,                                 "M - Machine data" },
1021
    { 0x1c,                                 "WAL - Working area limitation" },
1022
    { 0x1e,                                 "DIAG - Internal diagnostic data" },
1023
    { 0x1f,                                 "CC - Unknown" },
1024
    { 0x20,                                 "FE - Channel-specific external frame" },
1025
    { 0x21,                                 "TD - Tool data: General data" },
1026
    { 0x22,                                 "TS - Tool edge data: Monitoring data" },
1027
    { 0x23,                                 "TG - Tool data: Grinding-specific data" },
1028
    { 0x24,                                 "TU - Tool data" },
1029
    { 0x25,                                 "TUE - Tool edge data, userdefined data" },
1030
    { 0x26,                                 "TV - Tool data, directory" },
1031
    { 0x27,                                 "TM - Magazine data: General data" },
1032
    { 0x28,                                 "TP - Magazine data: Location data" },
1033
    { 0x29,                                 "TPM - Magazine data: Multiple assignment of location data" },
1034
    { 0x2a,                                 "TT - Magazine data: Location typ" },
1035
    { 0x2b,                                 "TMV - Magazine data: Directory" },
1036
    { 0x2c,                                 "TMC - Magazine data: Configuration data" },
1037
    { 0x2d,                                 "MGUD - MGUD-Block" },
1038
    { 0x2e,                                 "UGUD - UGUD-Block" },
1039
    { 0x2f,                                 "GUD4 - GUD4-Block" },
1040
    { 0x30,                                 "GUD5 - GUD5-Block" },
1041
    { 0x31,                                 "GUD6 - GUD6-Block" },
1042
    { 0x32,                                 "GUD7 - GUD7-Block" },
1043
    { 0x33,                                 "GUD8 - GUD8-Block" },
1044
    { 0x34,                                 "GUD9 - GUD9-Block" },
1045
    { 0x35,                                 "PA - Channel-specific protection zones" },
1046
    { 0x36,                                 "GD1 - SGUD-Block GD1" },
1047
    { 0x37,                                 "NIB - State data: Nibbling" },
1048
    { 0x38,                                 "ETP - Types of events" },
1049
    { 0x39,                                 "ETPD - Data lists for protocolling" },
1050
    { 0x3a,                                 "SYNACT - Channel-specific synchronous actions" },
1051
    { 0x3b,                                 "DIAGN - Diagnostic data" },
1052
    { 0x3c,                                 "VSYN - Channel-specific user variables for synchronous actions" },
1053
    { 0x3d,                                 "TUS - Tool data: user monitoring data" },
1054
    { 0x3e,                                 "TUM - Tool data: user magazine data" },
1055
    { 0x3f,                                 "TUP - Tool data: user magazine place data" },
1056
    { 0x40,                                 "TF - Parameterizing, return parameters of _N_TMGETT, _N_TSEARC" },
1057
    { 0x41,                                 "FB - Channel-specific base frames" },
1058
    { 0x42,                                 "SSP2 - State data: Spindle" },
1059
    { 0x43,                                 "PUD - programmglobale Benutzerdaten" },
1060
    { 0x44,                                 "TOS - Edge-related location-dependent fine total offsets" },
1061
    { 0x45,                                 "TOST - Edge-related location-dependent fine total offsets, transformed" },
1062
    { 0x46,                                 "TOE - Edge-related coarse total offsets, setup offsets" },
1063
    { 0x47,                                 "TOET - Edge-related coarse total offsets, transformed setup offsets" },
1064
    { 0x48,                                 "AD - Adapter data" },
1065
    { 0x49,                                 "TOT - Edge data: Transformed offset data" },
1066
    { 0x4a,                                 "AEV - Working offsets: Directory" },
1067
    { 0x4b,                                 "YFAFL - NCK instruction groups (Fanuc)" },
1068
    { 0x4c,                                 "FS - System-Frame" },
1069
    { 0x4d,                                 "SD - Servo data" },
1070
    { 0x4e,                                 "TAD - Application-specific data" },
1071
    { 0x4f,                                 "TAO - Application-specific cutting edge data" },
1072
    { 0x50,                                 "TAS - Application-specific monitoring data" },
1073
    { 0x51,                                 "TAM - Application-specific magazine data" },
1074
    { 0x52,                                 "TAP - Application-specific magazine location data" },
1075
    { 0x53,                                 "MEM - Unknown" },
1076
    { 0x54,                                 "SALUC - Alarm actions: List in reverse chronological order" },
1077
    { 0x55,                                 "AUXFU - Auxiliary functions" },
1078
    { 0x56,                                 "TDC - Tool/Tools" },
1079
    { 0x57,                                 "CP - Generic coupling" },
1080
    { 0x6e,                                 "SDME - Unknown" },
1081
    { 0x6f,                                 "SPARPI - Program pointer on interruption" },
1082
    { 0x70,                                 "SEGA - State data: Geometry axes in tool offset memory (extended)" },
1083
    { 0x71,                                 "SEMA - State data: Machine axes (extended)" },
1084
    { 0x72,                                 "SSP - State data: Spindle" },
1085
    { 0x73,                                 "SGA - State data: Geometry axes in tool offset memory" },
1086
    { 0x74,                                 "SMA - State data: Machine axes" },
1087
    { 0x75,                                 "SALAL - Alarms: List organized according to time" },
1088
    { 0x76,                                 "SALAP - Alarms: List organized according to priority" },
1089
    { 0x77,                                 "SALA - Alarms: List organized according to time" },
1090
    { 0x78,                                 "SSYNAC - Synchronous actions" },
1091
    { 0x79,                                 "SPARPF - Program pointers for block search and stop run" },
1092
    { 0x7a,                                 "SPARPP - Program pointer in automatic operation" },
1093
    { 0x7b,                                 "SNCF - Active G functions" },
1094
    { 0x7d,                                 "SPARP - Part program information" },
1095
    { 0x7e,                                 "SINF - Part-program-specific status data" },
1096
    { 0x7f,                                 "S - State data" },
1097
    { 0x80,                                 "0x80 - Unknown" },
1098
    { 0x81,                                 "0x81 - Unknown" },
1099
    { 0x82,                                 "0x82 - Unknown" },
1100
    { 0x83,                                 "0x83 - Unknown" },
1101
    { 0x84,                                 "0x84 - Unknown" },
1102
    { 0x85,                                 "0x85 - Unknown" },
1103
    { 0xfd,                                 "0 - Internal" },
1104
    { 0,                                    NULL }
1105
};
1106
static value_string_ext nck_module_names_ext = VALUE_STRING_EXT_INIT(nck_module_names);
1107
1108
static int hf_s7comm_tia1200_item_reserved1;          /* 1 Byte Reserved (always 0xff?) */
1109
static int hf_s7comm_tia1200_item_area1;              /* 2 Byte2 Root area (DB or IQMCT) */
1110
static int hf_s7comm_tia1200_item_area2;              /* 2 Bytes detail area (I/Q/M/C/T) */
1111
static int hf_s7comm_tia1200_item_area2unknown;       /* 2 Bytes detail area for possible unknown or not seen areas */
1112
static int hf_s7comm_tia1200_item_dbnumber;           /* 2 Bytes DB number */
1113
static int hf_s7comm_tia1200_item_crc;                /* 4 Bytes CRC */
1114
1115
static int hf_s7comm_tia1200_substructure_item;       /* Substructure */
1116
static int hf_s7comm_tia1200_var_lid_flags;           /* LID Flags */
1117
static int hf_s7comm_tia1200_item_value;
1118
1119
/**************************************************************************
1120
 **************************************************************************/
1121
1122
/* Header Block */
1123
static int hf_s7comm_header;
1124
static int hf_s7comm_header_protid;                   /* Header Byte  0 */
1125
static int hf_s7comm_header_rosctr;                   /* Header Bytes 1 */
1126
static int hf_s7comm_header_redid;                    /* Header Bytes 2, 3 */
1127
static int hf_s7comm_header_pduref;                   /* Header Bytes 4, 5 */
1128
static int hf_s7comm_header_parlg;                    /* Header Bytes 6, 7 */
1129
static int hf_s7comm_header_datlg;                    /* Header Bytes 8, 9 */
1130
static int hf_s7comm_header_errcls;                   /* Header Byte 10, only available at type 2 or 3 */
1131
static int hf_s7comm_header_errcod;                   /* Header Byte 11, only available at type 2 or 3 */
1132
/* Parameter Block */
1133
static int hf_s7comm_param;
1134
static int hf_s7comm_param_errcod;                    /* Parameter part: Error code */
1135
static int hf_s7comm_param_service;                   /* Parameter part: service */
1136
static int hf_s7comm_param_itemcount;                 /* Parameter part: item count */
1137
static int hf_s7comm_param_data;                      /* Parameter part: data */
1138
static int hf_s7comm_param_neg_pdu_length;            /* Parameter part: Negotiate PDU length */
1139
static int hf_s7comm_param_setup_reserved1;           /* Parameter part: Reserved byte in communication setup pdu*/
1140
1141
static int hf_s7comm_param_maxamq_calling;            /* Parameter part: Max AmQ calling */
1142
static int hf_s7comm_param_maxamq_called;             /* Parameter part: Max AmQ called */
1143
1144
/* Item data */
1145
static int hf_s7comm_param_item;
1146
static int hf_s7comm_param_subitem;                   /* Substructure */
1147
static int hf_s7comm_item_varspec;                    /* Variable specification */
1148
static int hf_s7comm_item_varspec_length;             /* Length of following address specification */
1149
static int hf_s7comm_item_syntax_id;                  /* Syntax Id */
1150
static int hf_s7comm_item_transport_size;             /* Transport size, 1 Byte*/
1151
static int hf_s7comm_item_length;                     /* length, 2 Bytes*/
1152
static int hf_s7comm_item_db;                         /* DB/M/E/A, 2 Bytes */
1153
static int hf_s7comm_item_area;                       /* Area code, 1 byte */
1154
static int hf_s7comm_item_address;                    /* Bit address, 3 Bytes */
1155
static int hf_s7comm_item_address_byte;               /* address: Byte address */
1156
static int hf_s7comm_item_address_bit;                /* address: Bit address */
1157
static int hf_s7comm_item_address_nr;                 /* address: Timer/Counter/block number */
1158
/* Special variable read with Syntax-Id 0xb0 (DBREAD) */
1159
static int hf_s7comm_item_dbread_numareas;            /* Number of areas following, 1 Byte*/
1160
static int hf_s7comm_item_dbread_length;              /* length, 1 Byte*/
1161
static int hf_s7comm_item_dbread_db;                  /* DB number, 2 Bytes*/
1162
static int hf_s7comm_item_dbread_startadr;            /* Start address, 2 Bytes*/
1163
/* Reading frequency inverter parameters via routing */
1164
static int hf_s7comm_item_driveesany_unknown1;        /* Unknown value 1, 1 Byte */
1165
static int hf_s7comm_item_driveesany_unknown2;        /* Unknown value 2, 2 Bytes */
1166
static int hf_s7comm_item_driveesany_unknown3;        /* Unknown value 3, 2 Bytes */
1167
static int hf_s7comm_item_driveesany_parameter_nr;    /* Parameter number, 2 Bytes */
1168
static int hf_s7comm_item_driveesany_parameter_idx;   /* Parameter index, 2 Bytes */
1169
/* NCK access with Syntax-Id 0x82 */
1170
static int hf_s7comm_item_nck_areaunit;               /* Bitmask: aaauuuuu: a=area, u=unit */
1171
static int hf_s7comm_item_nck_area;
1172
static int hf_s7comm_item_nck_unit;
1173
static int hf_s7comm_item_nck_column;
1174
static int hf_s7comm_item_nck_line;
1175
static int hf_s7comm_item_nck_module;
1176
static int hf_s7comm_item_nck_linecount;
1177
1178
static int hf_s7comm_data;
1179
static int hf_s7comm_data_returncode;                 /* return code, 1 byte */
1180
static int hf_s7comm_data_transport_size;             /* transport size 1 byte */
1181
static int hf_s7comm_data_length;                     /* Length of data, 2 Bytes */
1182
1183
static int hf_s7comm_data_item;
1184
1185
static int hf_s7comm_readresponse_data;
1186
static int hf_s7comm_data_fillbyte;
1187
1188
/* timefunction: s7 timestamp */
1189
static int hf_s7comm_data_ts;
1190
static int hf_s7comm_data_ts_reserved;
1191
static int hf_s7comm_data_ts_year1;                   /* first byte of BCD coded year, should be ignored */
1192
static int hf_s7comm_data_ts_year2;                   /* second byte of BCD coded year, if 00...89 then it's 2000...2089, else 1990...1999*/
1193
static int hf_s7comm_data_ts_month;
1194
static int hf_s7comm_data_ts_day;
1195
static int hf_s7comm_data_ts_hour;
1196
static int hf_s7comm_data_ts_minute;
1197
static int hf_s7comm_data_ts_second;
1198
static int hf_s7comm_data_ts_millisecond;
1199
static int hf_s7comm_data_ts_weekday;
1200
1201
/* userdata, block services */
1202
static int hf_s7comm_userdata_data;
1203
1204
static int hf_s7comm_userdata_param_type;
1205
static int hf_s7comm_userdata_param_funcgroup;
1206
static int hf_s7comm_userdata_param_subfunc_prog;
1207
static int hf_s7comm_userdata_param_subfunc_cyclic;
1208
static int hf_s7comm_userdata_param_subfunc_block;
1209
static int hf_s7comm_userdata_param_subfunc_cpu;
1210
static int hf_s7comm_userdata_param_subfunc_sec;
1211
static int hf_s7comm_userdata_param_subfunc_time;
1212
static int hf_s7comm_userdata_param_subfunc_ncprg;
1213
static int hf_s7comm_userdata_param_subfunc_drr;
1214
static int hf_s7comm_userdata_param_subfunc;          /* for all other subfunctions */
1215
static int hf_s7comm_userdata_param_seq_num;
1216
static int hf_s7comm_userdata_param_dataunitref;
1217
static int hf_s7comm_userdata_param_dataunit;
1218
1219
/* block functions, list blocks of type */
1220
static int hf_s7comm_ud_blockinfo_block_type;         /* Block type, 2 bytes */
1221
static int hf_s7comm_ud_blockinfo_block_num;          /* Block number, 2 bytes as int */
1222
static int hf_s7comm_ud_blockinfo_block_cnt;          /* Count, 2 bytes as int */
1223
static int hf_s7comm_ud_blockinfo_block_flags;        /* Block flags (unknown), 1 byte */
1224
static int hf_s7comm_ud_blockinfo_block_lang;         /* Block language, 1 byte, stringlist blocklanguage_names */
1225
/* block functions, get block infos */
1226
static int hf_s7comm_ud_blockinfo_block_num_ascii;    /* Block number, 5 bytes, ASCII*/
1227
static int hf_s7comm_ud_blockinfo_filesys;            /* Filesystem, 1 byte, ASCII*/
1228
static int hf_s7comm_ud_blockinfo_res_infolength;     /* Length of Info, 2 bytes as int */
1229
static int hf_s7comm_ud_blockinfo_res_unknown2;       /* Unknown blockinfo 2, 2 bytes, HEX*/
1230
static int hf_s7comm_ud_blockinfo_res_const3;         /* Constant 3, 2 bytes, ASCII */
1231
static int hf_s7comm_ud_blockinfo_res_unknown;        /* Unknown byte(s) */
1232
static int hf_s7comm_ud_blockinfo_subblk_type;        /* Subblk type, 1 byte, stringlist subblktype_names */
1233
static int hf_s7comm_ud_blockinfo_load_mem_len;       /* Length load memory, 4 bytes, int */
1234
static int hf_s7comm_ud_blockinfo_blocksecurity;      /* Block Security, 4 bytes, stringlist blocksecurity_names*/
1235
static int hf_s7comm_ud_blockinfo_interface_timestamp;/* Interface Timestamp, string */
1236
static int hf_s7comm_ud_blockinfo_code_timestamp;     /* Code Timestamp, string */
1237
static int hf_s7comm_ud_blockinfo_ssb_len;            /* SSB length, 2 bytes, int */
1238
static int hf_s7comm_ud_blockinfo_add_len;            /* ADD length, 2 bytes, int */
1239
static int hf_s7comm_ud_blockinfo_localdata_len;      /* Length localdata, 2 bytes, int */
1240
static int hf_s7comm_ud_blockinfo_mc7_len;            /* Length MC7 code, 2 bytes, int */
1241
static int hf_s7comm_ud_blockinfo_author;             /* Author, 8 bytes, ASCII */
1242
static int hf_s7comm_ud_blockinfo_family;             /* Family, 8 bytes, ASCII */
1243
static int hf_s7comm_ud_blockinfo_headername;         /* Name (Header), 8 bytes, ASCII */
1244
static int hf_s7comm_ud_blockinfo_headerversion;      /* Version (Header), 8 bytes, ASCII */
1245
static int hf_s7comm_ud_blockinfo_checksum;           /* Block checksum, 2 bytes, HEX */
1246
static int hf_s7comm_ud_blockinfo_reserved1;          /* Reserved 1, 4 bytes, HEX */
1247
static int hf_s7comm_ud_blockinfo_reserved2;          /* Reserved 2, 4 bytes, HEX */
1248
1249
static int hf_s7comm_userdata_blockinfo_flags;        /* Some flags in Block info response */
1250
static int hf_s7comm_userdata_blockinfo_linked;       /* Some flags in Block info response */
1251
static int hf_s7comm_userdata_blockinfo_standard_block;
1252
static int hf_s7comm_userdata_blockinfo_nonretain;    /* Some flags in Block info response */
1253
static int ett_s7comm_userdata_blockinfo_flags;
1254
static int * const s7comm_userdata_blockinfo_flags_fields[] = {
1255
    &hf_s7comm_userdata_blockinfo_linked,
1256
    &hf_s7comm_userdata_blockinfo_standard_block,
1257
    &hf_s7comm_userdata_blockinfo_nonretain,
1258
    NULL
1259
};
1260
1261
/* Programmer commands / Test and installation (TIS) functions */
1262
static int hf_s7comm_tis_parameter;
1263
static int hf_s7comm_tis_data;
1264
static int hf_s7comm_tis_parametersize;
1265
static int hf_s7comm_tis_datasize;
1266
static int hf_s7comm_tis_param1;
1267
static int hf_s7comm_tis_param2;
1268
static const value_string tis_param2_names[] = {    /* Values and their meaning are not always clearly defined in every function */
1269
    { 0,                                    "Update Monitor Variables / Activate Modify Values"},
1270
    { 1,                                    "Monitor Variable / Modify Variable" },
1271
    { 2,                                    "Modify Variable permanent" },
1272
    { 256,                                  "Force immediately" },
1273
    { 0,                                    NULL }
1274
};
1275
static int hf_s7comm_tis_param3;
1276
static const value_string tis_param3_names[] = {
1277
    { 0,                                    "Every cycle (permanent)" },
1278
    { 1,                                    "Once" },
1279
    { 2,                                    "Always (force)" },
1280
    { 0,                                    NULL }
1281
};
1282
static int hf_s7comm_tis_answersize;
1283
static int hf_s7comm_tis_param5;
1284
static int hf_s7comm_tis_param6;
1285
static int hf_s7comm_tis_param7;
1286
static int hf_s7comm_tis_param8;
1287
static int hf_s7comm_tis_param9;
1288
static int hf_s7comm_tis_trgevent;
1289
static int hf_s7comm_tis_res_param1;
1290
static int hf_s7comm_tis_res_param2;
1291
static int hf_s7comm_tis_job_function;
1292
static int hf_s7comm_tis_job_seqnr;
1293
static int hf_s7comm_tis_job_reserved;
1294
1295
1296
1297
/* B/I/L Stack */
1298
static int hf_s7comm_tis_interrupted_blocktype;
1299
static int hf_s7comm_tis_interrupted_blocknr;
1300
static int hf_s7comm_tis_interrupted_address;
1301
static int hf_s7comm_tis_interrupted_prioclass;
1302
static int hf_s7comm_tis_continued_blocktype;
1303
static int hf_s7comm_tis_continued_blocknr;
1304
static int hf_s7comm_tis_continued_address;
1305
static int hf_s7comm_tis_breakpoint_blocktype;
1306
static int hf_s7comm_tis_breakpoint_blocknr;
1307
static int hf_s7comm_tis_breakpoint_address;
1308
static int hf_s7comm_tis_breakpoint_reserved;
1309
1310
static int hf_s7comm_tis_p_callenv;
1311
static const value_string tis_p_callenv_names[] = {
1312
    { 0,                                   "Specified call environment"},
1313
    { 2,                                   "Specified global and/or instance data block"},
1314
    { 0,                                    NULL }
1315
};
1316
static int hf_s7comm_tis_p_callcond;
1317
static const value_string tis_p_callcond_names[] = {
1318
    { 0x0000,                               "Not set" },
1319
    { 0x0001,                               "On block number" },
1320
    { 0x0101,                               "On block number with code address" },
1321
    { 0x0a00,                               "On DB1 (DB) content" },
1322
    { 0x000a,                               "On DB2 (DI) content" },
1323
    { 0x0a0a,                               "On DB1 (DB) and DB2 (DI) content" },
1324
    { 0,                                    NULL }
1325
};
1326
static int hf_s7comm_tis_p_callcond_blocktype;
1327
static int hf_s7comm_tis_p_callcond_blocknr;
1328
static int hf_s7comm_tis_p_callcond_address;
1329
1330
1331
static int hf_s7comm_tis_register_db1_type;
1332
static int hf_s7comm_tis_register_db2_type;
1333
static int hf_s7comm_tis_register_db1_nr;
1334
static int hf_s7comm_tis_register_db2_nr;
1335
static int hf_s7comm_tis_register_accu1;
1336
static int hf_s7comm_tis_register_accu2;
1337
static int hf_s7comm_tis_register_accu3;
1338
static int hf_s7comm_tis_register_accu4;
1339
static int hf_s7comm_tis_register_ar1;
1340
static int hf_s7comm_tis_register_ar2;
1341
static int hf_s7comm_tis_register_stw;
1342
static int hf_s7comm_tis_exithold_until;
1343
static const value_string tis_exithold_until_names[] = {
1344
    { 0,                                    "Next breakpoint" },
1345
    { 1,                                    "Next statement" },
1346
    { 0,                                    NULL }
1347
};
1348
static int hf_s7comm_tis_exithold_res1;
1349
static int hf_s7comm_tis_bstack_nest_depth;
1350
static int hf_s7comm_tis_bstack_reserved;
1351
static int hf_s7comm_tis_istack_reserved;
1352
static int hf_s7comm_tis_lstack_reserved;
1353
static int hf_s7comm_tis_lstack_size;
1354
static int hf_s7comm_tis_lstack_data;
1355
static int hf_s7comm_tis_blockstat_flagsunknown;
1356
static int hf_s7comm_tis_blockstat_number_of_lines;
1357
static int hf_s7comm_tis_blockstat_line_address;
1358
static int hf_s7comm_tis_blockstat_data;
1359
static int hf_s7comm_tis_blockstat_reserved;
1360
1361
/* Organization block local data */
1362
static int hf_s7comm_ob_ev_class;
1363
static int hf_s7comm_ob_scan_1;
1364
static int hf_s7comm_ob_strt_inf;
1365
static int hf_s7comm_ob_flt_id;
1366
static int hf_s7comm_ob_priority;
1367
static int hf_s7comm_ob_number;
1368
static int hf_s7comm_ob_reserved_1;
1369
static int hf_s7comm_ob_reserved_2;
1370
static int hf_s7comm_ob_reserved_3;
1371
static int hf_s7comm_ob_reserved_4;
1372
static int hf_s7comm_ob_reserved_4_dw;
1373
static int hf_s7comm_ob_prev_cycle;
1374
static int hf_s7comm_ob_min_cycle;
1375
static int hf_s7comm_ob_max_cycle;
1376
static int hf_s7comm_ob_period_exe;
1377
static int hf_s7comm_ob_sign;
1378
static int hf_s7comm_ob_dtime;
1379
static int hf_s7comm_ob_phase_offset;
1380
static int hf_s7comm_ob_exec_freq;
1381
static int hf_s7comm_ob_io_flag;
1382
static int hf_s7comm_ob_mdl_addr;
1383
static int hf_s7comm_ob_point_addr;
1384
static int hf_s7comm_ob_inf_len;
1385
static int hf_s7comm_ob_alarm_type;
1386
static int hf_s7comm_ob_alarm_slot;
1387
static int hf_s7comm_ob_alarm_spec;
1388
static int hf_s7comm_ob_error_info;
1389
static int hf_s7comm_ob_err_ev_class;
1390
static int hf_s7comm_ob_err_ev_num;
1391
static int hf_s7comm_ob_err_ob_priority;
1392
static int hf_s7comm_ob_err_ob_num;
1393
static int hf_s7comm_ob_rack_cpu;
1394
static int hf_s7comm_ob_8x_fault_flags;
1395
static int hf_s7comm_ob_mdl_type_b;
1396
static int hf_s7comm_ob_mdl_type_w;
1397
static int hf_s7comm_ob_rack_num;
1398
static int hf_s7comm_ob_racks_flt;
1399
static int hf_s7comm_ob_strtup;
1400
static int hf_s7comm_ob_stop;
1401
static int hf_s7comm_ob_strt_info;
1402
static int hf_s7comm_ob_sw_flt;
1403
static int hf_s7comm_ob_blk_type;
1404
static int hf_s7comm_ob_flt_reg;
1405
static int hf_s7comm_ob_flt_blk_num;
1406
static int hf_s7comm_ob_prg_addr;
1407
static int hf_s7comm_ob_mem_area;
1408
static int hf_s7comm_ob_mem_addr;
1409
1410
static int hf_s7comm_diagdata_req_block_type;
1411
static int hf_s7comm_diagdata_req_block_num;
1412
static int hf_s7comm_diagdata_req_startaddr_awl;
1413
static int hf_s7comm_diagdata_req_saz;
1414
1415
/* Flags for requested registers in diagnostic data telegrams */
1416
static int hf_s7comm_diagdata_registerflag;           /* Registerflags */
1417
static int hf_s7comm_diagdata_registerflag_stw;       /* STW = Status word */
1418
static int hf_s7comm_diagdata_registerflag_accu1;     /* Accumulator 1 */
1419
static int hf_s7comm_diagdata_registerflag_accu2;     /* Accumulator 2 */
1420
static int hf_s7comm_diagdata_registerflag_ar1;       /* Addressregister 1 */
1421
static int hf_s7comm_diagdata_registerflag_ar2;       /* Addressregister 2 */
1422
static int hf_s7comm_diagdata_registerflag_db1;       /* Datablock register 1 */
1423
static int hf_s7comm_diagdata_registerflag_db2;       /* Datablock register 2 */
1424
static int ett_s7comm_diagdata_registerflag;
1425
static int * const s7comm_diagdata_registerflag_fields[] = {
1426
    &hf_s7comm_diagdata_registerflag_stw,
1427
    &hf_s7comm_diagdata_registerflag_accu1,
1428
    &hf_s7comm_diagdata_registerflag_accu2,
1429
    &hf_s7comm_diagdata_registerflag_ar1,
1430
    &hf_s7comm_diagdata_registerflag_ar2,
1431
    &hf_s7comm_diagdata_registerflag_db1,
1432
    &hf_s7comm_diagdata_registerflag_db2,
1433
    NULL
1434
};
1435
1436
static heur_dissector_list_t s7comm_heur_subdissector_list_bsend;
1437
static heur_dissector_list_t s7comm_heur_subdissector_list_block_data;
1438
1439
static expert_field ei_s7comm_data_blockcontrol_block_num_invalid;
1440
static expert_field ei_s7comm_ud_blockinfo_block_num_ascii_invalid;
1441
1442
/* PI service name IDs. Index represents the index in pi_service_names */
1443
typedef enum
1444
{
1445
    S7COMM_PI_UNKNOWN = 0,
1446
    S7COMM_PI_INSE,
1447
    S7COMM_PI_INS2,
1448
    S7COMM_PI_DELE,
1449
    S7COMM_PIP_PROGRAM,
1450
    S7COMM_PI_MODU,
1451
    S7COMM_PI_GARB,
1452
    S7COMM_PI_N_LOGIN_,
1453
    S7COMM_PI_N_LOGOUT,
1454
    S7COMM_PI_N_CANCEL,
1455
    S7COMM_PI_N_DASAVE,
1456
    S7COMM_PI_N_DIGIOF,
1457
    S7COMM_PI_N_DIGION,
1458
    S7COMM_PI_N_DZERO_,
1459
    S7COMM_PI_N_ENDEXT,
1460
    S7COMM_PI_N_F_OPER,
1461
    S7COMM_PI_N_OST_OF,
1462
    S7COMM_PI_N_OST_ON,
1463
    S7COMM_PI_N_SCALE_,
1464
    S7COMM_PI_N_SETUFR,
1465
    S7COMM_PI_N_STRTLK,
1466
    S7COMM_PI_N_STRTUL,
1467
    S7COMM_PI_N_TMRASS,
1468
    S7COMM_PI_N_F_DELE,
1469
    S7COMM_PI_N_EXTERN,
1470
    S7COMM_PI_N_EXTMOD,
1471
    S7COMM_PI_N_F_DELR,
1472
    S7COMM_PI_N_F_XFER,
1473
    S7COMM_PI_N_LOCKE_,
1474
    S7COMM_PI_N_SELECT,
1475
    S7COMM_PI_N_SRTEXT,
1476
    S7COMM_PI_N_F_CLOS,
1477
    S7COMM_PI_N_F_OPEN,
1478
    S7COMM_PI_N_F_SEEK,
1479
    S7COMM_PI_N_ASUP__,
1480
    S7COMM_PI_N_CHEKDM,
1481
    S7COMM_PI_N_CHKDNO,
1482
    S7COMM_PI_N_CONFIG,
1483
    S7COMM_PI_N_CRCEDN,
1484
    S7COMM_PI_N_DELECE,
1485
    S7COMM_PI_N_CREACE,
1486
    S7COMM_PI_N_CREATO,
1487
    S7COMM_PI_N_DELETO,
1488
    S7COMM_PI_N_CRTOCE,
1489
    S7COMM_PI_N_DELVAR,
1490
    S7COMM_PI_N_F_COPY,
1491
    S7COMM_PI_N_F_DMDA,
1492
    S7COMM_PI_N_F_PROR,
1493
    S7COMM_PI_N_F_PROT,
1494
    S7COMM_PI_N_F_RENA,
1495
    S7COMM_PI_N_FINDBL,
1496
    S7COMM_PI_N_IBN_SS,
1497
    S7COMM_PI_N_MMCSEM,
1498
    S7COMM_PI_N_NCKMOD,
1499
    S7COMM_PI_N_NEWPWD,
1500
    S7COMM_PI_N_SEL_BL,
1501
    S7COMM_PI_N_SETTST,
1502
    S7COMM_PI_N_TMAWCO,
1503
    S7COMM_PI_N_TMCRTC,
1504
    S7COMM_PI_N_TMCRTO,
1505
    S7COMM_PI_N_TMFDPL,
1506
    S7COMM_PI_N_TMFPBP,
1507
    S7COMM_PI_N_TMGETT,
1508
    S7COMM_PI_N_TMMVTL,
1509
    S7COMM_PI_N_TMPCIT,
1510
    S7COMM_PI_N_TMPOSM,
1511
    S7COMM_PI_N_TRESMO,
1512
    S7COMM_PI_N_TSEARC
1513
} pi_service_e;
1514
1515
/* Description for PI service names */
1516
static const string_string pi_service_names[] = {
1517
    { "UNKNOWN",                            "PI-Service is currently unknown" },
1518
    { "_INSE",                              "PI-Service _INSE (Activates a PLC module)" },
1519
    { "_INS2",                              "PI-Service _INS2 (Activates a PLC module)" },
1520
    { "_DELE",                              "PI-Service _DELE (Removes module from the PLC's passive file system)" },
1521
    { "P_PROGRAM",                          "PI-Service P_PROGRAM (PLC Start / Stop)" },
1522
    { "_MODU",                              "PI-Service _MODU (PLC Copy Ram to Rom)" },
1523
    { "_GARB",                              "PI-Service _GARB (Compress PLC memory)" },
1524
    { "_N_LOGIN_",                          "PI-Service _N_LOGIN_ (Login)" },
1525
    { "_N_LOGOUT",                          "PI-Service _N_LOGOUT (Logout)" },
1526
    { "_N_CANCEL",                          "PI-Service _N_CANCEL (Cancels NC alarm)" },
1527
    { "_N_DASAVE",                          "PI-Service _N_DASAVE (PI-Service for copying data from SRAM to FLASH)" },
1528
    { "_N_DIGIOF",                          "PI-Service _N_DIGIOF (Turns off digitizing)" },
1529
    { "_N_DIGION",                          "PI-Service _N_DIGION (Turns on digitizing)" },
1530
    { "_N_DZERO_",                          "PI-Service _N_DZERO_ (Set all D nos. invalid for function \"unique D no.\")" },
1531
    { "_N_ENDEXT",                          "PI-Service _N_ENDEXT ()" },
1532
    { "_N_F_OPER",                          "PI-Service _N_F_OPER (Opens a file read-only)" },
1533
    { "_N_OST_OF",                          "PI-Service _N_OST_OF (Overstore OFF)" },
1534
    { "_N_OST_ON",                          "PI-Service _N_OST_ON (Overstore ON)" },
1535
    { "_N_SCALE_",                          "PI-Service _N_SCALE_ (Unit of measurement setting (metric<->INCH))" },
1536
    { "_N_SETUFR",                          "PI-Service _N_SETUFR (Activates user frame)" },
1537
    { "_N_STRTLK",                          "PI-Service _N_STRTLK (The global start disable is set)" },
1538
    { "_N_STRTUL",                          "PI-Service _N_STRTUL (The global start disable is reset)" },
1539
    { "_N_TMRASS",                          "PI-Service _N_TMRASS (Resets the Active status)" },
1540
    { "_N_F_DELE",                          "PI-Service _N_F_DELE (Deletes file)" },
1541
    { "_N_EXTERN",                          "PI-Service _N_EXTERN (Selects external program for execution)" },
1542
    { "_N_EXTMOD",                          "PI-Service _N_EXTMOD (Selects external program for execution)" },
1543
    { "_N_F_DELR",                          "PI-Service _N_F_DELR (Delete file even without access rights)" },
1544
    { "_N_F_XFER",                          "PI-Service _N_F_XFER (Selects file for uploading)" },
1545
    { "_N_LOCKE_",                          "PI-Service _N_LOCKE_ (Locks the active file for editing)" },
1546
    { "_N_SELECT",                          "PI-Service _N_SELECT (Selects program for execution)" },
1547
    { "_N_SRTEXT",                          "PI-Service _N_SRTEXT (A file is being marked in /_N_EXT_DIR)" },
1548
    { "_N_F_CLOS",                          "PI-Service _N_F_CLOS (Closes file)" },
1549
    { "_N_F_OPEN",                          "PI-Service _N_F_OPEN (Opens file)" },
1550
    { "_N_F_SEEK",                          "PI-Service _N_F_SEEK (Position the file search pointer)" },
1551
    { "_N_ASUP__",                          "PI-Service _N_ASUP__ (Assigns interrupt)" },
1552
    { "_N_CHEKDM",                          "PI-Service _N_CHEKDM (Start uniqueness check on D numbers)" },
1553
    { "_N_CHKDNO",                          "PI-Service _N_CHKDNO (Check whether the tools have unique D numbers)" },
1554
    { "_N_CONFIG",                          "PI-Service _N_CONFIG (Reconfigures machine data)" },
1555
    { "_N_CRCEDN",                          "PI-Service _N_CRCEDN (Creates a cutting edge by specifying an edge no.)" },
1556
    { "_N_DELECE",                          "PI-Service _N_DELECE (Deletes a cutting edge)" },
1557
    { "_N_CREACE",                          "PI-Service _N_CREACE (Creates a cutting edge)" },
1558
    { "_N_CREATO",                          "PI-Service _N_CREATO (Creates a tool)" },
1559
    { "_N_DELETO",                          "PI-Service _N_DELETO (Deletes tool)" },
1560
    { "_N_CRTOCE",                          "PI-Service _N_CRTOCE (Generate tool with specified edge number)" },
1561
    { "_N_DELVAR",                          "PI-Service _N_DELVAR (Delete data block)" },
1562
    { "_N_F_COPY",                          "PI-Service _N_F_COPY (Copies file within the NCK)" },
1563
    { "_N_F_DMDA",                          "PI-Service _N_F_DMDA (Deletes MDA memory)" },
1564
    { "_N_F_PROR",                          "PI-Service _N_F_PROR" },
1565
    { "_N_F_PROT",                          "PI-Service _N_F_PROT (Assigns a protection level to a file)" },
1566
    { "_N_F_RENA",                          "PI-Service _N_F_RENA (Renames file)" },
1567
    { "_N_FINDBL",                          "PI-Service _N_FINDBL (Activates search)" },
1568
    { "_N_IBN_SS",                          "PI-Service _N_IBN_SS (Sets the set-up switch)" },
1569
    { "_N_MMCSEM",                          "PI-Service _N_MMCSEM (MMC-Semaphore)" },
1570
    { "_N_NCKMOD",                          "PI-Service _N_NCKMOD (The mode in which the NCK will work is being set)" },
1571
    { "_N_NEWPWD",                          "PI-Service _N_NEWPWD (New password)" },
1572
    { "_N_SEL_BL",                          "PI-Service _N_SEL_BL (Selects a new block)" },
1573
    { "_N_SETTST",                          "PI-Service _N_SETTST (Activate tools for replacement tool group)" },
1574
    { "_N_TMAWCO",                          "PI-Service _N_TMAWCO (Set the active wear group in one magazine)" },
1575
    { "_N_TMCRTC",                          "PI-Service _N_TMCRTC (Create tool with specified edge number)" },
1576
    { "_N_TMCRTO",                          "PI-Service _N_TMCRTO (Creates tool in the tool management)" },
1577
    { "_N_TMFDPL",                          "PI-Service _N_TMFDPL (Searches an empty place for loading)" },
1578
    { "_N_TMFPBP",                          "PI-Service _N_TMFPBP (Searches for empty location)" },
1579
    { "_N_TMGETT",                          "PI-Service _N_TMGETT (Determines T-number for specific toolID with Duplono)" },
1580
    { "_N_TMMVTL",                          "PI-Service _N_TMMVTL (Loads or unloads a tool)" },
1581
    { "_N_TMPCIT",                          "PI-Service _N_TMPCIT (Sets increment value of the piece counter)" },
1582
    { "_N_TMPOSM",                          "PI-Service _N_TMPOSM (Positions a magazine or tool)" },
1583
    { "_N_TRESMO",                          "PI-Service _N_TRESMO (Reset monitoring values)" },
1584
    { "_N_TSEARC",                          "PI-Service _N_TSEARC (Complex search via search screenforms)" },
1585
    { NULL,                                 NULL }
1586
};
1587
1588
/* Function 0x28 (PI Start) */
1589
static int hf_s7comm_piservice_unknown1;   /* Unknown bytes */
1590
static int hf_s7comm_piservice_parameterblock;
1591
static int hf_s7comm_piservice_parameterblock_len;
1592
static int hf_s7comm_piservice_servicename;
1593
1594
static int ett_s7comm_piservice_parameterblock;
1595
1596
static int hf_s7comm_piservice_string_len;
1597
static int hf_s7comm_pi_n_x_addressident;
1598
static int hf_s7comm_pi_n_x_password;
1599
static int hf_s7comm_pi_n_x_filename;
1600
static int hf_s7comm_pi_n_x_editwindowname;
1601
static int hf_s7comm_pi_n_x_seekpointer;
1602
static int hf_s7comm_pi_n_x_windowsize;
1603
static int hf_s7comm_pi_n_x_comparestring;
1604
static int hf_s7comm_pi_n_x_skipcount;
1605
static int hf_s7comm_pi_n_x_interruptnr;
1606
static int hf_s7comm_pi_n_x_priority;
1607
static int hf_s7comm_pi_n_x_liftfast;
1608
static int hf_s7comm_pi_n_x_blsync;
1609
static int hf_s7comm_pi_n_x_magnr;
1610
static int hf_s7comm_pi_n_x_dnr;
1611
static int hf_s7comm_pi_n_x_spindlenumber;
1612
static int hf_s7comm_pi_n_x_wznr;
1613
static int hf_s7comm_pi_n_x_class;
1614
static int hf_s7comm_pi_n_x_tnr;
1615
static int hf_s7comm_pi_n_x_toolnumber;
1616
static int hf_s7comm_pi_n_x_cenumber;
1617
static int hf_s7comm_pi_n_x_datablocknumber;
1618
static int hf_s7comm_pi_n_x_firstcolumnnumber;
1619
static int hf_s7comm_pi_n_x_lastcolumnnumber;
1620
static int hf_s7comm_pi_n_x_firstrownumber;
1621
static int hf_s7comm_pi_n_x_lastrownumber;
1622
static int hf_s7comm_pi_n_x_direction;
1623
static int hf_s7comm_pi_n_x_sourcefilename;
1624
static int hf_s7comm_pi_n_x_destinationfilename;
1625
static int hf_s7comm_pi_n_x_channelnumber;
1626
static int hf_s7comm_pi_n_x_protection;
1627
static int hf_s7comm_pi_n_x_oldfilename;
1628
static int hf_s7comm_pi_n_x_newfilename;
1629
static int hf_s7comm_pi_n_x_findmode;
1630
static int hf_s7comm_pi_n_x_switch;
1631
static int hf_s7comm_pi_n_x_functionnumber;
1632
static int hf_s7comm_pi_n_x_semaphorevalue;
1633
static int hf_s7comm_pi_n_x_onoff;
1634
static int hf_s7comm_pi_n_x_mode;
1635
static int hf_s7comm_pi_n_x_factor;
1636
static int hf_s7comm_pi_n_x_passwordlevel;
1637
static int hf_s7comm_pi_n_x_linenumber;
1638
static int hf_s7comm_pi_n_x_weargroup;
1639
static int hf_s7comm_pi_n_x_toolstatus;
1640
static int hf_s7comm_pi_n_x_wearsearchstrat;
1641
static int hf_s7comm_pi_n_x_toolid;
1642
static int hf_s7comm_pi_n_x_duplonumber;
1643
static int hf_s7comm_pi_n_x_edgenumber;
1644
static int hf_s7comm_pi_n_x_placenr;
1645
static int hf_s7comm_pi_n_x_placerefnr;
1646
static int hf_s7comm_pi_n_x_magrefnr;
1647
static int hf_s7comm_pi_n_x_magnrfrom;
1648
static int hf_s7comm_pi_n_x_placenrfrom;
1649
static int hf_s7comm_pi_n_x_magnrto;
1650
static int hf_s7comm_pi_n_x_placenrto;
1651
static int hf_s7comm_pi_n_x_halfplacesleft;
1652
static int hf_s7comm_pi_n_x_halfplacesright;
1653
static int hf_s7comm_pi_n_x_halfplacesup;
1654
static int hf_s7comm_pi_n_x_halfplacesdown;
1655
static int hf_s7comm_pi_n_x_placetype;
1656
static int hf_s7comm_pi_n_x_searchdirection;
1657
static int hf_s7comm_pi_n_x_toolname;
1658
static int hf_s7comm_pi_n_x_placenrsource;
1659
static int hf_s7comm_pi_n_x_magnrsource;
1660
static int hf_s7comm_pi_n_x_placenrdestination;
1661
static int hf_s7comm_pi_n_x_magnrdestination;
1662
static int hf_s7comm_pi_n_x_incrementnumber;
1663
static int hf_s7comm_pi_n_x_monitoringmode;
1664
static int hf_s7comm_pi_n_x_kindofsearch;
1665
1666
static int hf_s7comm_data_plccontrol_argument;        /* Argument, 2 Bytes as char */
1667
static int hf_s7comm_data_plccontrol_block_cnt;       /* Number of blocks, 1 Byte as int */
1668
static int hf_s7comm_data_pi_inse_unknown;
1669
static int hf_s7comm_data_plccontrol_part2_len;       /* Length part 2 in bytes, 1 Byte as Int */
1670
1671
/* block control functions */
1672
static int hf_s7comm_data_blockcontrol_unknown1;      /* for all unknown bytes in blockcontrol */
1673
static int hf_s7comm_data_blockcontrol_errorcode;     /* Error code 2 bytes as int, 0 is no error */
1674
static int hf_s7comm_data_blockcontrol_uploadid;
1675
static int hf_s7comm_data_blockcontrol_file_ident;    /* File identifier, as ASCII */
1676
static int hf_s7comm_data_blockcontrol_block_type;    /* Block type, 2 Byte */
1677
static int hf_s7comm_data_blockcontrol_block_num;     /* Block number, 5 Bytes, ASCII */
1678
static int hf_s7comm_data_blockcontrol_dest_filesys;  /* Destination filesystem, 1 Byte, ASCII */
1679
static int hf_s7comm_data_blockcontrol_part2_len;     /* Length part 2 in bytes, 1 Byte Int */
1680
static int hf_s7comm_data_blockcontrol_part2_unknown; /* Unknown char, ASCII */
1681
static int hf_s7comm_data_blockcontrol_loadmem_len;   /* Length load memory in bytes, ASCII */
1682
static int hf_s7comm_data_blockcontrol_mc7code_len;   /* Length of MC7 code in bytes, ASCII */
1683
static int hf_s7comm_data_blockcontrol_filename_len;
1684
static int hf_s7comm_data_blockcontrol_filename;
1685
static int hf_s7comm_data_blockcontrol_upl_lenstring_len;
1686
static int hf_s7comm_data_blockcontrol_upl_lenstring;
1687
1688
static int hf_s7comm_data_blockcontrol_functionstatus;
1689
static int hf_s7comm_data_blockcontrol_functionstatus_more;
1690
static int hf_s7comm_data_blockcontrol_functionstatus_error;
1691
static int ett_s7comm_data_blockcontrol_status;
1692
static int * const s7comm_data_blockcontrol_status_fields[] = {
1693
    &hf_s7comm_data_blockcontrol_functionstatus_more,
1694
    &hf_s7comm_data_blockcontrol_functionstatus_error,
1695
    NULL
1696
};
1697
1698
static int ett_s7comm_plcfilename;
1699
static int hf_s7comm_data_ncprg_unackcount;
1700
static int hf_s7comm_data_ncprg_filelength;
1701
static int hf_s7comm_data_ncprg_filetime;
1702
static int hf_s7comm_data_ncprg_filepath;
1703
static int hf_s7comm_data_ncprg_filedata;
1704
1705
/* Data record routing to Profibus */
1706
static int hf_s7comm_data_drr_data;
1707
1708
/* Variable status */
1709
static int hf_s7comm_varstat_unknown;                  /* Unknown byte(s), hex */
1710
static int hf_s7comm_varstat_item_count;               /* Item count, 2 bytes, int */
1711
static int hf_s7comm_varstat_req_memory_area;          /* Memory area, 1 byte, stringlist userdata_tis_varstat_area_names  */
1712
static int hf_s7comm_varstat_req_repetition_factor;    /* Repetition factor, 1 byte as int */
1713
static int hf_s7comm_varstat_req_db_number;            /* DB number, 2 bytes as int */
1714
static int hf_s7comm_varstat_req_startaddress;         /* Startaddress, 2 bytes as int */
1715
static int hf_s7comm_varstat_req_bitpos;
1716
1717
/* cyclic services */
1718
static int hf_s7comm_cycl_interval_timebase;          /* Interval timebase, 1 byte, int */
1719
static int hf_s7comm_cycl_interval_time;              /* Interval time, 1 byte, int */
1720
static int hf_s7comm_cycl_function;
1721
static int hf_s7comm_cycl_jobid;
1722
1723
/* Read record */
1724
static int hf_s7comm_rdrec_mlen;                      /* Max. length in bytes of the data record data to be read */
1725
static int hf_s7comm_rdrec_index;                     /* Data record number */
1726
static int hf_s7comm_rdrec_id;                        /* Diagnostic address */
1727
static int hf_s7comm_rdrec_statuslen;                 /* Length of optional status data */
1728
static int hf_s7comm_rdrec_statusdata;                /* Optional status data */
1729
static int hf_s7comm_rdrec_recordlen;                 /* Length of data record data read */
1730
static int hf_s7comm_rdrec_data;                      /* The read data record */
1731
static int hf_s7comm_rdrec_reserved1;
1732
1733
/* PBC, Programmable Block Functions */
1734
static int hf_s7comm_pbc_unknown;                     /* unknown, 1 byte */
1735
static int hf_s7comm_pbc_bsend_r_id;                  /* Request ID R_ID, 4 bytes as hex */
1736
static int hf_s7comm_pbc_bsend_len;
1737
static int hf_s7comm_pbc_usend_unknown1;
1738
static int hf_s7comm_pbc_usend_r_id;
1739
static int hf_s7comm_pbc_usend_unknown2;
1740
static int hf_s7comm_pbc_arsend_ar_id;
1741
static int hf_s7comm_pbc_arsend_ret;
1742
static int hf_s7comm_pbc_arsend_unknown;
1743
static int hf_s7comm_pbc_arsend_len;
1744
1745
/* Alarm messages */
1746
static int hf_s7comm_cpu_alarm_message_item;
1747
static int hf_s7comm_cpu_alarm_message_obj_item;
1748
static int hf_s7comm_cpu_alarm_message_function;
1749
static int hf_s7comm_cpu_alarm_message_nr_objects;
1750
static int hf_s7comm_cpu_alarm_message_nr_add_values;
1751
static int hf_s7comm_cpu_alarm_message_eventid;
1752
static int hf_s7comm_cpu_alarm_message_timestamp_coming;
1753
static int hf_s7comm_cpu_alarm_message_timestamp_going;
1754
static int hf_s7comm_cpu_alarm_message_associated_value;
1755
static int hf_s7comm_cpu_alarm_message_eventstate;
1756
static int hf_s7comm_cpu_alarm_message_state;
1757
static int hf_s7comm_cpu_alarm_message_ackstate_coming;
1758
static int hf_s7comm_cpu_alarm_message_ackstate_going;
1759
static int hf_s7comm_cpu_alarm_message_event_coming;
1760
static int hf_s7comm_cpu_alarm_message_event_going;
1761
static int hf_s7comm_cpu_alarm_message_event_lastchanged;
1762
static int hf_s7comm_cpu_alarm_message_event_reserved;
1763
static int hf_s7comm_cpu_alarm_message_scan_unknown1;
1764
static int hf_s7comm_cpu_alarm_message_scan_unknown2;
1765
1766
static int hf_s7comm_cpu_alarm_message_signal_sig1;
1767
static int hf_s7comm_cpu_alarm_message_signal_sig2;
1768
static int hf_s7comm_cpu_alarm_message_signal_sig3;
1769
static int hf_s7comm_cpu_alarm_message_signal_sig4;
1770
static int hf_s7comm_cpu_alarm_message_signal_sig5;
1771
static int hf_s7comm_cpu_alarm_message_signal_sig6;
1772
static int hf_s7comm_cpu_alarm_message_signal_sig7;
1773
static int hf_s7comm_cpu_alarm_message_signal_sig8;
1774
static int ett_s7comm_cpu_alarm_message_signal;
1775
static int * const s7comm_cpu_alarm_message_signal_fields[] = {
1776
    &hf_s7comm_cpu_alarm_message_signal_sig1,
1777
    &hf_s7comm_cpu_alarm_message_signal_sig2,
1778
    &hf_s7comm_cpu_alarm_message_signal_sig3,
1779
    &hf_s7comm_cpu_alarm_message_signal_sig4,
1780
    &hf_s7comm_cpu_alarm_message_signal_sig5,
1781
    &hf_s7comm_cpu_alarm_message_signal_sig6,
1782
    &hf_s7comm_cpu_alarm_message_signal_sig7,
1783
    &hf_s7comm_cpu_alarm_message_signal_sig8,
1784
    NULL
1785
};
1786
1787
static int hf_s7comm_cpu_alarm_query_unknown1;
1788
static int hf_s7comm_cpu_alarm_query_querytype;
1789
static int hf_s7comm_cpu_alarm_query_unknown2;
1790
static int hf_s7comm_cpu_alarm_query_alarmtype;
1791
static int hf_s7comm_cpu_alarm_query_completelen;
1792
static int hf_s7comm_cpu_alarm_query_datasetlen;
1793
static int hf_s7comm_cpu_alarm_query_resunknown1;
1794
1795
/* CPU diagnostic messages */
1796
static int hf_s7comm_cpu_diag_msg_item;
1797
static int hf_s7comm_cpu_diag_msg_eventid;
1798
static int hf_s7comm_cpu_diag_msg_eventid_class;
1799
static int hf_s7comm_cpu_diag_msg_eventid_ident_entleave;
1800
static int hf_s7comm_cpu_diag_msg_eventid_ident_diagbuf;
1801
static int hf_s7comm_cpu_diag_msg_eventid_ident_interr;
1802
static int hf_s7comm_cpu_diag_msg_eventid_ident_exterr;
1803
static int hf_s7comm_cpu_diag_msg_eventid_nr;
1804
static int hf_s7comm_cpu_diag_msg_prioclass;
1805
static int hf_s7comm_cpu_diag_msg_obnumber;
1806
static int hf_s7comm_cpu_diag_msg_datid;
1807
static int hf_s7comm_cpu_diag_msg_info1;
1808
static int hf_s7comm_cpu_diag_msg_info2;
1809
1810
static int ett_s7comm_cpu_diag_msg_eventid;
1811
static int * const s7comm_cpu_diag_msg_eventid_fields[] = {
1812
    &hf_s7comm_cpu_diag_msg_eventid_class,
1813
    &hf_s7comm_cpu_diag_msg_eventid_ident_entleave,
1814
    &hf_s7comm_cpu_diag_msg_eventid_ident_diagbuf,
1815
    &hf_s7comm_cpu_diag_msg_eventid_ident_interr,
1816
    &hf_s7comm_cpu_diag_msg_eventid_ident_exterr,
1817
    &hf_s7comm_cpu_diag_msg_eventid_nr,
1818
    NULL
1819
};
1820
1821
static const true_false_string tfs_s7comm_cpu_diag_msg_eventid_ident_entleave = {
1822
    "Event entering",
1823
    "Event leaving"
1824
};
1825
1826
static const value_string cpu_diag_msg_eventid_class_names[] = {
1827
    { 0x01,                                 "Standard OB events" },
1828
    { 0x02,                                 "Synchronous errors" },
1829
    { 0x03,                                 "Asynchronous errors" },
1830
    { 0x04,                                 "Mode transitions" },
1831
    { 0x05,                                 "Run-time events" },
1832
    { 0x06,                                 "Communication events" },
1833
    { 0x07,                                 "Events for fail-safe and fault-tolerant systems" },
1834
    { 0x08,                                 "Standardized diagnostic data on modules" },
1835
    { 0x09,                                 "Predefined user events" },
1836
    { 0x0a,                                 "Freely definable events" },
1837
    { 0x0b,                                 "Freely definable events" },
1838
    { 0x0c,                                 "Reserved" },
1839
    { 0x0d,                                 "Reserved" },
1840
    { 0x0e,                                 "Reserved" },
1841
    { 0x0f,                                 "Events for modules other than CPUs" },
1842
    { 0,                                    NULL }
1843
};
1844
1845
static const value_string cpu_diag_eventid_fix_names[] = {
1846
    { 0x113A,                               "Start request for cyclic interrupt OB with special handling (S7-300 only)" },
1847
    { 0x1155,                               "Status alarm for PROFIBUS DP" },
1848
    { 0x1156,                               "Update interrupt for PROFIBUS DP" },
1849
    { 0x1157,                               "Manufacturer interrupt for PROFIBUS DP" },
1850
    { 0x1158,                               "Status interrupt for PROFINET IO" },
1851
    { 0x1159,                               "Update interrupt for PROFINET IO" },
1852
    { 0x115A,                               "Manufacturer interrupt for PROFINET IO" },
1853
    { 0x115B,                               "IO: Profile-specific interrupt" },
1854
    { 0x116A,                               "Technology synchronization interrupt" },
1855
    { 0x1381,                               "Request for manual warm restart" },
1856
    { 0x1382,                               "Request for automatic warm restart" },
1857
    { 0x1383,                               "Request for manual hot restart" },
1858
    { 0x1384,                               "Request for automatic hot restart" },
1859
    { 0x1385,                               "Request for manual cold restart" },
1860
    { 0x1386,                               "Request for automatic cold restart" },
1861
    { 0x1387,                               "Master CPU: request for manual cold restart" },
1862
    { 0x1388,                               "Master CPU: request for automatic cold restart" },
1863
    { 0x138A,                               "Master CPU: request for manual warm restart" },
1864
    { 0x138B,                               "Master CPU: request for automatic warm restart" },
1865
    { 0x138C,                               "Standby CPU: request for manual hot restart" },
1866
    { 0x138D,                               "Standby CPU: request for automatic hot restart" },
1867
    { 0x2521,                               "BCD conversion error" },
1868
    { 0x2522,                               "Area length error when reading" },
1869
    { 0x2523,                               "Area length error when writing" },
1870
    { 0x2524,                               "Area error when reading" },
1871
    { 0x2525,                               "Area error when writing" },
1872
    { 0x2526,                               "Timer number error" },
1873
    { 0x2527,                               "Counter number error" },
1874
    { 0x2528,                               "Alignment error when reading" },
1875
    { 0x2529,                               "Alignment error when writing" },
1876
    { 0x2530,                               "Write error when accessing the DB" },
1877
    { 0x2531,                               "Write error when accessing the DI" },
1878
    { 0x2532,                               "Block number error when opening a DB" },
1879
    { 0x2533,                               "Block number error when opening a DI" },
1880
    { 0x2534,                               "Block number error when calling an FC" },
1881
    { 0x2535,                               "Block number error when calling an FB" },
1882
    { 0x253A,                               "DB not loaded" },
1883
    { 0x253C,                               "FC not loaded" },
1884
    { 0x253D,                               "SFC not loaded" },
1885
    { 0x253E,                               "FB not loaded" },
1886
    { 0x253F,                               "SFB not loaded" },
1887
    { 0x2942,                               "I/O access error, reading" },
1888
    { 0x2943,                               "I/O access error, writing" },
1889
    { 0x3267,                               "End of module reconfiguration" },
1890
    { 0x3367,                               "Start of module reconfiguration" },
1891
    { 0x34A4,                               "PROFInet Interface DB can be addressed again" },
1892
    { 0x3501,                               "Cycle time exceeded" },
1893
    { 0x3502,                               "User interface (OB or FRB) request error" },
1894
    { 0x3503,                               "Delay too long processing a priority class" },
1895
    { 0x3505,                               "Time-of-day interrupt(s) skipped due to new clock setting" },
1896
    { 0x3506,                               "Time-of-day interrupt(s) skipped when changing to RUN after HOLD" },
1897
    { 0x3507,                               "Multiple OB request errors caused internal buffer overflow" },
1898
    { 0x3508,                               "Synchronous cycle interrupt-timing error" },
1899
    { 0x3509,                               "Interrupt loss due to excess interrupt load" },
1900
    { 0x350A,                               "Resume RUN mode after CiR" },
1901
    { 0x350B,                               "Technology synchronization interrupt - timing error" },
1902
    { 0x3571,                               "Nesting depth too high in nesting levels" },
1903
    { 0x3572,                               "Nesting depth for Master Control Relays too high" },
1904
    { 0x3573,                               "Nesting depth too high after synchronous errors" },
1905
    { 0x3574,                               "Nesting depth for block calls (U stack) too high" },
1906
    { 0x3575,                               "Nesting depth for block calls (B stack) too high" },
1907
    { 0x3576,                               "Local data allocation error" },
1908
    { 0x3578,                               "Unknown instruction" },
1909
    { 0x357A,                               "Jump instruction to target outside of the block" },
1910
    { 0x3582,                               "Memory error detected and corrected by operating system" },
1911
    { 0x3583,                               "Accumulation of detected and corrected memo errors" },
1912
    { 0x3585,                               "Error in the PC operating system (only for LC RTX)" },
1913
    { 0x3587,                               "Multi-bit memory error detected and corrected" },
1914
    { 0x35A1,                               "User interface (OB or FRB) not found" },
1915
    { 0x35A2,                               "OB not loaded (started by SFC or operating system due to configuration)" },
1916
    { 0x35A3,                               "Error when operating system accesses a block" },
1917
    { 0x35A4,                               "PROFInet Interface DB cannot be addressed" },
1918
    { 0x35D2,                               "Diagnostic entries cannot be sent at present" },
1919
    { 0x35D3,                               "Synchronization frames cannot be sent" },
1920
    { 0x35D4,                               "Illegal time jump resulting from synchronization" },
1921
    { 0x35D5,                               "Error adopting the synchronization time" },
1922
    { 0x35E1,                               "Incorrect frame ID in GD" },
1923
    { 0x35E2,                               "GD packet status cannot be entered in DB" },
1924
    { 0x35E3,                               "Frame length error in GD" },
1925
    { 0x35E4,                               "Illegal GD packet number received" },
1926
    { 0x35E5,                               "Error accessing DB in communication SFBs for configured S7 connections" },
1927
    { 0x35E6,                               "GD total status cannot be entered in DB" },
1928
    { 0x3821,                               "BATTF: failure on at least one backup battery of the central rack, problem eliminated" },
1929
    { 0x3822,                               "BAF: failure of backup voltage on central rack, problem eliminated" },
1930
    { 0x3823,                               "24 volt supply failure on central rack, problem eliminated" },
1931
    { 0x3825,                               "BATTF: failure on at least one backup battery of the redundant central rack, problem eliminated" },
1932
    { 0x3826,                               "BAF: failure of backup voltage on redundant central rack, problem eliminated" },
1933
    { 0x3827,                               "24 volt supply failure on redundant central rack, problem eliminated" },
1934
    { 0x3831,                               "BATTF: failure of at least one backup battery of the expansion rack, problem eliminated" },
1935
    { 0x3832,                               "BAF: failure of backup voltage on expansion rack, problem eliminated" },
1936
    { 0x3833,                               "24 volt supply failure on at least one expansion rack, problem eliminated" },
1937
    { 0x3842,                               "Module OK" },
1938
    { 0x3854,                               "PROFINET IO interface submodule/submodule and matches the configured interface submodule/submodule" },
1939
    { 0x3855,                               "PROFINET IO interface submodule/submodule inserted, but does not match the configured interface submodule/submodule" },
1940
    { 0x3856,                               "PROFINET IO interface submodule/submodule inserted, but error in module parameter assignment" },
1941
    { 0x3858,                               "PROFINET IO interface submodule access error corrected" },
1942
    { 0x3861,                               "Module/interface module inserted, module type OK" },
1943
    { 0x3863,                               "Module/interface module plugged in, but wrong module type" },
1944
    { 0x3864,                               "Module/interface module plugged in, but causing problem (type ID unreadable)" },
1945
    { 0x3865,                               "Module plugged in, but error in module parameter assignment" },
1946
    { 0x3866,                               "Module can be addressed again, load voltage error removed" },
1947
    { 0x3881,                               "Interface error leaving state" },
1948
    { 0x3884,                               "Interface module plugged in" },
1949
    { 0x38B3,                               "I/O access error when updating the process image input table" },
1950
    { 0x38B4,                               "I/O access error when transferring the process image to the output modules" },
1951
    { 0x38C1,                               "Expansion rack operational again (1 to 21), leaving state" },
1952
    { 0x38C2,                               "Expansion rack operational again but mismatch between setpoint and actual configuration" },
1953
    { 0x38C4,                               "Distributed I/Os: station failure, leaving state" },
1954
    { 0x38C5,                               "Distributed I/Os: station fault, leaving state" },
1955
    { 0x38C6,                               "Expansion rack operational again, but error(s) in module parameter assignment" },
1956
    { 0x38C7,                               "DP: station operational again, but error(s) in module parameter assignment" },
1957
    { 0x38C8,                               "DP: station operational again, but mismatch between setpoint and actual configuration" },
1958
    { 0x38CB,                               "PROFINET IO station operational again" },
1959
    { 0x38CC,                               "PROFINET IO station error corrected" },
1960
    { 0x3921,                               "BATTF: failure on at least one backup battery of the central rack" },
1961
    { 0x3922,                               "BAF: failure of backup voltage on central rack" },
1962
    { 0x3923,                               "24 volt supply failure on central rack" },
1963
    { 0x3925,                               "BATTF: failure on at least one backup battery of the redundant central rack" },
1964
    { 0x3926,                               "BAF: failure of backup voltage on redundant central rack" },
1965
    { 0x3927,                               "24 volt supply failure on redundant central rack" },
1966
    { 0x3931,                               "BATTF: failure of at least one backup battery of the expansion rack" },
1967
    { 0x3932,                               "BAF: failure of backup voltage on expansion rack" },
1968
    { 0x3933,                               "24 volt supply failure on at least one expansion rack" },
1969
    { 0x3942,                               "Module error" },
1970
    { 0x3951,                               "PROFINET IO submodule removed" },
1971
    { 0x3954,                               "PROFINET IO interface submodule/submodule removed" },
1972
    { 0x3961,                               "Module/interface module removed, cannot be addressed" },
1973
    { 0x3966,                               "Module cannot be addressed, load voltage error" },
1974
    { 0x3968,                               "Module reconfiguration has ended with error" },
1975
    { 0x3981,                               "Interface error entering state" },
1976
    { 0x3984,                               "Interface module removed" },
1977
    { 0x3986,                               "Performance of an H-Sync link negatively affected" },
1978
    { 0x39B1,                               "I/O access error when updating the process image input table" },
1979
    { 0x39B2,                               "I/O access error when transferring the process image to the output modules" },
1980
    { 0x39B3,                               "I/O access error when updating the process image input table" },
1981
    { 0x39B4,                               "I/O access error when transferring the process image to the output modules" },
1982
    { 0x39C1,                               "Expansion rack failure (1 to 21), entering state" },
1983
    { 0x39C3,                               "Distributed I/Os: master system failure entering state" },
1984
    { 0x39C4,                               "Distributed I/Os: station failure, entering state" },
1985
    { 0x39C5,                               "Distributed I/Os: station fault, entering state" },
1986
    { 0x39CA,                               "PROFINET IO system failure" },
1987
    { 0x39CB,                               "PROFINET IO station failure" },
1988
    { 0x39CC,                               "PROFINET IO station error" },
1989
    { 0x39CD,                               "PROFINET IO station operational again, but expected configuration does not match actual configuration" },
1990
    { 0x39CE,                               "PROFINET IO station operational again, but error(s) in module parameter assignment" },
1991
    { 0x42F3,                               "Checksum error detected and corrected by the operating system" },
1992
    { 0x42F4,                               "Standby CPU: connection/update via SFC90 is locked in the master CPU" },
1993
    { 0x4300,                               "Backed-up power on" },
1994
    { 0x4301,                               "Mode transition from STOP to STARTUP" },
1995
    { 0x4302,                               "Mode transition from STARTUP to RUN" },
1996
    { 0x4303,                               "STOP caused by stop switch being activated" },
1997
    { 0x4304,                               "STOP caused by PG STOP operation or by SFB 20 STOP" },
1998
    { 0x4305,                               "HOLD: breakpoint reached" },
1999
    { 0x4306,                               "HOLD: breakpoint exited" },
2000
    { 0x4307,                               "Memory reset started by PG operation" },
2001
    { 0x4308,                               "Memory reset started by switch setting" },
2002
    { 0x4309,                               "Memory reset started automatically (power on not backed up)" },
2003
    { 0x430A,                               "HOLD exited, transition to STOP" },
2004
    { 0x430D,                               "STOP caused by other CPU in multicomputing" },
2005
    { 0x430E,                               "Memory reset executed" },
2006
    { 0x430F,                               "STOP on the module due to STOP on a CPU" },
2007
    { 0x4318,                               "Start of CiR" },
2008
    { 0x4319,                               "CiR completed" },
2009
    { 0x4357,                               "Module watchdog started" },
2010
    { 0x4358,                               "All modules are ready for operation" },
2011
    { 0x43B0,                               "Firmware update was successful" },
2012
    { 0x43B4,                               "Error in firmware fuse" },
2013
    { 0x43B6,                               "Firmware updates canceled by redundant modules" },
2014
    { 0x43D3,                               "STOP on standby CPU" },
2015
    { 0x43DC,                               "Abort during link-up with switchover" },
2016
    { 0x43DE,                               "Updating aborted due to monitoring time being exceeded during the n-th attempt, new update attempt initiated" },
2017
    { 0x43DF,                               "Updating aborted for final time due to monitoring time being exceeded after completing the maximum amount of attempts. User intervention required" },
2018
    { 0x43E0,                               "Change from solo mode after link-up" },
2019
    { 0x43E1,                               "Change from link-up after updating" },
2020
    { 0x43E2,                               "Change from updating to redundant mode" },
2021
    { 0x43E3,                               "Master CPU: change from redundant mode to solo mode" },
2022
    { 0x43E4,                               "Standby CPU: change from redundant mode after error-search mode" },
2023
    { 0x43E5,                               "Standby CPU: change from error-search mode after link-up or STOP" },
2024
    { 0x43E6,                               "Link-up aborted on the standby CPU" },
2025
    { 0x43E7,                               "Updating aborted on the standby CPU" },
2026
    { 0x43E8,                               "Standby CPU: change from link-up after startup" },
2027
    { 0x43E9,                               "Standby CPU: change from startup after updating" },
2028
    { 0x43F1,                               "Reserve-master switchover" },
2029
    { 0x43F2,                               "Coupling of incompatible H-CPUs blocked by system program" },
2030
    { 0x4510,                               "STOP violation of the CPU's data range" },
2031
    { 0x4520,                               "DEFECTIVE: STOP not possible" },
2032
    { 0x4521,                               "DEFECTIVE: failure of instruction processing processor" },
2033
    { 0x4522,                               "DEFECTIVE: failure of clock chip" },
2034
    { 0x4523,                               "DEFECTIVE: failure of clock pulse generator" },
2035
    { 0x4524,                               "DEFECTIVE: failure of timer update function" },
2036
    { 0x4525,                               "DEFECTIVE: failure of multicomputing synchronization" },
2037
    { 0x4527,                               "DEFECTIVE: failure of I/O access monitoring" },
2038
    { 0x4528,                               "DEFECTIVE: failure of scan time monitoring" },
2039
    { 0x4530,                               "DEFECTIVE: memory test error in internal memory" },
2040
    { 0x4532,                               "DEFECTIVE: failure of core resources" },
2041
    { 0x4536,                               "DEFECTIVE: switch defective" },
2042
    { 0x4540,                               "STOP: Memory expansion of the internal work memory has gaps. First memory expansion too small or missing" },
2043
    { 0x4541,                               "STOP caused by priority class system" },
2044
    { 0x4542,                               "STOP caused by object management system" },
2045
    { 0x4543,                               "STOP caused by test functions" },
2046
    { 0x4544,                               "STOP caused by diagnostic system" },
2047
    { 0x4545,                               "STOP caused by communication system" },
2048
    { 0x4546,                               "STOP caused by CPU memory management" },
2049
    { 0x4547,                               "STOP caused by process image management" },
2050
    { 0x4548,                               "STOP caused by I/O management" },
2051
    { 0x454A,                               "STOP caused by configuration: an OB deselected with STEP 7 was being loaded into the CPU during STARTUP" },
2052
    { 0x4550,                               "DEFECTIVE: internal system error" },
2053
    { 0x4555,                               "No restart possible, monitoring time elapsed" },
2054
    { 0x4556,                               "STOP: memory reset request from communication system / due to data inconsistency" },
2055
    { 0x4562,                               "STOP caused by programming error (OB not loaded or not possible)" },
2056
    { 0x4563,                               "STOP caused by I/O access error (OB not loaded or not possible)" },
2057
    { 0x4567,                               "STOP caused by H event" },
2058
    { 0x4568,                               "STOP caused by time error (OB not loaded or not possible)" },
2059
    { 0x456A,                               "STOP caused by diagnostic interrupt (OB not loaded or not possible)" },
2060
    { 0x456B,                               "STOP caused by removing/inserting module (OB not loaded or not possible)" },
2061
    { 0x456C,                               "STOP caused by CPU hardware error (OB not loaded or not possible, or no FRB)" },
2062
    { 0x456D,                               "STOP caused by program sequence error (OB not loaded or not possible)" },
2063
    { 0x456E,                               "STOP caused by communication error (OB not loaded or not possible)" },
2064
    { 0x456F,                               "STOP caused by rack failure OB (OB not loaded or not possible)" },
2065
    { 0x4570,                               "STOP caused by process interrupt (OB not loaded or not possible)" },
2066
    { 0x4571,                               "STOP caused by nesting stack error" },
2067
    { 0x4572,                               "STOP caused by master control relay stack error" },
2068
    { 0x4573,                               "STOP caused by exceeding the nesting depth for synchronous errors" },
2069
    { 0x4574,                               "STOP caused by exceeding interrupt stack nesting depth in the priority class stack" },
2070
    { 0x4575,                               "STOP caused by exceeding block stack nesting depth in the priority class stack" },
2071
    { 0x4576,                               "STOP caused by error when allocating the local data" },
2072
    { 0x4578,                               "STOP caused by unknown opcode" },
2073
    { 0x457A,                               "STOP caused by code length error" },
2074
    { 0x457B,                               "STOP caused by DB not being loaded on on-board I/Os" },
2075
    { 0x457D,                               "Reset/clear request because the version of the internal interface to the integrated technology was changed" },
2076
    { 0x457F,                               "STOP caused by STOP command" },
2077
    { 0x4580,                               "STOP: back-up buffer contents inconsistent (no transition to RUN)" },
2078
    { 0x4590,                               "STOP caused by overloading the internal functions" },
2079
    { 0x45D5,                               "LINK-UP rejected due to mismatched CPU memory configuration of the sub-PLC" },
2080
    { 0x45D6,                               "LINK-UP rejected due to mismatched system program of the sub-PLC" },
2081
    { 0x45D8,                               "DEFECTIVE: hardware fault detected due to other error" },
2082
    { 0x45D9,                               "STOP due to SYNC module error" },
2083
    { 0x45DA,                               "STOP due to synchronization error between H CPUs" },
2084
    { 0x45DD,                               "LINK-UP rejected due to running test or other online functions" },
2085
    { 0x4926,                               "DEFECTIVE: failure of the watchdog for I/O access" },
2086
    { 0x4931,                               "STOP or DEFECTIVE: memory test error in memory submodule" },
2087
    { 0x4933,                               "Checksum error" },
2088
    { 0x4934,                               "DEFECTIVE: memory not available" },
2089
    { 0x4935,                               "DEFECTIVE: cancelled by watchdog/processor exceptions" },
2090
    { 0x4949,                               "STOP caused by continuous hardware interrupt" },
2091
    { 0x494D,                               "STOP caused by I/O error" },
2092
    { 0x494E,                               "STOP caused by power failure" },
2093
    { 0x494F,                               "STOP caused by configuration error" },
2094
    { 0x4959,                               "One or more modules not ready for operation" },
2095
    { 0x497C,                               "STOP caused by integrated technology" },
2096
    { 0x49A0,                               "STOP caused by parameter assignment error or non-permissible variation of setpoint and actual extension: Start-up blocked" },
2097
    { 0x49A1,                               "STOP caused by parameter assignment error: memory reset request" },
2098
    { 0x49A2,                               "STOP caused by error in parameter modification: startup disabled" },
2099
    { 0x49A3,                               "STOP caused by error in parameter modification: memory reset request" },
2100
    { 0x49A4,                               "STOP: inconsistency in configuration data" },
2101
    { 0x49A5,                               "STOP: distributed I/Os: inconsistency in the loaded configuration information" },
2102
    { 0x49A6,                               "STOP: distributed I/Os: invalid configuration information" },
2103
    { 0x49A7,                               "STOP: distributed I/Os: no configuration information" },
2104
    { 0x49A8,                               "STOP: error indicated by the interface module for the distributed I/Os" },
2105
    { 0x49B1,                               "Firmware update data incorrect" },
2106
    { 0x49B2,                               "Firmware update: hardware version does not match firmware" },
2107
    { 0x49B3,                               "Firmware update: module type does not match firmware" },
2108
    { 0x49D0,                               "LINK-UP aborted due to violation of coordination rules" },
2109
    { 0x49D1,                               "LINK-UP/UPDATE sequence aborted" },
2110
    { 0x49D2,                               "Standby CPU changed to STOP due to STOP on the master CPU during link-up" },
2111
    { 0x49D4,                               "STOP on a master, since partner CPU is also a master (link-up error)" },
2112
    { 0x49D7,                               "LINK-UP rejected due to change in user program or in configuration" },
2113
    { 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" },
2114
    { 0x530D,                               "New startup information in the STOP mode" },
2115
    { 0x5311,                               "Startup despite Not Ready message from module(s)" },
2116
    { 0x5371,                               "Distributed I/Os: end of the synchronization with a DP master" },
2117
    { 0x5380,                               "Diagnostic buffer entries of interrupt and asynchronous errors disabled" },
2118
    { 0x5395,                               "Distributed I/Os: reset of a DP master" },
2119
    { 0x53A2,                               "Download of technology firmware successful" },
2120
    { 0x53A4,                               "Download of technology DB not successful" },
2121
    { 0x53FF,                               "Reset to factory setting" },
2122
    { 0x5445,                               "Start of System reconfiguration in RUN mode" },
2123
    { 0x5481,                               "All licenses for runtime software are complete again" },
2124
    { 0x5498,                               "No more inconsistency with DP master systems due to CiR" },
2125
    { 0x5545,                               "Start of System reconfiguration in RUN mode" },
2126
    { 0x5581,                               "One or several licenses for runtime software are missing" },
2127
    { 0x558A,                               "Difference between the MLFB of the configured and inserted CPU" },
2128
    { 0x558B,                               "Difference in the firmware version of the configured and inserted CPU" },
2129
    { 0x5598,                               "Start of possible inconsistency with DP master systems due to CiR" },
2130
    { 0x55A5,                               "Version conflict: internal interface with integrated technology" },
2131
    { 0x55A6,                               "The maximum number of technology objects has been exceeded" },
2132
    { 0x55A7,                               "A technology DB of this type is already present" },
2133
    { 0x5879,                               "Diagnostic message from DP interface: EXTF LED off" },
2134
    { 0x5960,                               "Parameter assignment error when switching" },
2135
    { 0x5961,                               "Parameter assignment error" },
2136
    { 0x5962,                               "Parameter assignment error preventing startup" },
2137
    { 0x5963,                               "Parameter assignment error with memory reset request" },
2138
    { 0x5966,                               "Parameter assignment error when switching" },
2139
    { 0x5969,                               "Parameter assignment error with startup blocked" },
2140
    { 0x596A,                               "PROFINET IO: IP address of an IO device already present" },
2141
    { 0x596B,                               "IP address of an Ethernet interface already exists" },
2142
    { 0x596C,                               "Name of an Ethernet interface already exists" },
2143
    { 0x596D,                               "The existing network configuration does not mach the system requirements or configuration" },
2144
    { 0x5979,                               "Diagnostic message from DP interface: EXTF LED on" },
2145
    { 0x597C,                               "DP Global Control command failed or moved" },
2146
    { 0x59A0,                               "The interrupt can not be associated in the CPU" },
2147
    { 0x59A1,                               "Configuration error in the integrated technology" },
2148
    { 0x59A3,                               "Error when downloading the integrated technology" },
2149
    { 0x6253,                               "Firmware update: End of firmware download over the network" },
2150
    { 0x6316,                               "Interface error when starting programmable controller" },
2151
    { 0x6353,                               "Firmware update: Start of firmware download over the network" },
2152
    { 0x6390,                               "Formatting of Micro Memory Card complete" },
2153
    { 0x6500,                               "Connection ID exists twice on module" },
2154
    { 0x6501,                               "Connection resources inadequate" },
2155
    { 0x6502,                               "Error in the connection description" },
2156
    { 0x6510,                               "CFB structure error detected in instance DB when evaluating EPROM" },
2157
    { 0x6514,                               "GD packet number exists twice on the module" },
2158
    { 0x6515,                               "Inconsistent length specifications in GD configuration information" },
2159
    { 0x6521,                               "No memory submodule and no internal memory available" },
2160
    { 0x6522,                               "Illegal memory submodule: replace submodule and reset memory" },
2161
    { 0x6523,                               "Memory reset request due to error accessing submodule" },
2162
    { 0x6524,                               "Memory reset request due to error in block header" },
2163
    { 0x6526,                               "Memory reset request due to memory replacement" },
2164
    { 0x6527,                               "Memory replaced, therefore restart not possible" },
2165
    { 0x6528,                               "Object handling function in the STOP/HOLD mode, no restart possible" },
2166
    { 0x6529,                               "No startup possible during the \"load user program\" function" },
2167
    { 0x652A,                               "No startup because block exists twice in user memory" },
2168
    { 0x652B,                               "No startup because block is too long for submodule - replace submodule" },
2169
    { 0x652C,                               "No startup due to illegal OB on submodule" },
2170
    { 0x6532,                               "No startup because illegal configuration information on submodule" },
2171
    { 0x6533,                               "Memory reset request because of invalid submodule content" },
2172
    { 0x6534,                               "No startup: block exists more than once on submodule" },
2173
    { 0x6535,                               "No startup: not enough memory to transfer block from submodule" },
2174
    { 0x6536,                               "No startup: submodule contains an illegal block number" },
2175
    { 0x6537,                               "No startup: submodule contains a block with an illegal length" },
2176
    { 0x6538,                               "Local data or write-protection ID (for DB) of a block illegal for CPU" },
2177
    { 0x6539,                               "Illegal command in block (detected by compiler)" },
2178
    { 0x653A,                               "Memory reset request because local OB data on submodule too short" },
2179
    { 0x6543,                               "No startup: illegal block type" },
2180
    { 0x6544,                               "No startup: attribute \"relevant for processing\" illegal" },
2181
    { 0x6545,                               "Source language illegal" },
2182
    { 0x6546,                               "Maximum amount of configuration information reached" },
2183
    { 0x6547,                               "Parameter assignment error assigning parameters to modules (not on P bus, cancel download)" },
2184
    { 0x6548,                               "Plausibility error during block check" },
2185
    { 0x6549,                               "Structure error in block" },
2186
    { 0x6550,                               "A block has an error in the CRC" },
2187
    { 0x6551,                               "A block has no CRC" },
2188
    { 0x6560,                               "SCAN overflow" },
2189
    { 0x6805,                               "Resource problem on configured connections, eliminated" },
2190
    { 0x6881,                               "Interface error leaving state" },
2191
    { 0x6905,                               "Resource problem on configured connections" },
2192
    { 0x6981,                               "Interface error entering state" },
2193
    { 0x72A2,                               "Failure of a DP master or a DP master system" },
2194
    { 0x72A3,                               "Redundancy restored on the DP slave" },
2195
    { 0x72DB,                               "Safety program: safety mode disabled" },
2196
    { 0x72E0,                               "Loss of redundancy in communication, problem eliminated" },
2197
    { 0x7301,                               "Loss of redundancy (1 of 2) due to failure of a CPU" },
2198
    { 0x7302,                               "Loss of redundancy (1 of 2) due to STOP on the standby triggered by user" },
2199
    { 0x7303,                               "H system (1 of 2) changed to redundant mode" },
2200
    { 0x7323,                               "Discrepancy found in operating system data" },
2201
    { 0x7331,                               "Standby-master switchover due to master failure" },
2202
    { 0x7333,                               "Standby-master switchover due to system modification during runtime" },
2203
    { 0x7334,                               "Standby-master switchover due to communication error at the synchronization module" },
2204
    { 0x7340,                               "Synchronization error in user program due to elapsed wait time" },
2205
    { 0x7341,                               "Synchronization error in user program due to waiting at different synchronization points" },
2206
    { 0x7342,                               "Synchronization error in operating system due to waiting at different synchronization points" },
2207
    { 0x7343,                               "Synchronization error in operating system due to elapsed wait time" },
2208
    { 0x7344,                               "Synchronization error in operating system due to incorrect data" },
2209
    { 0x734A,                               "The \"Re-enable\" job triggered by SFC 90 \"H_CTRL\" was executed" },
2210
    { 0x73A3,                               "Loss of redundancy on the DP slave" },
2211
    { 0x73C1,                               "Update process canceled" },
2212
    { 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)" },
2213
    { 0x73D8,                               "Safety mode disabled" },
2214
    { 0x73DB,                               "Safety program: safety mode enabled" },
2215
    { 0x73E0,                               "Loss of redundancy in communication" },
2216
    { 0x74DD,                               "Safety program: Shutdown of a fail-save runtime group disabled" },
2217
    { 0x74DE,                               "Safety program: Shutdown of the F program disabled" },
2218
    { 0x74DF,                               "Start of F program initialization" },
2219
    { 0x7520,                               "Error in RAM comparison" },
2220
    { 0x7521,                               "Error in comparison of process image output value" },
2221
    { 0x7522,                               "Error in comparison of memory bits, timers, or counters" },
2222
    { 0x75D1,                               "Safety program: Internal CPU error" },
2223
    { 0x75D2,                               "Safety program error: Cycle time time-out" },
2224
    { 0x75D6,                               "Data corrupted in safety program prior to the output to F I/O" },
2225
    { 0x75D7,                               "Data corrupted in safety program prior to the output to partner F-CPU" },
2226
    { 0x75D9,                               "Invalid REAL number in a DB" },
2227
    { 0x75DA,                               "Safety program: Error in safety data format" },
2228
    { 0x75DC,                               "Runtime group, internal protocol error" },
2229
    { 0x75DD,                               "Safety program: Shutdown of a fail-save runtime group enabled" },
2230
    { 0x75DE,                               "Safety program: Shutdown of the F program enabled" },
2231
    { 0x75DF,                               "End of F program initialization" },
2232
    { 0x75E1,                               "Safety program: Error in FB \"F_PLK\" or \"F_PLK_O\" or \"F_CYC_CO\" or \"F_TEST\" or \"F_TESTC\"" },
2233
    { 0x75E2,                               "Safety program: Area length error" },
2234
    { 0x7852,                               "SYNC module inserted" },
2235
    { 0x7855,                               "SYNC module eliminated" },
2236
    { 0x78D3,                               "Communication error between PROFIsafe and F I/O" },
2237
    { 0x78D4,                               "Error in safety relevant communication between F CPUs" },
2238
    { 0x78D5,                               "Error in safety relevant communication between F CPUs" },
2239
    { 0x78E3,                               "F-I/O device input channel depassivated" },
2240
    { 0x78E4,                               "F-I/O device output channel depassivated" },
2241
    { 0x78E5,                               "F-I/O device depassivated" },
2242
    { 0x7934,                               "Standby-master switchover due to connection problem at the SYNC module" },
2243
    { 0x7950,                               "Synchronization module missing" },
2244
    { 0x7951,                               "Change at the SYNC module without Power On" },
2245
    { 0x7952,                               "SYNC module removed" },
2246
    { 0x7953,                               "Change at the SYNC-module without reset" },
2247
    { 0x7954,                               "SYNC module: rack number assigned twice" },
2248
    { 0x7955,                               "SYNC module error" },
2249
    { 0x7956,                               "Illegal rack number set on SYNC module" },
2250
    { 0x7960,                               "Redundant I/O: Time-out of discrepancy time at digital input, error is not yet localized" },
2251
    { 0x7961,                               "Redundant I/O, digital input error: Signal change after expiration of the discrepancy time" },
2252
    { 0x7962,                               "Redundant I/O: Digital input error" },
2253
    { 0x796F,                               "Redundant I/O: The I/O was globally disabled" },
2254
    { 0x7970,                               "Redundant I/O: Digital output error" },
2255
    { 0x7980,                               "Redundant I/O: Time-out of discrepancy time at analog input" },
2256
    { 0x7981,                               "Redundant I/O: Analog input error" },
2257
    { 0x7990,                               "Redundant I/O: Analog output error" },
2258
    { 0x79D3,                               "Communication error between PROFIsafe and F I/O" },
2259
    { 0x79D4,                               "Error in safety relevant communication between F CPUs" },
2260
    { 0x79D5,                               "Error in safety relevant communication between F CPUs" },
2261
    { 0x79E3,                               "F-I/O device input channel passivated" },
2262
    { 0x79E4,                               "F-I/O device output channel passivated" },
2263
    { 0x79E5,                               "F-I/O device passivated" },
2264
    { 0x79E6,                               "Inconsistent safety program" },
2265
    { 0x79E7,                               "Simulation block (F system block) loaded" },
2266
    { 0,                                    NULL }
2267
};
2268
static value_string_ext cpu_diag_eventid_fix_names_ext = VALUE_STRING_EXT_INIT(cpu_diag_eventid_fix_names);
2269
2270
static const value_string cpu_diag_eventid_0x8_0x9_names[] = {
2271
    { 0x8000,                               "Module fault/OK" },
2272
    { 0x8001,                               "Internal error" },
2273
    { 0x8002,                               "External error" },
2274
    { 0x8003,                               "Channel error" },
2275
    { 0x8004,                               "No external auxiliary voltage" },
2276
    { 0x8005,                               "No front connector" },
2277
    { 0x8006,                               "No parameter assignment" },
2278
    { 0x8007,                               "Incorrect parameters in module" },
2279
    { 0x8030,                               "User submodule incorrect/not found" },
2280
    { 0x8031,                               "Communication problem" },
2281
    { 0x8032,                               "Operating mode: RUN/STOP (STOP: entering state, RUN: leaving state)" },
2282
    { 0x8033,                               "Time monitoring responded (watchdog)" },
2283
    { 0x8034,                               "Internal module power failure" },
2284
    { 0x8035,                               "BATTF: battery exhausted" },
2285
    { 0x8036,                               "Total backup failed" },
2286
    { 0x8040,                               "Expansion rack failed" },
2287
    { 0x8041,                               "Processor failure" },
2288
    { 0x8042,                               "EPROM error" },
2289
    { 0x8043,                               "RAM error" },
2290
    { 0x8044,                               "ADC/DAC error" },
2291
    { 0x8045,                               "Fuse blown" },
2292
    { 0x8046,                               "Hardware interrupt lost Any" },
2293
    { 0x8050,                               "Configuration/parameter assignment error" },
2294
    { 0x8051,                               "Common mode error" },
2295
    { 0x8052,                               "Short circuit to phase" },
2296
    { 0x8053,                               "Short circuit to ground" },
2297
    { 0x8054,                               "Wire break" },
2298
    { 0x8055,                               "Reference channel error" },
2299
    { 0x8056,                               "Below measuring range" },
2300
    { 0x8057,                               "Above measuring range Analog input" },
2301
    { 0x8060,                               "Configuration/parameter assignment error" },
2302
    { 0x8061,                               "Common mode error" },
2303
    { 0x8062,                               "Short circuit to phase" },
2304
    { 0x8063,                               "Short circuit to ground" },
2305
    { 0x8064,                               "Wire break" },
2306
    { 0x8066,                               "No load voltage" },
2307
    { 0x8070,                               "Configuration/parameter assignment error" },
2308
    { 0x8071,                               "Chassis ground fault" },
2309
    { 0x8072,                               "Short circuit to phase (sensor)" },
2310
    { 0x8073,                               "Short circuit to ground (sensor)" },
2311
    { 0x8074,                               "Wire break" },
2312
    { 0x8075,                               "No sensor power supply Digital input" },
2313
    { 0x8080,                               "Configuration/parameter assignment error" },
2314
    { 0x8081,                               "Chassis ground fault" },
2315
    { 0x8082,                               "Short circuit to phase" },
2316
    { 0x8083,                               "Short circuit to ground" },
2317
    { 0x8084,                               "Wire break" },
2318
    { 0x8085,                               "Fuse tripped" },
2319
    { 0x8086,                               "No load voltage" },
2320
    { 0x8087,                               "Excess temperature Digital output" },
2321
    { 0x80B0,                               "Counter module, signal A faulty" },
2322
    { 0x80B1,                               "Counter module, signal B faulty" },
2323
    { 0x80B2,                               "Counter module, signal N faulty" },
2324
    { 0x80B3,                               "Counter module, incorrect value passed between the channels" },
2325
    { 0x80B4,                               "Counter module, 5.2 V sensor supply faulty" },
2326
    { 0x80B5,                               "Counter module, 24 V sensor supply faulty" },
2327
    { 0x9001,                               "Automatic/Manual mode (coming=man,going=auto)" },
2328
    { 0x9002,                               "OPEN/CLOSED, ON/OFF" },
2329
    { 0x9003,                               "Manual command enable" },
2330
    { 0x9004,                               "Unit protective command (OPEN/CLOSED)" },
2331
    { 0x9005,                               "Process enable" },
2332
    { 0x9006,                               "System protection command" },
2333
    { 0x9007,                               "Process value monitoring responded" },
2334
    { 0x9008,                               "Manipulated variable monitoring responded" },
2335
    { 0x9009,                               "System deviation greater than permitted" },
2336
    { 0x900A,                               "Limit position error" },
2337
    { 0x900B,                               "Runtime error" },
2338
    { 0x900C,                               "Command execution error (sequencer)" },
2339
    { 0x900D,                               "Operating status running > OPEN" },
2340
    { 0x900E,                               "Operating status running > CLOSED" },
2341
    { 0x900F,                               "Command blocking" },
2342
    { 0x9011,                               "Process status OPEN/ON" },
2343
    { 0x9012,                               "Process status CLOSED/OFF" },
2344
    { 0x9013,                               "Process status intermediate position" },
2345
    { 0x9014,                               "Process status ON via AUTO" },
2346
    { 0x9015,                               "Process status ON via manual" },
2347
    { 0x9016,                               "Process status ON via protective command" },
2348
    { 0x9017,                               "Process status OFF via AUTO" },
2349
    { 0x9018,                               "Process status OFF via manual" },
2350
    { 0x9019,                               "Process status OFF via protective command" },
2351
    { 0x9021,                               "Function error on approach" },
2352
    { 0x9022,                               "Function error on leaving" },
2353
    { 0x9031,                               "Actuator (DE/WE) limit position OPEN" },
2354
    { 0x9032,                               "Actuator (DE/WE) limit position not OPEN" },
2355
    { 0x9033,                               "Actuator (DE/WE) limit position CLOSED" },
2356
    { 0x9034,                               "Actuator (DE/WE) limit position not CLOSED" },
2357
    { 0x9041,                               "Illegal status, tolerance time elapsed" },
2358
    { 0x9042,                               "Illegal status, tolerance time not elapsed" },
2359
    { 0x9043,                               "Interlock error, tolerance time = 0" },
2360
    { 0x9044,                               "Interlock error, tolerance time > 0" },
2361
    { 0x9045,                               "No reaction" },
2362
    { 0x9046,                               "Final status exited illegally, tolerance time = 0" },
2363
    { 0x9047,                               "Final status exited illegally, tolerance time > 0" },
2364
    { 0x9050,                               "Upper limit of signal range USR" },
2365
    { 0x9051,                               "Upper limit of measuring range UMR" },
2366
    { 0x9052,                               "Lower limit of signal range LSR" },
2367
    { 0x9053,                               "Lower limit of measuring range LMR" },
2368
    { 0x9054,                               "Upper alarm limit UAL" },
2369
    { 0x9055,                               "Upper warning limit UWL" },
2370
    { 0x9056,                               "Upper tolerance limit UTL" },
2371
    { 0x9057,                               "Lower tolerance limit LTL" },
2372
    { 0x9058,                               "Lower warning limit LWL" },
2373
    { 0x9059,                               "Lower alarm limit LAL" },
2374
    { 0x9060,                               "GRAPH7 step entering/leaving" },
2375
    { 0x9061,                               "GRAPH7 interlock error" },
2376
    { 0x9062,                               "GRAPH7 execution error" },
2377
    { 0x9063,                               "GRAPH7 error noted" },
2378
    { 0x9064,                               "GRAPH7 error acknowledged" },
2379
    { 0x9070,                               "Trend exceeded in positive direction" },
2380
    { 0x9071,                               "Trend exceeded in negative direction" },
2381
    { 0x9072,                               "No reaction" },
2382
    { 0x9073,                               "Final state exited illegally" },
2383
    { 0x9080,                               "Limit value exceeded, tolerance time = 0" },
2384
    { 0x9081,                               "Limit value exceeded, tolerance time > 0" },
2385
    { 0x9082,                               "Below limit value, tolerance time = 0" },
2386
    { 0x9083,                               "Below limit value, tolerance time > 0" },
2387
    { 0x9084,                               "Gradient exceeded, tolerance time = 0" },
2388
    { 0x9085,                               "Gradient exceeded, tolerance time > 0" },
2389
    { 0x9086,                               "Below gradient, tolerance time = 0" },
2390
    { 0x9087,                               "Below gradient, tolerance time > 0" },
2391
    { 0x9090,                               "User parameter assignment error entering/leaving" },
2392
    { 0x90F0,                               "Overflow" },
2393
    { 0x90F1,                               "Underflow" },
2394
    { 0x90F2,                               "Division by 0" },
2395
    { 0x90F3,                               "Illegal calculation operation" },
2396
    { 0,                                    NULL }
2397
};
2398
static value_string_ext cpu_diag_eventid_0x8_0x9_names_ext = VALUE_STRING_EXT_INIT(cpu_diag_eventid_0x8_0x9_names);
2399
2400
/**************************************************************************
2401
 * Type of alarmquery in alarm query request
2402
 */
2403
0
#define S7COMM_ALARM_MESSAGE_QUERYTYPE_BYALARMTYPE      1
2404
0
#define S7COMM_ALARM_MESSAGE_QUERYTYPE_BYEVENTID        3
2405
2406
static const value_string alarm_message_querytype_names[] = {
2407
    { S7COMM_ALARM_MESSAGE_QUERYTYPE_BYALARMTYPE,      "ByAlarmtype" },
2408
    { S7COMM_ALARM_MESSAGE_QUERYTYPE_BYEVENTID,        "ByEventID" },
2409
    { 0,                                                NULL }
2410
};
2411
2412
/**************************************************************************
2413
 * Alarmtype in alarm query
2414
 */
2415
#define S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_SCAN       1
2416
#define S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_8    2
2417
20
#define S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_S    4
2418
2419
static const value_string alarm_message_query_alarmtype_names[] = {
2420
    { S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_SCAN,        "SCAN" },
2421
    { S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_8,     "ALARM_8" },
2422
    { S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_S,     "ALARM_S" },
2423
    { 0,                                                NULL }
2424
};
2425
2426
/* CPU message service */
2427
static int hf_s7comm_cpu_msgservice_subscribe_events;
2428
static int hf_s7comm_cpu_msgservice_subscribe_events_modetrans;
2429
static int hf_s7comm_cpu_msgservice_subscribe_events_system;
2430
static int hf_s7comm_cpu_msgservice_subscribe_events_userdefined;
2431
static int hf_s7comm_cpu_msgservice_subscribe_events_alarms;
2432
static int ett_s7comm_cpu_msgservice_subscribe_events;
2433
static int * const s7comm_cpu_msgservice_subscribe_events_fields[] = {
2434
    &hf_s7comm_cpu_msgservice_subscribe_events_modetrans,
2435
    &hf_s7comm_cpu_msgservice_subscribe_events_system,
2436
    &hf_s7comm_cpu_msgservice_subscribe_events_userdefined,
2437
    &hf_s7comm_cpu_msgservice_subscribe_events_alarms,
2438
    NULL
2439
};
2440
static int hf_s7comm_cpu_msgservice_req_reserved1;
2441
static int hf_s7comm_cpu_msgservice_username;
2442
static int hf_s7comm_cpu_msgservice_almtype;
2443
static int hf_s7comm_cpu_msgservice_req_reserved2;
2444
static int hf_s7comm_cpu_msgservice_res_result;
2445
static int hf_s7comm_cpu_msgservice_res_reserved1;
2446
static int hf_s7comm_cpu_msgservice_res_reserved2;
2447
static int hf_s7comm_cpu_msgservice_res_reserved3;
2448
2449
#define S7COMM_CPU_MSG_ALMTYPE_SCAN_ABORT               0
2450
#define S7COMM_CPU_MSG_ALMTYPE_SCAN_INITIATE            1
2451
#define S7COMM_CPU_MSG_ALMTYPE_ALARM_ABORT              4
2452
#define S7COMM_CPU_MSG_ALMTYPE_ALARM_INITIATE           5
2453
13
#define S7COMM_CPU_MSG_ALMTYPE_AR_SEND_ABORT            6
2454
28
#define S7COMM_CPU_MSG_ALMTYPE_AR_SEND_INITIATE         7
2455
#define S7COMM_CPU_MSG_ALMTYPE_ALARM_S_ABORT            8
2456
#define S7COMM_CPU_MSG_ALMTYPE_ALARM_S_INITIATE         9
2457
2458
static const value_string cpu_msgservice_almtype_names[] = {
2459
    { S7COMM_CPU_MSG_ALMTYPE_SCAN_ABORT,                "SCAN_ABORT" },
2460
    { S7COMM_CPU_MSG_ALMTYPE_SCAN_INITIATE,             "SCAN_INITIATE" },
2461
    { S7COMM_CPU_MSG_ALMTYPE_ALARM_ABORT,               "ALARM_ABORT" },
2462
    { S7COMM_CPU_MSG_ALMTYPE_ALARM_INITIATE,            "ALARM_INITIATE" },
2463
    { S7COMM_CPU_MSG_ALMTYPE_AR_SEND_ABORT,             "AR_SEND_ABORT" },
2464
    { S7COMM_CPU_MSG_ALMTYPE_AR_SEND_INITIATE,          "AR_SEND_INITIATE" },
2465
    { S7COMM_CPU_MSG_ALMTYPE_ALARM_S_ABORT,             "ALARM_S_ABORT" },
2466
    { S7COMM_CPU_MSG_ALMTYPE_ALARM_S_INITIATE,          "ALARM_S_INITIATE" },
2467
    { 0,                                                NULL }
2468
};
2469
2470
static int hf_s7comm_modetrans_param_unknown1;
2471
static int hf_s7comm_modetrans_param_mode;
2472
static const value_string modetrans_param_mode_names[] = {
2473
    { 0,                                    "STOP" },
2474
    { 1,                                    "Warm Restart" },
2475
    { 2,                                    "RUN" },
2476
    { 3,                                    "Hot Restart" },
2477
    { 4,                                    "HOLD" },
2478
    { 6,                                    "Cold Restart" },
2479
    { 9,                                    "RUN_R (H-System redundant)" },
2480
    { 11,                                   "LINK-UP" },
2481
    { 12,                                   "UPDATE" },
2482
    { 0,                                    NULL }
2483
};
2484
static int hf_s7comm_modetrans_param_unknown2;
2485
2486
/* These fields used when reassembling S7COMM fragments */
2487
static int hf_s7comm_fragments;
2488
static int hf_s7comm_fragment;
2489
static int hf_s7comm_fragment_overlap;
2490
static int hf_s7comm_fragment_overlap_conflict;
2491
static int hf_s7comm_fragment_multiple_tails;
2492
static int hf_s7comm_fragment_too_long_fragment;
2493
static int hf_s7comm_fragment_error;
2494
static int hf_s7comm_fragment_count;
2495
static int hf_s7comm_reassembled_in;
2496
static int hf_s7comm_reassembled_length;
2497
static int ett_s7comm_fragment;
2498
static int ett_s7comm_fragments;
2499
2500
static const fragment_items s7comm_frag_items = {
2501
    /* Fragment subtrees */
2502
    &ett_s7comm_fragment,
2503
    &ett_s7comm_fragments,
2504
    /* Fragment fields */
2505
    &hf_s7comm_fragments,
2506
    &hf_s7comm_fragment,
2507
    &hf_s7comm_fragment_overlap,
2508
    &hf_s7comm_fragment_overlap_conflict,
2509
    &hf_s7comm_fragment_multiple_tails,
2510
    &hf_s7comm_fragment_too_long_fragment,
2511
    &hf_s7comm_fragment_error,
2512
    &hf_s7comm_fragment_count,
2513
    /* Reassembled in field */
2514
    &hf_s7comm_reassembled_in,
2515
    /* Reassembled length field */
2516
    &hf_s7comm_reassembled_length,
2517
    /* Reassembled data field */
2518
    NULL,
2519
    /* Tag */
2520
    "S7COMM fragments"
2521
};
2522
2523
static reassembly_table s7comm_reassembly_table;
2524
2525
/* These are the ids of the subtrees that we are creating */
2526
static int ett_s7comm;                                        /* S7 communication tree, parent of all other subtree */
2527
static int ett_s7comm_header;                                 /* Subtree for header block */
2528
static int ett_s7comm_param;                                  /* Subtree for parameter block */
2529
static int ett_s7comm_param_item;                             /* Subtree for items in parameter block */
2530
static int ett_s7comm_param_subitem;                          /* Subtree for subitems under items in parameter block */
2531
static int ett_s7comm_data;                                   /* Subtree for data block */
2532
static int ett_s7comm_data_item;                              /* Subtree for an item in data block */
2533
static int ett_s7comm_item_address;                           /* Subtree for an address (byte/bit) */
2534
static int ett_s7comm_cpu_alarm_message;                      /* Subtree for an alarm message */
2535
static int ett_s7comm_cpu_alarm_message_object;               /* Subtree for an alarm message block*/
2536
static int ett_s7comm_cpu_alarm_message_timestamp;            /* Subtree for an alarm message timestamp */
2537
static int ett_s7comm_cpu_alarm_message_associated_value;     /* Subtree for an alarm message associated value */
2538
static int ett_s7comm_cpu_diag_msg;                           /* Subtree for a CPU diagnostic message */
2539
static int ett_s7comm_prog_parameter;
2540
static int ett_s7comm_prog_data;
2541
2542
static const char mon_names[][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
2543
2544
/*******************************************************************************************************
2545
 *
2546
 * Converts a siemens special timestamp to a string of 25+1 bytes length (e.g. "Apr 15, 2009 12:49:30.520").
2547
 * The timestamp is 6 bytes long, one word is the number of days since 1.1.1984, and 4 bytes milliseconds of the day
2548
 *
2549
 *******************************************************************************************************/
2550
static void
2551
s7comm_get_timestring_from_s7time(tvbuff_t *tvb, unsigned offset, char *str, int max)
2552
0
{
2553
0
    uint16_t days;
2554
0
    uint32_t day_msec;
2555
0
    struct tm *mt;
2556
0
    time_t t;
2557
2558
0
    day_msec = tvb_get_ntohl(tvb, offset);
2559
0
    days = tvb_get_ntohs(tvb, offset + 4);
2560
2561
0
    t = 441763200L;             /* 1.1.1984 00:00:00 */
2562
0
    t += (uint32_t)days * (24*60*60);
2563
0
    t += day_msec / 1000;
2564
0
    mt = gmtime(&t);
2565
0
    str[0] = '\0';
2566
0
    if (mt != NULL) {
2567
0
        snprintf(str, max, "%s %2d, %d %02d:%02d:%02d.%03d", mon_names[mt->tm_mon], mt->tm_mday,
2568
0
            mt->tm_year + 1900, mt->tm_hour, mt->tm_min, mt->tm_sec, day_msec % 1000);
2569
0
    }
2570
0
}
2571
2572
/*******************************************************************************************************
2573
 *
2574
 * Helper for time functions
2575
 * Get int from bcd
2576
 *
2577
 *******************************************************************************************************/
2578
static uint8_t
2579
s7comm_uint8_from_bcd(uint8_t i)
2580
376
{
2581
376
    return 10 * (i /16) + (i % 16);
2582
376
}
2583
2584
/*******************************************************************************************************
2585
 *
2586
 * Helper for time functions
2587
 * Add a BCD coded timestamp (10/8 Bytes length) to tree
2588
 *
2589
 *******************************************************************************************************/
2590
static uint32_t
2591
s7comm_add_timestamp_to_tree(tvbuff_t *tvb,
2592
                             proto_tree *tree,
2593
                             uint32_t offset,
2594
                             bool append_text,
2595
                             bool has_ten_bytes)          /* if this is false the [0] reserved and [1] year bytes are missing */
2596
47
{
2597
47
    uint8_t timestamp[10];
2598
47
    uint8_t i;
2599
47
    uint8_t tmp;
2600
47
    uint8_t year_org;
2601
47
    uint16_t msec;
2602
47
    nstime_t tv;
2603
47
    proto_item *item = NULL;
2604
47
    proto_item *time_tree = NULL;
2605
47
    struct tm mt;
2606
47
    int timestamp_size = 10;
2607
2608
47
    if (has_ten_bytes) {
2609
        /* The low nibble of byte 10 is weekday, the high nibble the LSD of msec */
2610
0
        for (i = 0; i < 9; i++) {
2611
0
            timestamp[i] = s7comm_uint8_from_bcd(tvb_get_uint8(tvb, offset + i));
2612
0
        }
2613
0
        tmp = tvb_get_uint8(tvb, offset + 9) >> 4;
2614
47
    } else {
2615
        /* this is a 8 byte timestamp, where the reserved and the year byte is missing */
2616
47
        timestamp_size = 8;
2617
47
        timestamp[0] = 0;
2618
47
        timestamp[1] = 19;  /* start with 19.., will be corrected later */
2619
376
        for (i = 0; i < 7; i++) {
2620
329
            timestamp[i + 2] = s7comm_uint8_from_bcd(tvb_get_uint8(tvb, offset + i));
2621
329
        }
2622
47
        tmp = tvb_get_uint8(tvb, offset + 7) >> 4;
2623
47
    }
2624
47
    timestamp[9] = s7comm_uint8_from_bcd(tmp);
2625
2626
47
    msec = (uint16_t)timestamp[8] * 10 + (uint16_t)timestamp[9];
2627
47
    year_org = timestamp[1];
2628
    /* year special: ignore the first byte, since some cpus give 1914 for 2014
2629
     * if second byte is below 89, it's 2000..2089, if over 90 it's 1990..1999
2630
     */
2631
47
    if (timestamp[2] < 89) {
2632
19
        timestamp[1] = 20;
2633
19
    }
2634
    /* convert time to nstime_t */
2635
47
    mt.tm_year = (timestamp[1] * 100 + timestamp[2]) - 1900;
2636
47
    mt.tm_mon = timestamp[3] - 1;
2637
47
    mt.tm_mday = timestamp[4];
2638
47
    mt.tm_hour = timestamp[5];
2639
47
    mt.tm_min = timestamp[6];
2640
47
    mt.tm_sec = timestamp[7];
2641
47
    mt.tm_isdst = -1;
2642
47
    tv.secs = mktime(&mt);
2643
47
    tv.nsecs = msec * 1000000;
2644
47
    if (mt.tm_mon >= 0 && mt.tm_mon <= 11) {
2645
47
        item = proto_tree_add_time_format_value(tree, hf_s7comm_data_ts, tvb, offset, timestamp_size, &tv,
2646
47
            "%s %2d, %d %02d:%02d:%02d.%03d", mon_names[mt.tm_mon], mt.tm_mday,
2647
47
            mt.tm_year + 1900, mt.tm_hour, mt.tm_min, mt.tm_sec,
2648
47
            msec);
2649
47
        time_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
2650
2651
        /* timefunction: s7 timestamp */
2652
47
        if (has_ten_bytes) {
2653
0
            proto_tree_add_uint(time_tree, hf_s7comm_data_ts_reserved, tvb, offset, 1, timestamp[0]);
2654
0
            offset += 1;
2655
0
            proto_tree_add_uint(time_tree, hf_s7comm_data_ts_year1, tvb, offset, 1, year_org);
2656
0
            offset += 1;
2657
0
        }
2658
47
        proto_tree_add_uint(time_tree, hf_s7comm_data_ts_year2, tvb, offset, 1, timestamp[2]);
2659
47
        offset += 1;
2660
47
        proto_tree_add_uint(time_tree, hf_s7comm_data_ts_month, tvb, offset, 1, timestamp[3]);
2661
47
        offset += 1;
2662
47
        proto_tree_add_uint(time_tree, hf_s7comm_data_ts_day, tvb, offset, 1, timestamp[4]);
2663
47
        offset += 1;
2664
47
        proto_tree_add_uint(time_tree, hf_s7comm_data_ts_hour, tvb, offset, 1, timestamp[5]);
2665
47
        offset += 1;
2666
47
        proto_tree_add_uint(time_tree, hf_s7comm_data_ts_minute, tvb, offset, 1, timestamp[6]);
2667
47
        offset += 1;
2668
47
        proto_tree_add_uint(time_tree, hf_s7comm_data_ts_second, tvb, offset, 1, timestamp[7]);
2669
47
        offset += 1;
2670
47
        proto_tree_add_uint(time_tree, hf_s7comm_data_ts_millisecond, tvb, offset, 2, msec);
2671
47
        proto_tree_add_item(time_tree, hf_s7comm_data_ts_weekday, tvb, offset, 2, ENC_BIG_ENDIAN);
2672
47
        offset += 2;
2673
2674
47
        if (append_text == true) {
2675
47
            proto_item_append_text(tree, "(Timestamp: %s %2d, %d %02d:%02d:%02d.%03d)", mon_names[mt.tm_mon], mt.tm_mday,
2676
47
                mt.tm_year + 1900, mt.tm_hour, mt.tm_min, mt.tm_sec,
2677
47
                msec);
2678
47
        }
2679
47
    } else {
2680
        /* If the timestamp is invalid, continue as best as we can */
2681
0
        if (has_ten_bytes) {
2682
0
            offset += 10;
2683
0
        }
2684
0
        else {
2685
0
            offset += 8;
2686
0
        }
2687
0
    }
2688
47
    return offset;
2689
47
}
2690
2691
/*******************************************************************************************************
2692
 *
2693
 * Generate a comma separated string for registerflags
2694
 *
2695
 *******************************************************************************************************/
2696
static void
2697
make_registerflag_string(char *str, uint8_t flags, int max)
2698
3.09k
{
2699
3.09k
    (void) g_strlcpy(str, "", max);
2700
3.09k
    if (flags & 0x01) (void) g_strlcat(str, "STW, ", max);
2701
3.09k
    if (flags & 0x02) (void) g_strlcat(str, "ACCU1, ", max);
2702
3.09k
    if (flags & 0x04) (void) g_strlcat(str, "ACCU2, ", max);
2703
3.09k
    if (flags & 0x08) (void) g_strlcat(str, "AR1, ", max);
2704
3.09k
    if (flags & 0x10) (void) g_strlcat(str, "AR2, ", max);
2705
3.09k
    if (flags & 0x20) (void) g_strlcat(str, "DB1, ", max);
2706
3.09k
    if (flags & 0x40) (void) g_strlcat(str, "DB2, ", max);
2707
3.09k
    if (strlen(str) > 2)
2708
2.50k
        str[strlen(str) - 2 ] = '\0';
2709
3.09k
}
2710
2711
/*******************************************************************************************************
2712
 *
2713
 * Addressdefinition for Syntax ID S7-ANY (Step 7 Classic 300/400 or 1200/1500 not optimized)
2714
 * type == 0x12, length == 10, syntax-ID == 0x10
2715
 *
2716
 *******************************************************************************************************/
2717
static uint32_t
2718
s7comm_syntaxid_s7any(tvbuff_t *tvb, packet_info* pinfo, uint32_t offset, proto_tree *tree)
2719
0
{
2720
0
    uint32_t t_size = 0;
2721
0
    uint32_t len = 0;
2722
0
    uint32_t db = 0;
2723
0
    uint32_t area = 0;
2724
0
    uint32_t a_address = 0;
2725
0
    uint32_t bytepos = 0;
2726
0
    uint32_t bitpos = 0;
2727
0
    proto_item *address_item = NULL;
2728
0
    proto_tree *address_item_tree = NULL;
2729
2730
    /* Transport size, 1 byte */
2731
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_item_transport_size, tvb, offset, 1, ENC_BIG_ENDIAN, &t_size);
2732
0
    offset += 1;
2733
    /* Special handling of data record */
2734
0
    area = tvb_get_uint8(tvb, offset + 4);     /* peek area first */
2735
0
    if (area == S7COMM_AREA_DATARECORD) {
2736
        /* MLEN, 2 bytes */
2737
0
        proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_mlen, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
2738
0
        offset += 2;
2739
        /* INDEX, 2 bytes */
2740
0
        proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_index, tvb, offset, 2, ENC_BIG_ENDIAN, &db);
2741
0
        offset += 2;
2742
        /* Area, 1 byte */
2743
0
        proto_tree_add_uint(tree, hf_s7comm_item_area, tvb, offset, 1, area);
2744
0
        offset += 1;
2745
        /* ID, 3 bytes */
2746
0
        proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_id, tvb, offset, 3, ENC_BIG_ENDIAN, &a_address);
2747
0
        offset += 3;
2748
0
        proto_item_append_text(tree, " (RECORD MLEN=%d INDEX=0x%04x ID=%d)", len, db, a_address);
2749
0
    } else {
2750
        /* Length, 2 bytes */
2751
0
        proto_tree_add_item_ret_uint(tree, hf_s7comm_item_length, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
2752
0
        offset += 2;
2753
        /* DB number, 2 bytes */
2754
0
        proto_tree_add_item_ret_uint(tree, hf_s7comm_item_db, tvb, offset, 2, ENC_BIG_ENDIAN, &db);
2755
0
        offset += 2;
2756
        /* Area, 1 byte */
2757
0
        proto_tree_add_uint(tree, hf_s7comm_item_area, tvb, offset, 1, area);
2758
0
        offset += 1;
2759
        /* Address, 3 bytes */
2760
0
        address_item = proto_tree_add_item_ret_uint(tree, hf_s7comm_item_address, tvb, offset, 3, ENC_BIG_ENDIAN, &a_address);
2761
0
        address_item_tree = proto_item_add_subtree(address_item, ett_s7comm_item_address);
2762
0
        bytepos = a_address / 8;
2763
0
        bitpos = a_address % 8;
2764
        /* build a full address to show item data directly beside the item */
2765
0
        proto_item_append_text(tree, " (%s", val_to_str(pinfo->pool, area, item_areanames_short, "unknown area 0x%02x"));
2766
0
        if (area == S7COMM_AREA_TIMER || area == S7COMM_AREA_COUNTER) {
2767
0
            proto_item_append_text(tree, " %d)", a_address);
2768
0
            proto_tree_add_uint(address_item_tree, hf_s7comm_item_address_nr, tvb, offset, 3, a_address);
2769
0
        } else {
2770
0
            proto_tree_add_uint(address_item_tree, hf_s7comm_item_address_byte, tvb, offset, 3, a_address);
2771
0
            proto_tree_add_uint(address_item_tree, hf_s7comm_item_address_bit, tvb, offset, 3, a_address);
2772
0
            if (area == S7COMM_AREA_DB) {
2773
0
                proto_item_append_text(tree, " %d.DBX", db);
2774
0
            } else if (area == S7COMM_AREA_DI) {
2775
0
                proto_item_append_text(tree, " %d.DIX", db);
2776
0
            }
2777
0
            proto_item_append_text(tree, " %d.%d %s %d)",
2778
0
                bytepos, bitpos, val_to_str(pinfo->pool, t_size, item_transportsizenames, "Unknown transport size: 0x%02x"), len);
2779
0
        }
2780
0
        offset += 3;
2781
0
    }
2782
0
    return offset;
2783
0
}
2784
/*******************************************************************************************************
2785
 *
2786
 * Addressdefinition to read a DB area (S7-400 special)
2787
 * type == 0x12, length >= 7, syntax-ID == 0xb0
2788
 *
2789
 *******************************************************************************************************/
2790
static uint32_t
2791
s7comm_syntaxid_dbread(tvbuff_t *tvb,
2792
                       uint32_t offset,
2793
                       proto_tree *tree)
2794
0
{
2795
0
    uint32_t number_of_areas = 0;
2796
0
    uint32_t len = 0;
2797
0
    uint32_t db = 0;
2798
0
    uint32_t bytepos = 0;
2799
0
    uint32_t i;
2800
0
    proto_item *sub_item = NULL;
2801
0
    proto_tree *sub_item_tree = NULL;
2802
2803
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_item_dbread_numareas, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_areas);
2804
0
    proto_item_append_text(tree, " (%d Data-Areas of Syntax-Id DBREAD)", number_of_areas);
2805
0
    offset += 1;
2806
0
    for (i = 0; i < number_of_areas; i++) {
2807
0
        sub_item = proto_tree_add_item(tree, hf_s7comm_param_subitem, tvb, offset, 5, ENC_NA);
2808
0
        sub_item_tree = proto_item_add_subtree(sub_item, ett_s7comm_param_subitem);
2809
0
        proto_tree_add_item_ret_uint(sub_item_tree, hf_s7comm_item_dbread_length, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
2810
0
        offset += 1;
2811
0
        proto_tree_add_item_ret_uint(sub_item_tree, hf_s7comm_item_dbread_db, tvb, offset, 2, ENC_BIG_ENDIAN, &db);
2812
0
        offset += 2;
2813
0
        proto_tree_add_item_ret_uint(sub_item_tree, hf_s7comm_item_dbread_startadr, tvb, offset, 2, ENC_BIG_ENDIAN, &bytepos);
2814
0
        offset += 2;
2815
        /* Display in pseudo S7-Any Format */
2816
0
        proto_item_append_text(sub_item, " [%d]: (DB%d.DBB %d BYTE %d)", i+1, db, bytepos, len);
2817
0
    }
2818
0
    return offset;
2819
0
}
2820
2821
/*******************************************************************************************************
2822
 *
2823
 * Addressdefinition for TIA S7 1200 symbolic address mode
2824
 * type == 0x12, length >= 14, syntax-ID == 0xb2
2825
 *
2826
 *******************************************************************************************************/
2827
static uint32_t
2828
s7comm_syntaxid_1200sym(tvbuff_t *tvb, packet_info* pinfo, uint32_t offset, proto_tree *tree, uint8_t varspec_length)
2829
0
{
2830
0
    uint32_t tia_var_area1 = 0;
2831
0
    uint32_t tia_var_area2 = 0;
2832
0
    uint8_t tia_lid_flags = 0;
2833
0
    uint32_t tia_value = 0;
2834
0
    proto_item *sub_item = NULL;
2835
0
    proto_tree *sub_item_tree = NULL;
2836
2837
0
    proto_item_append_text(tree, " 1200 symbolic address");
2838
    /* first byte in address seems always to be 0xff */
2839
0
    proto_tree_add_item(tree, hf_s7comm_tia1200_item_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
2840
0
    offset += 1;
2841
    /* When Bytes 2/3 == 0, then Bytes 4/5 defines the area as known from classic 300/400 address mode.
2842
     * When Bytes 2/3 == 0x8a0e then Bytes 4/5 are containing the DB number.
2843
     */
2844
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_tia1200_item_area1, tvb, offset, 2, ENC_BIG_ENDIAN, &tia_var_area1);
2845
0
    offset += 2;
2846
0
    tia_var_area2 = tvb_get_ntohs(tvb, offset);
2847
0
    if (tia_var_area1 == S7COMM_TIA1200_VAR_ITEM_AREA1_IQMCT) {
2848
0
        proto_tree_add_uint(tree, hf_s7comm_tia1200_item_area2, tvb, offset, 2, tia_var_area2);
2849
0
        proto_item_append_text(tree, " - Accessing %s", val_to_str(pinfo->pool, tia_var_area2, tia1200_var_item_area2_names, "Unknown IQMCT Area: 0x%04x"));
2850
0
        offset += 2;
2851
0
    } else if (tia_var_area1 == S7COMM_TIA1200_VAR_ITEM_AREA1_DB) {
2852
0
        proto_tree_add_uint(tree, hf_s7comm_tia1200_item_dbnumber, tvb, offset, 2, tia_var_area2);
2853
0
        proto_item_append_text(tree, " - Accessing DB%d", tia_var_area2);
2854
0
        offset += 2;
2855
0
    } else {
2856
        /* for current unknown areas */
2857
0
        proto_tree_add_uint(tree, hf_s7comm_tia1200_item_area2unknown, tvb, offset, 2, tia_var_area2);
2858
0
        proto_item_append_text(tree, " - Unknown area specification");
2859
0
        offset += 2;
2860
0
    }
2861
0
    proto_tree_add_item(tree, hf_s7comm_tia1200_item_crc, tvb, offset, 4, ENC_BIG_ENDIAN);
2862
0
    offset += 4;
2863
2864
0
    for (int i = 0; i < (varspec_length - 10) / 4; i++) {
2865
0
        sub_item = proto_tree_add_item(tree, hf_s7comm_tia1200_substructure_item, tvb, offset, 4, ENC_NA);
2866
0
        sub_item_tree = proto_item_add_subtree(sub_item, ett_s7comm_param_subitem);
2867
0
        tia_lid_flags = tvb_get_uint8(tvb, offset) >> 4;
2868
0
        proto_tree_add_item(sub_item_tree, hf_s7comm_tia1200_var_lid_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
2869
0
        tia_value = tvb_get_ntohl(tvb, offset) & 0x0fffffff;
2870
0
        proto_item_append_text(sub_item, " [%d]: %s, Value: %u", i + 1,
2871
0
            val_to_str(pinfo->pool, tia_lid_flags, tia1200_var_lid_flag_names, "Unknown flags: 0x%02x"),
2872
0
            tia_value
2873
0
        );
2874
0
        proto_tree_add_item(sub_item_tree, hf_s7comm_tia1200_item_value, tvb, offset, 4, ENC_BIG_ENDIAN);
2875
0
        offset += 4;
2876
0
    }
2877
0
    return offset;
2878
0
}
2879
2880
/*******************************************************************************************************
2881
 *
2882
 * Addressdefinition for Sinumeric NCK access
2883
 * type == 0x12, length == 8, syntax-ID == 0x82 or == 0x83 or == 0x84
2884
 *
2885
 *******************************************************************************************************/
2886
static uint32_t
2887
s7comm_syntaxid_nck(tvbuff_t *tvb,
2888
                    uint32_t offset,
2889
                    proto_tree *tree)
2890
0
{
2891
0
    uint32_t area = 0;
2892
0
    uint32_t nck_area = 0;
2893
0
    uint32_t nck_unit = 0;
2894
0
    uint32_t nck_column = 0;
2895
0
    uint32_t nck_line = 0;
2896
0
    uint32_t nck_module = 0;
2897
2898
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_item_nck_areaunit, tvb, offset, 1, ENC_BIG_ENDIAN, &area);
2899
0
    nck_area = area >> 5;
2900
0
    nck_unit = area & 0x1f;
2901
0
    proto_tree_add_item(tree, hf_s7comm_item_nck_area, tvb, offset, 1, ENC_BIG_ENDIAN);
2902
0
    proto_tree_add_item(tree, hf_s7comm_item_nck_unit, tvb, offset, 1, ENC_BIG_ENDIAN);
2903
0
    offset += 1;
2904
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_item_nck_column, tvb, offset, 2, ENC_BIG_ENDIAN, &nck_column);
2905
0
    offset += 2;
2906
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_item_nck_line, tvb, offset, 2, ENC_BIG_ENDIAN, &nck_line);
2907
0
    offset += 2;
2908
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_item_nck_module, tvb, offset, 1, ENC_BIG_ENDIAN, &nck_module);
2909
0
    offset += 1;
2910
0
    proto_tree_add_item(tree, hf_s7comm_item_nck_linecount, tvb, offset, 1, ENC_BIG_ENDIAN);
2911
0
    offset += 1;
2912
0
    proto_item_append_text(tree, " (NCK Area:%d Unit:%d Column:%d Line:%d Module:0x%02x)",
2913
0
        nck_area, nck_unit, nck_column, nck_line, nck_module);
2914
0
    return offset;
2915
0
}
2916
2917
/*******************************************************************************************************
2918
 *
2919
 * Addressdefinition for accessing Multimaster / Sinamics frequency convertes via routing from DriveES.
2920
 * type == 0x12, length == 10, syntax-ID == 0x82
2921
 *
2922
 *******************************************************************************************************/
2923
static uint32_t
2924
s7comm_syntaxid_driveesany(tvbuff_t *tvb,
2925
                           uint32_t offset,
2926
                           proto_tree *tree)
2927
0
{
2928
0
    uint32_t nr = 0;
2929
0
    uint32_t idx = 0;
2930
2931
0
    proto_tree_add_item(tree, hf_s7comm_item_driveesany_unknown1, tvb, offset, 1, ENC_BIG_ENDIAN);
2932
0
    offset += 1;
2933
0
    proto_tree_add_item(tree, hf_s7comm_item_driveesany_unknown2, tvb, offset, 2, ENC_BIG_ENDIAN);
2934
0
    offset += 2;
2935
0
    proto_tree_add_item(tree, hf_s7comm_item_driveesany_unknown3, tvb, offset, 2, ENC_BIG_ENDIAN);
2936
0
    offset += 2;
2937
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_item_driveesany_parameter_nr, tvb, offset, 2, ENC_BIG_ENDIAN, &nr);
2938
0
    offset += 2;
2939
0
    proto_tree_add_item_ret_uint(tree, hf_s7comm_item_driveesany_parameter_idx, tvb, offset, 2, ENC_BIG_ENDIAN, &idx);
2940
0
    offset += 2;
2941
0
    proto_item_append_text(tree, " (DriveES Parameter: %d[%d])", nr, idx);
2942
0
    return offset;
2943
0
}
2944
2945
/*******************************************************************************************************
2946
 *
2947
 * Try for heuristic dissector for the block data (e.g. SDB) and call the data dissector
2948
 *
2949
 *******************************************************************************************************/
2950
static void
2951
s7comm_try_block_data_heuristic(tvbuff_t *tvb,
2952
                               packet_info *pinfo,
2953
                               proto_tree *tree,
2954
                               uint32_t offset,
2955
                               uint8_t function,
2956
                               uint8_t status)
2957
0
{
2958
0
    heur_dtbl_entry_t* hdtbl_entry = NULL;
2959
0
    uint8_t fc[2] = { function , status};
2960
2961
    /* dissect heuristic response data */
2962
0
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
2963
0
        struct tvbuff* next_tvb = tvb_new_subset_remaining(tvb, offset);
2964
2965
        /*no need to call call_data_dissector() if dissector_try_heuristic() returns false*/
2966
0
        (void) dissector_try_heuristic(s7comm_heur_subdissector_list_block_data, next_tvb, pinfo, tree, &hdtbl_entry, fc);
2967
0
    }
2968
0
}
2969
2970
/*******************************************************************************************************
2971
 *
2972
 * Dissect the parameter details of a read/write request (Items)
2973
 *
2974
 *******************************************************************************************************/
2975
static uint32_t
2976
s7comm_decode_param_item(tvbuff_t *tvb, packet_info* pinfo, uint32_t offset, proto_tree *sub_tree, uint8_t item_no)
2977
58
{
2978
58
    proto_item *item = NULL;
2979
58
    proto_tree *item_tree = NULL;
2980
58
    uint8_t var_spec_type = 0;
2981
58
    uint8_t var_spec_length = 0;
2982
58
    uint8_t var_spec_syntax_id = 0;
2983
2984
58
    var_spec_type = tvb_get_uint8(tvb, offset);
2985
58
    var_spec_length = tvb_get_uint8(tvb, offset + 1);
2986
58
    var_spec_syntax_id = tvb_get_uint8(tvb, offset + 2);
2987
2988
    /* Insert a new tree for every item */
2989
58
    item = proto_tree_add_item(sub_tree, hf_s7comm_param_item, tvb, offset, var_spec_length + 2, ENC_NA);
2990
58
    item_tree = proto_item_add_subtree(item, ett_s7comm_param_item);
2991
58
    proto_item_append_text(item, " [%d]:", item_no + 1);
2992
2993
    /* Item head, constant 3 bytes */
2994
58
    proto_tree_add_item(item_tree, hf_s7comm_item_varspec, tvb, offset, 1, ENC_BIG_ENDIAN);
2995
58
    offset += 1;
2996
58
    proto_tree_add_item(item_tree, hf_s7comm_item_varspec_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2997
58
    offset += 1;
2998
58
    proto_tree_add_item(item_tree, hf_s7comm_item_syntax_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2999
58
    offset += 1;
3000
3001
58
    if (var_spec_type == 0x12 && var_spec_length == 10 && var_spec_syntax_id == S7COMM_SYNTAXID_S7ANY) {
3002
        /* Step 7 Classic 300 400 */
3003
0
        offset = s7comm_syntaxid_s7any(tvb, pinfo, offset, item_tree);
3004
58
    } else if (var_spec_type == 0x12 && var_spec_length >= 7 && var_spec_syntax_id == S7COMM_SYNTAXID_DBREAD) {
3005
        /* S7-400 special address mode (kind of cyclic read) */
3006
0
        offset = s7comm_syntaxid_dbread(tvb, offset, item_tree);
3007
58
    } else if (var_spec_type == 0x12 && var_spec_length >= 14 && var_spec_syntax_id == S7COMM_SYNTAXID_1200SYM) {
3008
        /* TIA S7 1200 symbolic address mode */
3009
0
        offset = s7comm_syntaxid_1200sym(tvb, pinfo, offset, item_tree, var_spec_length);
3010
58
    } else if (var_spec_type == 0x12 && var_spec_length == 8
3011
0
               && ((var_spec_syntax_id == S7COMM_SYNTAXID_NCK)
3012
0
                   || (var_spec_syntax_id == S7COMM_SYNTAXID_NCK_METRIC)
3013
0
                   || (var_spec_syntax_id == S7COMM_SYNTAXID_NCK_INCH))) {
3014
        /* Sinumerik NCK access */
3015
0
        offset = s7comm_syntaxid_nck(tvb, offset, item_tree);
3016
58
    } else if (var_spec_type == 0x12 && var_spec_length == 10 && var_spec_syntax_id == S7COMM_SYNTAXID_DRIVEESANY) {
3017
        /* Accessing frequency inverter parameters (via routing) */
3018
0
        offset = s7comm_syntaxid_driveesany(tvb, offset, item_tree);
3019
0
    }
3020
58
    else {
3021
        /* var spec, length and syntax id are still added to tree here */
3022
58
        offset += var_spec_length - 1;
3023
58
        proto_item_append_text(item_tree, " Unknown variable specification");
3024
58
    }
3025
58
    return offset;
3026
58
}
3027
3028
/*******************************************************************************************************
3029
 *
3030
 * Decode parameter part of a PDU for setup communication
3031
 *
3032
 *******************************************************************************************************/
3033
static uint32_t
3034
s7comm_decode_pdu_setup_communication(tvbuff_t *tvb,
3035
                                      proto_tree *tree,
3036
                                      uint32_t offset)
3037
0
{
3038
0
    proto_tree_add_item(tree, hf_s7comm_param_setup_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
3039
0
    offset += 1;
3040
0
    proto_tree_add_item(tree, hf_s7comm_param_maxamq_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
3041
0
    offset += 2;
3042
0
    proto_tree_add_item(tree, hf_s7comm_param_maxamq_called, tvb, offset, 2, ENC_BIG_ENDIAN);
3043
0
    offset += 2;
3044
0
    proto_tree_add_item(tree, hf_s7comm_param_neg_pdu_length, tvb, offset, 2, ENC_BIG_ENDIAN);
3045
0
    offset += 2;
3046
0
    return offset;
3047
0
}
3048
3049
/*******************************************************************************************************
3050
 *
3051
 * PDU Type: Response -> Function Write  -> Data part
3052
 *
3053
 *******************************************************************************************************/
3054
static uint32_t
3055
s7comm_decode_response_write_data(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint8_t item_count, uint32_t offset)
3056
1
{
3057
1
    uint8_t ret_val = 0;
3058
1
    uint8_t i = 0;
3059
1
    proto_item *item = NULL;
3060
1
    proto_tree *item_tree = NULL;
3061
3062
31
    for (i = 0; i < item_count; i++) {
3063
30
        ret_val = tvb_get_uint8(tvb, offset);
3064
        /* Insert a new tree for every item */
3065
30
        item = proto_tree_add_item(tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
3066
30
        item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
3067
30
        proto_item_append_text(item, " [%d]: (%s)", i+1, val_to_str(pinfo->pool, ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
3068
30
        proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
3069
30
        offset += 1;
3070
30
    }
3071
1
    return offset;
3072
1
}
3073
3074
/*******************************************************************************************************
3075
 *
3076
 * PDU Type: Response -> Function Read  -> Data part
3077
 *           Request  -> Function Write -> Data part
3078
 *
3079
 *******************************************************************************************************/
3080
static uint32_t
3081
s7comm_decode_response_read_data(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint8_t item_count, uint32_t offset)
3082
28
{
3083
28
    uint8_t ret_val = 0;
3084
28
    uint8_t tsize = 0;
3085
28
    uint16_t len = 0, len2 = 0;
3086
28
    uint16_t head_len = 4;           /* 1 byte res-code, 1 byte transp-size, 2 bytes len */
3087
28
    uint8_t i = 0;
3088
28
    proto_item *item = NULL;
3089
28
    proto_tree *item_tree = NULL;
3090
3091
    /* Maybe this is only valid for Sinumerik NCK: Pre-check transport-size
3092
     * If transport size is 0x11 or 0x12, then an array with requested NCK areas will follow.
3093
     */
3094
28
    tsize = tvb_get_uint8(tvb, offset + 1);
3095
28
    if (tsize == S7COMM_DATA_TRANSPORT_SIZE_NCKADDR1 || tsize == S7COMM_DATA_TRANSPORT_SIZE_NCKADDR2) {
3096
0
        proto_tree_add_item(tree, hf_s7comm_data_returncode, tvb, offset, 1, ENC_BIG_ENDIAN);
3097
0
        proto_tree_add_uint(tree, hf_s7comm_data_transport_size, tvb, offset + 1, 1, tsize);
3098
0
        offset += 2;
3099
0
        for (i = 0; i < item_count; i++) {
3100
0
            offset = s7comm_decode_param_item(tvb, pinfo, offset, tree, i);
3101
0
        }
3102
28
    } else {
3103
        /* Standard */
3104
406
        for (i = 0; i < item_count; i++) {
3105
378
            ret_val = tvb_get_uint8(tvb, offset);
3106
378
            if (ret_val == S7COMM_ITEM_RETVAL_RESERVED ||
3107
280
                ret_val == S7COMM_ITEM_RETVAL_DATA_OK ||
3108
274
                ret_val == S7COMM_ITEM_RETVAL_DATA_ERR
3109
378
                ) {
3110
114
                tsize = tvb_get_uint8(tvb, offset + 1);
3111
114
                len = tvb_get_ntohs(tvb, offset + 2);
3112
                /* calculate length in bytes */
3113
114
                if (tsize == S7COMM_DATA_TRANSPORT_SIZE_BBIT ||
3114
114
                    tsize == S7COMM_DATA_TRANSPORT_SIZE_BBYTE ||
3115
113
                    tsize == S7COMM_DATA_TRANSPORT_SIZE_BINT
3116
114
                    ) {     /* given length is in number of bits */
3117
1
                    if (len % 8) { /* len is not a multiple of 8, then round up to next number */
3118
1
                        len /= 8;
3119
1
                        len = len + 1;
3120
1
                    } else {
3121
0
                        len /= 8;
3122
0
                    }
3123
1
                }
3124
3125
                /* the PLC places extra bytes at the end of all but last result, if length is not a multiple of 2 */
3126
114
                if ((len % 2) && (i < (item_count-1))) {
3127
16
                    len2 = len + 1;
3128
98
                } else {
3129
98
                    len2 = len;
3130
98
                }
3131
114
            }
3132
            /* Insert a new tree for every item */
3133
378
            item = proto_tree_add_item(tree, hf_s7comm_data_item, tvb, offset, len + head_len, ENC_NA);
3134
378
            item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
3135
378
            proto_item_append_text(item, " [%d]: (%s)", i+1, val_to_str(pinfo->pool, ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
3136
3137
378
            proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
3138
378
            proto_tree_add_uint(item_tree, hf_s7comm_data_transport_size, tvb, offset + 1, 1, tsize);
3139
378
            proto_tree_add_uint(item_tree, hf_s7comm_data_length, tvb, offset + 2, 2, len);
3140
378
            offset += head_len;
3141
3142
378
            if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK || ret_val == S7COMM_ITEM_RETVAL_RESERVED) {
3143
103
                proto_tree_add_item(item_tree, hf_s7comm_readresponse_data, tvb, offset, len, ENC_NA);
3144
103
                offset += len;
3145
103
                if (len != len2) {
3146
9
                    proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
3147
9
                    offset += 1;
3148
9
                }
3149
103
            }
3150
378
        }
3151
28
    }
3152
28
    return offset;
3153
28
}
3154
3155
/*******************************************************************************************************
3156
 *
3157
 * PDU Type: Request or Response -> Function 0x29 (PLC control functions -> STOP)
3158
 *
3159
 *******************************************************************************************************/
3160
static uint32_t
3161
s7comm_decode_plc_controls_param_hex29(tvbuff_t *tvb,
3162
                                       proto_tree *tree,
3163
                                       uint32_t offset)
3164
0
{
3165
0
    uint8_t len;
3166
3167
    /* The first byte 0x29 is checked and inserted to tree outside, so skip it here */
3168
0
    offset += 1;
3169
    /* Meaning of first 5 bytes (Part 1) is unknown */
3170
0
    proto_tree_add_item(tree, hf_s7comm_piservice_unknown1, tvb, offset, 5, ENC_NA);
3171
0
    offset += 5;
3172
    /* Part 2 */
3173
0
    len = tvb_get_uint8(tvb, offset);
3174
0
    proto_tree_add_uint(tree, hf_s7comm_data_plccontrol_part2_len, tvb, offset, 1, len);
3175
0
    offset += 1;
3176
    /* Function as string */
3177
0
    proto_tree_add_item(tree, hf_s7comm_piservice_servicename, tvb, offset, len, ENC_ASCII);
3178
0
    offset += len;
3179
3180
0
    return offset;
3181
0
}
3182
3183
/*******************************************************************************************************
3184
 * PI_START Parameters: Decodes a parameter array with string values.
3185
 *******************************************************************************************************/
3186
static uint32_t
3187
s7comm_decode_pistart_parameters(tvbuff_t *tvb,
3188
                                 packet_info *pinfo,
3189
                                 proto_tree *tree,
3190
                                 proto_tree *param_tree,
3191
                                 const uint8_t *servicename,
3192
                                 uint8_t nfields,      /* number of fields used */
3193
                                 unsigned hf[],          /* array with header fields */
3194
                                 uint32_t offset)
3195
0
{
3196
0
    uint8_t i;
3197
0
    uint8_t len;
3198
0
    wmem_strbuf_t *args_buf;
3199
0
    args_buf = wmem_strbuf_create(pinfo->pool);
3200
3201
0
    for (i = 0; i < nfields; i++) {
3202
0
        len = tvb_get_uint8(tvb, offset);
3203
0
        proto_tree_add_uint(param_tree, hf_s7comm_piservice_string_len, tvb, offset, 1, len);
3204
0
        offset += 1;
3205
0
        proto_tree_add_item(param_tree, hf[i], tvb, offset, len, ENC_ASCII|ENC_NA);
3206
0
        wmem_strbuf_append(args_buf, "\"");
3207
0
        wmem_strbuf_append(args_buf, tvb_format_text(pinfo->pool, tvb, offset, len));
3208
0
        if (i < nfields-1) {
3209
0
            wmem_strbuf_append(args_buf, "\", ");
3210
0
        } else {
3211
0
            wmem_strbuf_append(args_buf, "\"");
3212
0
        }
3213
0
        offset += len + (len % 2 == 0);
3214
0
    }
3215
0
    proto_item_append_text(param_tree, ": (%s)", wmem_strbuf_get_str(args_buf));
3216
0
    proto_item_append_text(tree, " -> %s(%s)", servicename, wmem_strbuf_get_str(args_buf));
3217
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s(%s)", servicename, wmem_strbuf_get_str(args_buf));
3218
3219
0
    return offset;
3220
0
}
3221
3222
/*******************************************************************************************************
3223
 * PI-Service
3224
 *******************************************************************************************************/
3225
static uint32_t
3226
s7comm_decode_pi_service(tvbuff_t *tvb,
3227
                         packet_info *pinfo,
3228
                         proto_tree *tree,
3229
                         uint16_t plength,
3230
                         uint32_t offset)
3231
0
{
3232
0
    uint16_t len, paramlen;
3233
0
    uint32_t startoffset;
3234
0
    uint32_t paramoffset;
3235
0
    uint8_t count;
3236
0
    uint8_t i;
3237
0
    const uint8_t *servicename;
3238
0
    const uint8_t *str;
3239
0
    const uint8_t *str1;
3240
0
    uint16_t blocktype;
3241
0
    unsigned hf[13];
3242
0
    int pi_servicename_idx;
3243
0
    const char *pi_servicename_descr;
3244
3245
0
    proto_item *item = NULL;
3246
0
    proto_item *itemadd = NULL;
3247
0
    proto_tree *param_tree = NULL;
3248
0
    proto_tree *file_tree = NULL;
3249
3250
0
    int32_t num = -1;
3251
0
    bool num_valid;
3252
3253
0
    startoffset = offset;
3254
3255
    /* The first byte is checked and inserted to tree outside, so skip it here */
3256
0
    offset += 1;
3257
3258
    /* First part is unknown, 7 bytes */
3259
0
    proto_tree_add_item(tree, hf_s7comm_piservice_unknown1, tvb, offset, 7, ENC_NA);
3260
0
    offset += 7;
3261
3262
0
    if (offset - startoffset >= plength) {
3263
0
        return offset;
3264
0
    }
3265
    /* Parameter block */
3266
0
    paramlen = tvb_get_ntohs(tvb, offset);
3267
0
    proto_tree_add_uint(tree, hf_s7comm_piservice_parameterblock_len, tvb, offset, 2, paramlen);
3268
0
    offset += 2;
3269
3270
0
    paramoffset = offset;
3271
0
    item = proto_tree_add_item(tree, hf_s7comm_piservice_parameterblock, tvb, offset, paramlen, ENC_NA);
3272
0
    param_tree = proto_item_add_subtree(item, ett_s7comm_piservice_parameterblock);
3273
0
    offset += paramlen;
3274
3275
    /* PI servicename */
3276
0
    len = tvb_get_uint8(tvb, offset);
3277
0
    proto_tree_add_uint(tree, hf_s7comm_piservice_string_len, tvb, offset, 1, len);
3278
0
    offset += 1;
3279
0
    item = proto_tree_add_item_ret_string(tree, hf_s7comm_piservice_servicename, tvb, offset, len, ENC_ASCII|ENC_NA, pinfo->pool, &servicename);
3280
0
    offset += len;
3281
3282
    /* get the index position in pi_service_names, and add infotext with description to the item */
3283
0
    pi_servicename_descr = try_str_to_str_idx((const char*)servicename, pi_service_names, &pi_servicename_idx);
3284
0
    if (pi_servicename_idx < 0) {
3285
0
        pi_servicename_idx = S7COMM_PI_UNKNOWN;
3286
0
        pi_servicename_descr = "Unknown PI Service";
3287
0
    }
3288
0
    proto_item_append_text(item, " [%s]", pi_servicename_descr);
3289
3290
    /* Work parameter data, depending on servicename */
3291
0
    switch (pi_servicename_idx) {
3292
0
        case S7COMM_PI_INSE:
3293
0
        case S7COMM_PI_INS2:
3294
0
        case S7COMM_PI_DELE:
3295
0
            count = tvb_get_uint8(tvb, paramoffset);                   /* number of blocks following */
3296
0
            proto_tree_add_uint(param_tree, hf_s7comm_data_plccontrol_block_cnt, tvb, paramoffset, 1, count);
3297
0
            paramoffset += 1;
3298
            /* Unknown, is always 0x00 */
3299
0
            proto_tree_add_item(param_tree, hf_s7comm_data_pi_inse_unknown, tvb, paramoffset, 1, ENC_BIG_ENDIAN);
3300
0
            paramoffset += 1;
3301
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s(", servicename);
3302
0
            for (i = 0; i < count; i++) {
3303
0
                item = proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_filename, tvb, paramoffset, 8, ENC_ASCII);
3304
0
                file_tree = proto_item_add_subtree(item, ett_s7comm_plcfilename);
3305
0
                blocktype = tvb_get_ntohs(tvb, paramoffset);
3306
0
                itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_block_type, tvb, paramoffset, 2, ENC_ASCII);
3307
0
                proto_item_append_text(itemadd, " (%s)", val_to_str(pinfo->pool, blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3308
0
                paramoffset += 2;
3309
0
                proto_tree_add_item_ret_string(file_tree, hf_s7comm_data_blockcontrol_block_num, tvb, paramoffset, 5, ENC_ASCII|ENC_NA, pinfo->pool, &str);
3310
0
                paramoffset += 5;
3311
0
                num_valid = ws_strtoi32((const char*)str, NULL, &num);
3312
0
                proto_item_append_text(file_tree, " [%s ",
3313
0
                    val_to_str(pinfo->pool, blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3314
0
                col_append_str(pinfo->cinfo, COL_INFO,
3315
0
                    val_to_str(pinfo->pool, blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3316
0
                if (num_valid) {
3317
0
                    proto_item_append_text(file_tree, "%d]", num);
3318
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, "%d", num);
3319
0
                } else {
3320
0
                    expert_add_info(pinfo, file_tree, &ei_s7comm_data_blockcontrol_block_num_invalid);
3321
0
                    proto_item_append_text(file_tree, "NaN]");
3322
0
                    col_append_str(pinfo->cinfo, COL_INFO, "NaN");
3323
0
                }
3324
0
                if (i+1 < count) {
3325
0
                    col_append_str(pinfo->cinfo, COL_INFO, ", ");
3326
0
                }
3327
0
                itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_dest_filesys, tvb, paramoffset, 1, ENC_ASCII);
3328
0
                proto_item_append_text(itemadd, " (%s)", val_to_str_const(tvb_get_uint8(tvb, paramoffset), blocktype_attribute2_names, "Unknown filesys"));
3329
0
                paramoffset += 1;
3330
0
            }
3331
0
            col_append_str(pinfo->cinfo, COL_INFO, ")");
3332
0
            break;
3333
0
        case S7COMM_PIP_PROGRAM:
3334
0
        case S7COMM_PI_MODU:
3335
0
        case S7COMM_PI_GARB:
3336
0
            if (paramlen == 0) {
3337
0
                proto_item_append_text(param_tree, ": ()");
3338
0
                proto_item_append_text(tree, " -> %s()", servicename);
3339
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s()", servicename);
3340
0
            } else {
3341
0
                proto_tree_add_item_ret_string(param_tree, hf_s7comm_data_plccontrol_argument, tvb, paramoffset, paramlen, ENC_ASCII|ENC_NA, pinfo->pool, &str1);
3342
0
                proto_item_append_text(param_tree, ": (\"%s\")", str1);
3343
0
                proto_item_append_text(tree, " -> %s(\"%s\")", servicename, str1);
3344
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s(\"%s\")", servicename, str1);
3345
0
            }
3346
0
            break;
3347
0
        case S7COMM_PI_N_LOGIN_:
3348
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3349
0
            hf[1] = hf_s7comm_pi_n_x_password;
3350
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3351
0
            break;
3352
0
        case S7COMM_PI_N_LOGOUT:
3353
0
        case S7COMM_PI_N_CANCEL:
3354
0
        case S7COMM_PI_N_DASAVE:
3355
0
        case S7COMM_PI_N_DIGIOF:
3356
0
        case S7COMM_PI_N_DIGION:
3357
0
        case S7COMM_PI_N_DZERO_:
3358
0
        case S7COMM_PI_N_ENDEXT:
3359
0
        case S7COMM_PI_N_OST_OF:
3360
0
        case S7COMM_PI_N_OST_ON:
3361
0
        case S7COMM_PI_N_SCALE_:
3362
0
        case S7COMM_PI_N_SETUFR:
3363
0
        case S7COMM_PI_N_STRTLK:
3364
0
        case S7COMM_PI_N_STRTUL:
3365
0
        case S7COMM_PI_N_TMRASS:
3366
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3367
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 1, hf, paramoffset);
3368
0
            break;
3369
0
        case S7COMM_PI_N_F_DELE:
3370
0
        case S7COMM_PI_N_EXTERN:
3371
0
        case S7COMM_PI_N_EXTMOD:
3372
0
        case S7COMM_PI_N_F_DELR:
3373
0
        case S7COMM_PI_N_F_XFER:
3374
0
        case S7COMM_PI_N_LOCKE_:
3375
0
        case S7COMM_PI_N_SELECT:
3376
0
        case S7COMM_PI_N_SRTEXT:
3377
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3378
0
            hf[1] = hf_s7comm_pi_n_x_filename;
3379
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3380
0
            break;
3381
0
        case S7COMM_PI_N_F_CLOS:
3382
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3383
0
            hf[1] = hf_s7comm_pi_n_x_editwindowname;
3384
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3385
0
            break;
3386
0
        case S7COMM_PI_N_F_OPEN:
3387
0
        case S7COMM_PI_N_F_OPER:
3388
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3389
0
            hf[1] = hf_s7comm_pi_n_x_filename;
3390
0
            hf[2] = hf_s7comm_pi_n_x_editwindowname;
3391
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3392
0
            break;
3393
0
        case S7COMM_PI_N_F_SEEK:
3394
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3395
0
            hf[1] = hf_s7comm_pi_n_x_editwindowname;
3396
0
            hf[2] = hf_s7comm_pi_n_x_seekpointer;
3397
0
            hf[3] = hf_s7comm_pi_n_x_windowsize;
3398
0
            hf[4] = hf_s7comm_pi_n_x_comparestring;
3399
0
            hf[5] = hf_s7comm_pi_n_x_skipcount;
3400
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3401
0
            break;
3402
0
        case S7COMM_PI_N_ASUP__:
3403
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3404
0
            hf[1] = hf_s7comm_pi_n_x_interruptnr;
3405
0
            hf[2] = hf_s7comm_pi_n_x_priority;
3406
0
            hf[3] = hf_s7comm_pi_n_x_liftfast;
3407
0
            hf[4] = hf_s7comm_pi_n_x_blsync;
3408
0
            hf[5] = hf_s7comm_pi_n_x_filename;
3409
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3410
0
            break;
3411
0
        case S7COMM_PI_N_CHEKDM:
3412
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3413
0
            hf[1] = hf_s7comm_pi_n_x_magnr;
3414
0
            hf[2] = hf_s7comm_pi_n_x_dnr;
3415
0
            hf[3] = hf_s7comm_pi_n_x_spindlenumber;
3416
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3417
0
            break;
3418
0
        case S7COMM_PI_N_CHKDNO:
3419
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3420
0
            hf[1] = hf_s7comm_pi_n_x_wznr;
3421
0
            hf[2] = hf_s7comm_pi_n_x_wznr;
3422
0
            hf[3] = hf_s7comm_pi_n_x_dnr;
3423
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3424
0
            break;
3425
0
        case S7COMM_PI_N_CONFIG:
3426
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3427
0
            hf[1] = hf_s7comm_pi_n_x_class;
3428
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3429
0
            break;
3430
0
        case S7COMM_PI_N_CRCEDN:
3431
0
        case S7COMM_PI_N_DELECE:
3432
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3433
0
            hf[1] = hf_s7comm_pi_n_x_tnr;
3434
0
            hf[2] = hf_s7comm_pi_n_x_dnr;
3435
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3436
0
            break;
3437
0
        case S7COMM_PI_N_CREACE:
3438
0
        case S7COMM_PI_N_CREATO:
3439
0
        case S7COMM_PI_N_DELETO:
3440
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3441
0
            hf[1] = hf_s7comm_pi_n_x_toolnumber;
3442
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3443
0
            break;
3444
0
        case S7COMM_PI_N_CRTOCE:
3445
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3446
0
            hf[1] = hf_s7comm_pi_n_x_toolnumber;
3447
0
            hf[2] = hf_s7comm_pi_n_x_cenumber;
3448
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3449
0
            break;
3450
0
        case S7COMM_PI_N_DELVAR:
3451
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3452
0
            hf[1] = hf_s7comm_pi_n_x_datablocknumber;
3453
0
            hf[2] = hf_s7comm_pi_n_x_firstcolumnnumber;
3454
0
            hf[3] = hf_s7comm_pi_n_x_lastcolumnnumber;
3455
0
            hf[4] = hf_s7comm_pi_n_x_firstrownumber;
3456
0
            hf[5] = hf_s7comm_pi_n_x_lastrownumber;
3457
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3458
0
            break;
3459
0
        case S7COMM_PI_N_F_COPY:
3460
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3461
0
            hf[1] = hf_s7comm_pi_n_x_direction;
3462
0
            hf[2] = hf_s7comm_pi_n_x_sourcefilename;
3463
0
            hf[3] = hf_s7comm_pi_n_x_destinationfilename;
3464
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3465
0
            break;
3466
0
        case S7COMM_PI_N_F_DMDA:
3467
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3468
0
            hf[1] = hf_s7comm_pi_n_x_channelnumber;
3469
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3470
0
            break;
3471
0
        case S7COMM_PI_N_F_PROR:
3472
0
        case S7COMM_PI_N_F_PROT:
3473
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3474
0
            hf[1] = hf_s7comm_pi_n_x_filename;
3475
0
            hf[2] = hf_s7comm_pi_n_x_protection;
3476
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3477
0
            break;
3478
0
        case S7COMM_PI_N_F_RENA:
3479
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3480
0
            hf[1] = hf_s7comm_pi_n_x_oldfilename;
3481
0
            hf[2] = hf_s7comm_pi_n_x_newfilename;
3482
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3483
0
            break;
3484
0
        case S7COMM_PI_N_FINDBL:
3485
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3486
0
            hf[1] = hf_s7comm_pi_n_x_findmode;
3487
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3488
0
            break;
3489
0
        case S7COMM_PI_N_IBN_SS:
3490
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3491
0
            hf[1] = hf_s7comm_pi_n_x_switch;
3492
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3493
0
            break;
3494
0
        case S7COMM_PI_N_MMCSEM:
3495
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3496
0
            hf[1] = hf_s7comm_pi_n_x_functionnumber;
3497
0
            hf[2] = hf_s7comm_pi_n_x_semaphorevalue;
3498
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3499
0
            break;
3500
0
        case S7COMM_PI_N_NCKMOD:
3501
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3502
0
            hf[1] = hf_s7comm_pi_n_x_onoff;
3503
0
            hf[2] = hf_s7comm_pi_n_x_mode;
3504
0
            hf[3] = hf_s7comm_pi_n_x_factor;
3505
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3506
0
            break;
3507
0
        case S7COMM_PI_N_NEWPWD:
3508
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3509
0
            hf[1] = hf_s7comm_pi_n_x_password;
3510
0
            hf[2] = hf_s7comm_pi_n_x_passwordlevel;
3511
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3512
0
            break;
3513
0
        case S7COMM_PI_N_SEL_BL:
3514
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3515
0
            hf[1] = hf_s7comm_pi_n_x_linenumber;
3516
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3517
0
            break;
3518
0
        case S7COMM_PI_N_SETTST:
3519
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3520
0
            hf[1] = hf_s7comm_pi_n_x_magnr;
3521
0
            hf[2] = hf_s7comm_pi_n_x_weargroup;
3522
0
            hf[3] = hf_s7comm_pi_n_x_toolstatus;
3523
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3524
0
            break;
3525
0
        case S7COMM_PI_N_TMAWCO:
3526
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3527
0
            hf[1] = hf_s7comm_pi_n_x_magnr;
3528
0
            hf[2] = hf_s7comm_pi_n_x_weargroup;
3529
0
            hf[3] = hf_s7comm_pi_n_x_wearsearchstrat;
3530
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3531
0
            break;
3532
0
        case S7COMM_PI_N_TMCRTC:
3533
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3534
0
            hf[1] = hf_s7comm_pi_n_x_toolid;
3535
0
            hf[2] = hf_s7comm_pi_n_x_toolnumber;
3536
0
            hf[3] = hf_s7comm_pi_n_x_duplonumber;
3537
0
            hf[4] = hf_s7comm_pi_n_x_edgenumber;
3538
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 5, hf, paramoffset);
3539
0
            break;
3540
0
        case S7COMM_PI_N_TMCRTO:
3541
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3542
0
            hf[1] = hf_s7comm_pi_n_x_toolid;
3543
0
            hf[2] = hf_s7comm_pi_n_x_toolnumber;
3544
0
            hf[3] = hf_s7comm_pi_n_x_duplonumber;
3545
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3546
0
            break;
3547
0
        case S7COMM_PI_N_TMFDPL:
3548
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3549
0
            hf[1] = hf_s7comm_pi_n_x_toolnumber;
3550
0
            hf[2] = hf_s7comm_pi_n_x_placenr;
3551
0
            hf[3] = hf_s7comm_pi_n_x_magnr;
3552
0
            hf[4] = hf_s7comm_pi_n_x_placerefnr;
3553
0
            hf[5] = hf_s7comm_pi_n_x_magrefnr;
3554
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3555
0
            break;
3556
0
        case S7COMM_PI_N_TMFPBP:
3557
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3558
0
            hf[1] = hf_s7comm_pi_n_x_magnrfrom;
3559
0
            hf[2] = hf_s7comm_pi_n_x_placenrfrom;
3560
0
            hf[3] = hf_s7comm_pi_n_x_magnrto;
3561
0
            hf[4] = hf_s7comm_pi_n_x_placenrto;
3562
0
            hf[5] = hf_s7comm_pi_n_x_magrefnr;
3563
0
            hf[6] = hf_s7comm_pi_n_x_placerefnr;
3564
0
            hf[7] = hf_s7comm_pi_n_x_halfplacesleft;
3565
0
            hf[8] = hf_s7comm_pi_n_x_halfplacesright;
3566
0
            hf[9] = hf_s7comm_pi_n_x_halfplacesup;
3567
0
            hf[10] = hf_s7comm_pi_n_x_halfplacesdown;
3568
0
            hf[11] = hf_s7comm_pi_n_x_placetype;
3569
0
            hf[12] = hf_s7comm_pi_n_x_searchdirection;
3570
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 13, hf, paramoffset);
3571
0
            break;
3572
0
        case S7COMM_PI_N_TMGETT:
3573
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3574
0
            hf[1] = hf_s7comm_pi_n_x_toolname;
3575
0
            hf[2] = hf_s7comm_pi_n_x_duplonumber;
3576
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3577
0
            break;
3578
0
        case S7COMM_PI_N_TMMVTL:
3579
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3580
0
            hf[1] = hf_s7comm_pi_n_x_toolnumber;
3581
0
            hf[2] = hf_s7comm_pi_n_x_placenrsource;
3582
0
            hf[3] = hf_s7comm_pi_n_x_magnrsource;
3583
0
            hf[4] = hf_s7comm_pi_n_x_placenrdestination;
3584
0
            hf[5] = hf_s7comm_pi_n_x_magnrdestination;
3585
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3586
0
            break;
3587
0
        case S7COMM_PI_N_TMPCIT:
3588
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3589
0
            hf[1] = hf_s7comm_pi_n_x_spindlenumber;
3590
0
            hf[2] = hf_s7comm_pi_n_x_incrementnumber;
3591
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3592
0
            break;
3593
0
        case S7COMM_PI_N_TMPOSM:
3594
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3595
0
            hf[1] = hf_s7comm_pi_n_x_toolnumber;
3596
0
            hf[2] = hf_s7comm_pi_n_x_toolid;
3597
0
            hf[3] = hf_s7comm_pi_n_x_duplonumber;
3598
0
            hf[4] = hf_s7comm_pi_n_x_placenrsource;
3599
0
            hf[5] = hf_s7comm_pi_n_x_magnrsource;
3600
0
            hf[6] = hf_s7comm_pi_n_x_placenrdestination;
3601
0
            hf[7] = hf_s7comm_pi_n_x_magnrdestination;
3602
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 8, hf, paramoffset);
3603
0
            break;
3604
0
        case S7COMM_PI_N_TRESMO:
3605
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3606
0
            hf[1] = hf_s7comm_pi_n_x_toolnumber;
3607
0
            hf[2] = hf_s7comm_pi_n_x_dnr;
3608
0
            hf[3] = hf_s7comm_pi_n_x_monitoringmode;
3609
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3610
0
            break;
3611
0
        case S7COMM_PI_N_TSEARC:
3612
0
            hf[0] = hf_s7comm_pi_n_x_addressident;
3613
0
            hf[1] = hf_s7comm_pi_n_x_magnrfrom;
3614
0
            hf[2] = hf_s7comm_pi_n_x_placenrfrom;
3615
0
            hf[3] = hf_s7comm_pi_n_x_magnrto;
3616
0
            hf[4] = hf_s7comm_pi_n_x_placenrto;
3617
0
            hf[5] = hf_s7comm_pi_n_x_magrefnr;
3618
0
            hf[6] = hf_s7comm_pi_n_x_placerefnr;
3619
0
            hf[7] = hf_s7comm_pi_n_x_searchdirection;
3620
0
            hf[8] = hf_s7comm_pi_n_x_kindofsearch;
3621
0
            s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 9, hf, paramoffset);
3622
0
            break;
3623
0
        default:
3624
            /* Don't know how to interpret the parameters, show only the PI servicename */
3625
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]", servicename);
3626
0
    }
3627
0
    return offset;
3628
0
}
3629
3630
/*******************************************************************************************************
3631
 *
3632
 * Decode a blockname/filename used in block/file upload/download
3633
 *
3634
 *******************************************************************************************************/
3635
static uint32_t
3636
s7comm_decode_plc_controls_filename(tvbuff_t *tvb,
3637
                                    packet_info *pinfo,
3638
                                    proto_tree *param_tree,
3639
                                    uint32_t offset)
3640
0
{
3641
0
    uint8_t len;
3642
0
    const uint8_t *str;
3643
0
    uint16_t blocktype;
3644
0
    bool is_plcfilename;
3645
0
    proto_item *item = NULL;
3646
0
    proto_item *itemadd = NULL;
3647
0
    proto_tree *file_tree = NULL;
3648
3649
0
    len = tvb_get_uint8(tvb, offset);
3650
0
    proto_tree_add_uint(param_tree, hf_s7comm_data_blockcontrol_filename_len, tvb, offset, 1, len);
3651
0
    offset += 1;
3652
0
    item = proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_filename, tvb, offset, len, ENC_ASCII);
3653
    /* The filename when uploading from PLC has a well known structure, which can be further dissected.
3654
     * An upload from a NC is a simple filename string with no deeper structure.
3655
     * Check for PLC filename, by checking some fixed fields.
3656
     */
3657
0
    is_plcfilename = false;
3658
0
    if (len == 9) {
3659
0
        blocktype = tvb_get_ntohs(tvb, offset + 1);
3660
0
        if ((tvb_get_uint8(tvb, offset) == '_') && (blocktype >= S7COMM_BLOCKTYPE_OB) && (blocktype <= S7COMM_BLOCKTYPE_SFB)) {
3661
0
            int32_t num = 1;
3662
0
            bool num_valid;
3663
0
            is_plcfilename = true;
3664
0
            file_tree = proto_item_add_subtree(item, ett_s7comm_plcfilename);
3665
0
            itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_file_ident, tvb, offset, 1, ENC_ASCII);
3666
0
            proto_item_append_text(itemadd, " (%s)", val_to_str(pinfo->pool, tvb_get_uint8(tvb, offset), blocktype_attribute1_names, "Unknown identifier: %c"));
3667
0
            offset += 1;
3668
0
            itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_block_type, tvb, offset, 2, ENC_ASCII);
3669
0
            proto_item_append_text(itemadd, " (%s)", val_to_str(pinfo->pool, blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3670
0
            offset += 2;
3671
0
            proto_tree_add_item_ret_string(file_tree, hf_s7comm_data_blockcontrol_block_num, tvb, offset, 5, ENC_ASCII|ENC_NA, pinfo->pool, &str);
3672
0
            offset += 5;
3673
0
            num_valid = ws_strtoi32((const char*)str, NULL, &num);
3674
0
            proto_item_append_text(file_tree, " [%s",
3675
0
                val_to_str(pinfo->pool, blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3676
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> Block:[%s",
3677
0
                val_to_str(pinfo->pool, blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3678
0
            if (num_valid) {
3679
0
                proto_item_append_text(file_tree, "%d]", num);
3680
0
                col_append_fstr(pinfo->cinfo, COL_INFO, "%d]", num);
3681
0
            } else {
3682
0
                expert_add_info(pinfo, file_tree, &ei_s7comm_data_blockcontrol_block_num_invalid);
3683
0
                proto_item_append_text(file_tree, "NaN]");
3684
0
                col_append_str(pinfo->cinfo, COL_INFO, "NaN]");
3685
0
            }
3686
0
            itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_dest_filesys, tvb, offset, 1, ENC_ASCII);
3687
0
            proto_item_append_text(itemadd, " (%s)", val_to_str_const(tvb_get_uint8(tvb, offset), blocktype_attribute2_names, "Unknown filesys"));
3688
0
            offset += 1;
3689
0
        }
3690
0
    }
3691
0
    if (is_plcfilename == false) {
3692
0
        str = tvb_get_string_enc(pinfo->pool, tvb, offset, len, ENC_ASCII);
3693
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " File:[%s]", str);
3694
0
        offset += len;
3695
0
    }
3696
0
    return offset;
3697
0
}
3698
3699
/*******************************************************************************************************
3700
 *
3701
 * PDU Type: Request or Response -> Function 0x1d, 0x1e, 0x1f (block control functions) for upload
3702
 *
3703
 *******************************************************************************************************/
3704
static uint32_t
3705
s7comm_decode_plc_controls_updownload(tvbuff_t *tvb,
3706
                                      packet_info *pinfo,
3707
                                      proto_tree *tree,
3708
                                      proto_tree *param_tree,
3709
                                      uint16_t plength,
3710
                                      uint16_t dlength,
3711
                                      uint32_t offset,
3712
                                      uint8_t rosctr)
3713
4
{
3714
4
    uint8_t len;
3715
4
    uint8_t function;
3716
4
    uint8_t status;
3717
4
    uint32_t errorcode;
3718
4
    const char *errorcode_text;
3719
4
    proto_item *item = NULL;
3720
4
    proto_tree *data_tree = NULL;
3721
3722
4
    function = tvb_get_uint8(tvb, offset);
3723
4
    offset += 1;
3724
4
    status = S7COMM_FUNC_INVALID;
3725
4
    errorcode = 0;
3726
3727
4
    switch (function) {
3728
        /*---------------------------------------------------------------------*/
3729
0
        case S7COMM_FUNCREQUESTDOWNLOAD:
3730
0
            if (rosctr == S7COMM_ROSCTR_JOB) {
3731
0
                proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3732
0
                    ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3733
0
                offset += 1;
3734
0
                proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
3735
0
                offset += 2;
3736
                /* on upload this is the upload-id, here it is anything else (or not used ) */
3737
0
                proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 4, ENC_NA);
3738
0
                offset += 4;
3739
0
                offset = s7comm_decode_plc_controls_filename(tvb, pinfo, param_tree, offset);
3740
0
                if (plength > 18) {
3741
0
                    len = tvb_get_uint8(tvb, offset);
3742
0
                    proto_tree_add_uint(param_tree, hf_s7comm_data_blockcontrol_part2_len, tvb, offset, 1, len);
3743
0
                    offset += 1;
3744
                    /* first byte unknown '1' */
3745
0
                    proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_part2_unknown, tvb, offset, 1, ENC_ASCII);
3746
0
                    offset += 1;
3747
0
                    proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_loadmem_len, tvb, offset, 6, ENC_ASCII);
3748
0
                    offset += 6;
3749
0
                    proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_mc7code_len, tvb, offset, 6, ENC_ASCII);
3750
0
                    offset += 6;
3751
0
                }
3752
0
            } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
3753
0
                if (plength >= 2) {
3754
0
                    proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3755
0
                        ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3756
0
                    offset += 1;
3757
0
                }
3758
0
            }
3759
0
            break;
3760
        /*---------------------------------------------------------------------*/
3761
0
        case S7COMM_FUNCSTARTUPLOAD:
3762
0
            proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3763
0
                ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3764
0
            offset += 1;
3765
0
            proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
3766
0
            offset += 2;
3767
0
            proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_uploadid, tvb, offset, 4, ENC_BIG_ENDIAN);
3768
0
            offset += 4;
3769
0
            if (rosctr == S7COMM_ROSCTR_JOB) {
3770
0
                offset = s7comm_decode_plc_controls_filename(tvb, pinfo, param_tree, offset);
3771
0
            } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
3772
0
                if (plength > 8) {
3773
                    /* If uploading from a PLC, the response has a string with the length
3774
                     * of the complete module in bytes, which maybe transferred/split into many PDUs.
3775
                     * On a NC file upload, there are no such fields.
3776
                     */
3777
0
                    len = tvb_get_uint8(tvb, offset);
3778
0
                    proto_tree_add_uint(param_tree, hf_s7comm_data_blockcontrol_upl_lenstring_len, tvb, offset, 1, len);
3779
0
                    offset += 1;
3780
0
                    proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_upl_lenstring, tvb, offset, len, ENC_ASCII);
3781
0
                    offset += len;
3782
0
                }
3783
0
            }
3784
0
            break;
3785
        /*---------------------------------------------------------------------*/
3786
0
        case S7COMM_FUNCUPLOAD:
3787
1
        case S7COMM_FUNCDOWNLOADBLOCK:
3788
1
            if (rosctr == S7COMM_ROSCTR_JOB) {
3789
0
                proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3790
0
                    ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3791
0
                offset += 1;
3792
0
                proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
3793
0
                offset += 2;
3794
0
                if (function == S7COMM_FUNCUPLOAD) {
3795
0
                    proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_uploadid, tvb, offset, 4, ENC_BIG_ENDIAN);
3796
0
                    offset += 4;
3797
0
                } else {
3798
0
                    proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 4, ENC_NA);
3799
0
                    offset += 4;
3800
0
                    offset = s7comm_decode_plc_controls_filename(tvb, pinfo, param_tree, offset);
3801
0
                }
3802
1
            } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
3803
1
                if (plength >= 2) {
3804
1
                    status = tvb_get_uint8(tvb, offset);
3805
1
                    proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3806
1
                        ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3807
1
                    offset += 1;
3808
1
                }
3809
1
                if (dlength > 0) {
3810
1
                    item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
3811
1
                    data_tree = proto_item_add_subtree(item, ett_s7comm_data);
3812
1
                    proto_tree_add_item(data_tree, hf_s7comm_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
3813
1
                    offset += 2;
3814
1
                    proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
3815
1
                    offset += 2;
3816
1
                    proto_tree_add_item(data_tree, hf_s7comm_readresponse_data, tvb, offset, dlength - 4, ENC_NA);
3817
3818
                    /* try heuristic response data dissector*/
3819
1
                    s7comm_try_block_data_heuristic(tvb, pinfo, tree, offset, function, status);
3820
3821
1
                    offset += dlength - 4;
3822
1
                }
3823
1
            }
3824
1
            break;
3825
        /*---------------------------------------------------------------------*/
3826
3
        case S7COMM_FUNCENDUPLOAD:
3827
3
        case S7COMM_FUNCDOWNLOADENDED:
3828
3
            if (rosctr == S7COMM_ROSCTR_JOB) {
3829
3
                proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3830
3
                    ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3831
3
                offset += 1;
3832
3
                item = proto_tree_add_item_ret_uint(param_tree, hf_s7comm_data_blockcontrol_errorcode, tvb, offset, 2, ENC_BIG_ENDIAN, &errorcode);
3833
                /* here it uses the same errorcode from parameter part */
3834
3
                if ((errorcode_text = try_val_to_str_ext(errorcode, &param_errcode_names_ext))) {
3835
0
                    proto_item_append_text(item, " (%s)", errorcode_text);
3836
0
                }
3837
3
                offset += 2;
3838
3
                if (function == S7COMM_FUNCENDUPLOAD) {
3839
3
                    proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_uploadid, tvb, offset, 4, ENC_BIG_ENDIAN);
3840
3
                    offset += 4;
3841
3
                } else {
3842
0
                    proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 4, ENC_NA);
3843
0
                    offset += 4;
3844
0
                    offset = s7comm_decode_plc_controls_filename(tvb, pinfo, param_tree, offset);
3845
0
                }
3846
3
            } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
3847
0
                if (plength >= 2) {
3848
0
                    proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3849
0
                        ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3850
0
                    offset += 1;
3851
0
                }
3852
0
            }
3853
3
            break;
3854
4
    }
3855
    /* if an error occurred show in info column */
3856
3
    if (errorcode > 0) {
3857
3
        col_append_fstr(pinfo->cinfo, COL_INFO, " -> Errorcode:[0x%04x]", errorcode);
3858
3
    }
3859
3
    return offset;
3860
4
}
3861
3862
/*******************************************************************************************************
3863
 *
3864
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Block status (0x13 or 0x01)
3865
 *
3866
 *******************************************************************************************************/
3867
static uint32_t
3868
s7comm_decode_ud_tis_blockstat(tvbuff_t *tvb,
3869
                               proto_tree *td_tree,
3870
                               uint16_t td_size,
3871
                               uint8_t type,
3872
                               uint8_t subfunc,
3873
                               uint32_t offset)
3874
56
{
3875
56
    proto_item *item = NULL;
3876
56
    proto_tree *item_tree = NULL;
3877
56
    uint16_t line_nr;
3878
56
    uint16_t line_cnt;
3879
56
    uint16_t item_size = 4;
3880
56
    uint8_t registerflags;
3881
56
    char str_flags[80];
3882
3883
56
    if (type == S7COMM_UD_TYPE_REQ) {
3884
53
        if (subfunc == S7COMM_UD_SUBF_TIS_BLOCKSTAT2) {
3885
23
            proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_flagsunknown, tvb, offset, 1, ENC_BIG_ENDIAN);
3886
23
            offset += 1;
3887
23
            line_cnt = tvb_get_uint8(tvb, offset);
3888
23
            proto_tree_add_uint(td_tree, hf_s7comm_tis_blockstat_number_of_lines, tvb, offset, 1, line_cnt);
3889
23
            offset += 1;
3890
23
            proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
3891
23
            offset += 1;
3892
30
        } else {
3893
30
            proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
3894
30
            offset += 1;
3895
30
            line_cnt = (td_size - 2) / 2;
3896
30
        }
3897
53
        proto_tree_add_bitmask(td_tree, tvb, offset, hf_s7comm_diagdata_registerflag,
3898
53
            ett_s7comm_diagdata_registerflag, s7comm_diagdata_registerflag_fields, ENC_BIG_ENDIAN);
3899
53
        offset += 1;
3900
3901
53
        if (subfunc == S7COMM_UD_SUBF_TIS_BLOCKSTAT2) {
3902
23
            item_size = 4;
3903
30
        } else {
3904
30
            item_size = 2;
3905
30
        }
3906
3.19k
        for (line_nr = 0; line_nr < line_cnt; line_nr++) {
3907
3.13k
            item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, item_size, ENC_NA);
3908
3.13k
            item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
3909
3.13k
            if (subfunc == S7COMM_UD_SUBF_TIS_BLOCKSTAT2) {
3910
272
                proto_tree_add_item(item_tree, hf_s7comm_tis_blockstat_line_address, tvb, offset, 2, ENC_BIG_ENDIAN);
3911
272
                offset += 2;
3912
272
            }
3913
3.13k
            proto_tree_add_item(item_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
3914
3.13k
            offset += 1;
3915
3.13k
            registerflags = tvb_get_uint8(tvb, offset);
3916
3.13k
            make_registerflag_string(str_flags, registerflags, sizeof(str_flags));
3917
3.13k
            proto_item_append_text(item, " [%d]: (%s)", line_nr+1, str_flags);
3918
3.13k
            proto_tree_add_bitmask(item_tree, tvb, offset, hf_s7comm_diagdata_registerflag,
3919
3.13k
                ett_s7comm_diagdata_registerflag, s7comm_diagdata_registerflag_fields, ENC_BIG_ENDIAN);
3920
3.13k
            offset += 1;
3921
3.13k
        }
3922
53
    } else if (type == S7COMM_UD_TYPE_IND) {
3923
        /* The response data can only be dissected when the requested registers for each line
3924
         * from the job setup is known. As the STW is only 16 Bits and all other registers 32 Bits,
3925
         * this has no fixed structure.
3926
         * The only thing that can be shown is the start address. Next the requested registers,
3927
         * the start address of next line with the requested registers and so on.
3928
         */
3929
3
        proto_tree_add_item(td_tree, hf_s7comm_diagdata_req_startaddr_awl, tvb, offset, 2, ENC_BIG_ENDIAN);
3930
3
        offset += 2;
3931
3
        proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_data, tvb, offset, td_size - 2, ENC_NA);
3932
3
        offset += (td_size - 2);
3933
3
    } else {
3934
        /* TODO: Show unknown data as raw bytes */
3935
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, td_size, ENC_NA);
3936
0
        offset += td_size;
3937
0
    }
3938
56
    return offset;
3939
56
}
3940
3941
/*******************************************************************************************************
3942
 *
3943
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Item address
3944
 *
3945
 *******************************************************************************************************/
3946
static uint32_t
3947
s7comm_decode_ud_tis_item_address(tvbuff_t *tvb,
3948
                                  uint32_t offset,
3949
                                  proto_tree *sub_tree,
3950
                                  uint16_t item_no,
3951
                                  char *add_text)
3952
4.77k
{
3953
4.77k
    uint32_t bytepos = 0;
3954
4.77k
    uint16_t len = 0;
3955
4.77k
    uint16_t bitpos = 0;
3956
4.77k
    uint16_t db = 0;
3957
4.77k
    uint8_t area = 0;
3958
4.77k
    proto_item *item = NULL;
3959
3960
    /* Insert a new tree with 6 bytes for every item */
3961
4.77k
    item = proto_tree_add_item(sub_tree, hf_s7comm_param_item, tvb, offset, 6, ENC_NA);
3962
3963
4.77k
    sub_tree = proto_item_add_subtree(item, ett_s7comm_param_item);
3964
3965
4.77k
    proto_item_append_text(item, " [%d]%s:", item_no + 1, add_text);
3966
3967
    /* Area, 1 byte */
3968
4.77k
    proto_tree_add_item_ret_uint8(sub_tree, hf_s7comm_varstat_req_memory_area, tvb, offset, 1, ENC_BIG_ENDIAN, &area);
3969
4.77k
    offset += 1;
3970
3971
    /* Length (repetition factor), 1 byte. If area is a bit address, then this is the bit number.
3972
     * The area is a bit address when the low nibble is zero.
3973
     */
3974
4.77k
    if (area & 0x0f) {
3975
3.45k
        len = tvb_get_uint8(tvb, offset);
3976
3.45k
        proto_tree_add_uint(sub_tree, hf_s7comm_varstat_req_repetition_factor, tvb, offset, 1, len);
3977
3.45k
        offset += 1;
3978
3.45k
    } else {
3979
1.31k
        bitpos = tvb_get_uint8(tvb, offset);
3980
1.31k
        proto_tree_add_uint(sub_tree, hf_s7comm_varstat_req_bitpos, tvb, offset, 1, bitpos);
3981
1.31k
        offset += 1;
3982
1.31k
    }
3983
3984
    /* DB number, 2 bytes */
3985
4.77k
    db = tvb_get_ntohs(tvb, offset);
3986
4.77k
    proto_tree_add_uint(sub_tree, hf_s7comm_varstat_req_db_number, tvb, offset, 2, db);
3987
4.77k
    offset += 2;
3988
3989
    /* byte offset, 2 bytes */
3990
4.77k
    bytepos = tvb_get_ntohs(tvb, offset);
3991
4.77k
    proto_tree_add_uint(sub_tree, hf_s7comm_varstat_req_startaddress, tvb, offset, 2, bytepos);
3992
4.77k
    offset += 2;
3993
3994
    /* build a full address to show item data directly beside the item */
3995
4.77k
    switch (area) {
3996
889
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MX:
3997
889
            proto_item_append_text(sub_tree, " (M%d.%d)", bytepos, bitpos);
3998
889
            break;
3999
139
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MB:
4000
139
            proto_item_append_text(sub_tree, " (M%d.0 BYTE %d)", bytepos, len);
4001
139
            break;
4002
121
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MW:
4003
121
            proto_item_append_text(sub_tree, " (M%d.0 WORD %d)", bytepos, len);
4004
121
            break;
4005
116
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_MD:
4006
116
            proto_item_append_text(sub_tree, " (M%d.0 DWORD %d)", bytepos, len);
4007
116
            break;
4008
36
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EX:
4009
36
            proto_item_append_text(sub_tree, " (I%d.%d)", bytepos, bitpos);
4010
36
            break;
4011
15
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EB:
4012
15
            proto_item_append_text(sub_tree, " (I%d.0 BYTE %d)", bytepos, len);
4013
15
            break;
4014
139
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_EW:
4015
139
            proto_item_append_text(sub_tree, " (I%d.0 WORD %d)", bytepos, len);
4016
139
            break;
4017
21
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_ED:
4018
21
            proto_item_append_text(sub_tree, " (I%d.0 DWORD %d)", bytepos, len);
4019
21
            break;
4020
49
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AX:
4021
49
            proto_item_append_text(sub_tree, " (Q%d.%d)", bytepos, bitpos);
4022
49
            break;
4023
38
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AB:
4024
38
            proto_item_append_text(sub_tree, " (Q%d.0 BYTE %d)", bytepos, len);
4025
38
            break;
4026
4
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AW:
4027
4
            proto_item_append_text(sub_tree, " (Q%d.0 WORD %d)", bytepos, len);
4028
4
            break;
4029
43
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_AD:
4030
43
            proto_item_append_text(sub_tree, " (Q%d.0 DWORD %d)", bytepos, len);
4031
43
            break;
4032
103
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PEB:
4033
103
            proto_item_append_text(sub_tree, " (PI%d.0 BYTE %d)", bytepos, len);
4034
103
            break;
4035
104
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PEW:
4036
104
            proto_item_append_text(sub_tree, " (PI%d.0 WORD %d)", bytepos, len);
4037
104
            break;
4038
106
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_PED:
4039
106
            proto_item_append_text(sub_tree, " (PI%d.0 DWORD %d)", bytepos, len);
4040
106
            break;
4041
55
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBX:
4042
55
            proto_item_append_text(sub_tree, " (DB%d.DBX%d.%d)", db, bytepos, bitpos);
4043
55
            break;
4044
19
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBB:
4045
19
            proto_item_append_text(sub_tree, " (DB%d.DBX%d.0 BYTE %d)", db, bytepos, len);
4046
19
            break;
4047
57
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBW:
4048
57
            proto_item_append_text(sub_tree, " (DB%d.DBX%d.0 WORD %d)", db, bytepos, len);
4049
57
            break;
4050
11
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_DBD:
4051
11
            proto_item_append_text(sub_tree, " (DB%d.DBX%d.0 DWORD %d)", db, bytepos, len);
4052
11
            break;
4053
63
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_T:
4054
            /* it's possible to read multiple timers */
4055
63
            if (len >1)
4056
59
                proto_item_append_text(sub_tree, " (T %d..%d)", bytepos, bytepos + len - 1);
4057
4
            else
4058
4
                proto_item_append_text(sub_tree, " (T %d)", bytepos);
4059
63
            break;
4060
37
        case S7COMM_UD_SUBF_TIS_VARSTAT_AREA_C:
4061
            /* it's possible to read multiple counters */
4062
37
            if (len >1)
4063
34
                proto_item_append_text(sub_tree, " (C %d..%d)", bytepos, bytepos + len - 1);
4064
3
            else
4065
3
                proto_item_append_text(sub_tree, " (C %d)", bytepos);
4066
37
            break;
4067
4.77k
    }
4068
4.68k
    return offset;
4069
4.77k
}
4070
4071
/*******************************************************************************************************
4072
 *
4073
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Item value
4074
 *
4075
 *******************************************************************************************************/
4076
static uint32_t
4077
s7comm_decode_ud_tis_item_value(tvbuff_t *tvb, packet_info* pinfo,
4078
                                uint32_t offset,
4079
                                proto_tree *sub_tree,
4080
                                uint16_t item_no,
4081
                                char *add_text)
4082
373
{
4083
373
    uint16_t len = 0, len2 = 0;
4084
373
    uint8_t ret_val = 0;
4085
373
    uint8_t tsize = 0;
4086
373
    uint8_t head_len = 4;
4087
4088
373
    proto_item *item = NULL;
4089
4090
373
    ret_val = tvb_get_uint8(tvb, offset);
4091
373
    if (ret_val == S7COMM_ITEM_RETVAL_RESERVED ||
4092
236
        ret_val == S7COMM_ITEM_RETVAL_DATA_OK ||
4093
225
        ret_val == S7COMM_ITEM_RETVAL_DATA_ERR
4094
373
        ) {
4095
148
        tsize = tvb_get_uint8(tvb, offset + 1);
4096
148
        len = tvb_get_ntohs(tvb, offset + 2);
4097
4098
148
        if (tsize == S7COMM_DATA_TRANSPORT_SIZE_BBYTE || tsize == S7COMM_DATA_TRANSPORT_SIZE_BINT) {
4099
5
            len /= 8;
4100
5
        }
4101
        /* the PLC places extra bytes at the end if length is not a multiple of 2 */
4102
148
        if (len % 2) {
4103
25
            len2 = len + 1;
4104
123
        } else {
4105
123
            len2 = len;
4106
123
        }
4107
148
    }
4108
    /* Insert a new tree for every item */
4109
373
    item = proto_tree_add_item(sub_tree, hf_s7comm_data_item, tvb, offset, len + head_len, ENC_NA);
4110
373
    sub_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4111
4112
373
    proto_item_append_text(item, " [%d]%s: (%s)", item_no + 1, add_text, val_to_str(pinfo->pool, ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
4113
4114
373
    proto_tree_add_uint(sub_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
4115
373
    proto_tree_add_uint(sub_tree, hf_s7comm_data_transport_size, tvb, offset + 1, 1, tsize);
4116
373
    proto_tree_add_uint(sub_tree, hf_s7comm_data_length, tvb, offset + 2, 2, len);
4117
4118
373
    offset += head_len;
4119
373
    if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK || ret_val == S7COMM_ITEM_RETVAL_RESERVED) {
4120
143
        proto_tree_add_item(sub_tree, hf_s7comm_readresponse_data, tvb, offset, len, ENC_NA);
4121
143
        offset += len;
4122
143
        if (len != len2) {
4123
8
            proto_tree_add_item(sub_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
4124
8
            offset += 1;
4125
8
        }
4126
143
    }
4127
373
    return offset;
4128
373
}
4129
4130
/*******************************************************************************************************
4131
 *
4132
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Force (0x09)
4133
 *
4134
 *******************************************************************************************************/
4135
static uint32_t
4136
s7comm_decode_ud_tis_force(tvbuff_t *tvb, packet_info* pinfo,
4137
                           proto_tree *td_tree,
4138
                           uint8_t type,
4139
                           uint32_t offset)
4140
97
{
4141
97
    uint16_t item_count;
4142
97
    uint16_t i;
4143
97
    uint8_t ret_val = 0;
4144
97
    proto_item *item = NULL;
4145
97
    proto_tree *item_tree = NULL;
4146
4147
97
    switch (type) {
4148
91
        case S7COMM_UD_TYPE_REQ:
4149
91
            item_count = tvb_get_ntohs(tvb, offset);
4150
91
            proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4151
91
            offset += 2;
4152
3.48k
            for (i = 0; i < item_count; i++) {
4153
3.39k
                offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to force");
4154
3.39k
            }
4155
221
            for (i = 0; i < item_count; i++) {
4156
130
                offset = s7comm_decode_ud_tis_item_value(tvb, pinfo, offset, td_tree, i, " Value to force");
4157
130
            }
4158
91
            break;
4159
2
        case S7COMM_UD_TYPE_IND:
4160
2
            item_count = tvb_get_ntohs(tvb, offset);
4161
2
            proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4162
2
            offset += 2;
4163
33
            for (i = 0; i < item_count; i++) {
4164
31
                item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
4165
31
                item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4166
31
                ret_val = tvb_get_uint8(tvb, offset);
4167
31
                proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
4168
31
                proto_item_append_text(item, " [%d]: (%s)", i + 1, val_to_str(pinfo->pool, ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
4169
31
                offset += 1;
4170
31
            }
4171
2
            if (item_count % 2) {
4172
0
                proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
4173
0
                offset += 1;
4174
0
            }
4175
2
            break;
4176
97
    }
4177
12
    return offset;
4178
97
}
4179
4180
/*******************************************************************************************************
4181
 *
4182
 * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
4183
 *           Dissects the parameter part
4184
 *
4185
 *******************************************************************************************************/
4186
static uint32_t
4187
s7comm_decode_ud_tis_param(tvbuff_t *tvb,
4188
                           proto_tree *tree,
4189
                           uint8_t type,
4190
                           uint16_t tp_size,
4191
                           uint32_t offset)
4192
304
{
4193
304
    uint32_t start_offset;
4194
304
    uint32_t callenv_setup = 0;
4195
304
    proto_item *item = NULL;
4196
304
    proto_tree *tp_tree = NULL;
4197
4198
304
    start_offset = offset;
4199
304
    if (tp_size > 0) {
4200
211
        item = proto_tree_add_item(tree, hf_s7comm_tis_parameter, tvb, offset, tp_size, ENC_NA);
4201
211
        tp_tree = proto_item_add_subtree(item, ett_s7comm_prog_parameter);
4202
211
        if (type == S7COMM_UD_TYPE_REQ) {
4203
189
            if (tp_size >= 4) {
4204
158
                proto_tree_add_item(tp_tree, hf_s7comm_tis_param1, tvb, offset, 2, ENC_BIG_ENDIAN);
4205
158
                offset += 2;
4206
158
                proto_tree_add_item(tp_tree, hf_s7comm_tis_param2, tvb, offset, 2, ENC_BIG_ENDIAN);
4207
158
                offset += 2;
4208
158
            }
4209
189
            if (tp_size >= 20) {
4210
117
                proto_tree_add_item(tp_tree, hf_s7comm_tis_param3, tvb, offset, 2, ENC_BIG_ENDIAN);
4211
117
                offset += 2;
4212
117
                proto_tree_add_item(tp_tree, hf_s7comm_tis_answersize, tvb, offset, 2, ENC_BIG_ENDIAN);
4213
117
                offset += 2;
4214
117
                proto_tree_add_item(tp_tree, hf_s7comm_tis_param5, tvb, offset, 2, ENC_BIG_ENDIAN);
4215
117
                offset += 2;
4216
117
                proto_tree_add_item(tp_tree, hf_s7comm_tis_param6, tvb, offset, 2, ENC_BIG_ENDIAN);
4217
117
                offset += 2;
4218
117
                proto_tree_add_item(tp_tree, hf_s7comm_tis_param7, tvb, offset, 2, ENC_BIG_ENDIAN);
4219
117
                offset += 2;
4220
117
                proto_tree_add_item(tp_tree, hf_s7comm_tis_param8, tvb, offset, 2, ENC_BIG_ENDIAN);
4221
117
                offset += 2;
4222
117
                proto_tree_add_item(tp_tree, hf_s7comm_tis_param9, tvb, offset, 2, ENC_BIG_ENDIAN);
4223
117
                offset += 2;
4224
117
                proto_tree_add_item(tp_tree, hf_s7comm_tis_trgevent, tvb, offset, 2, ENC_BIG_ENDIAN);
4225
117
                offset += 2;
4226
117
            }
4227
189
            if (tp_size >= 26) {
4228
114
                proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_block_type, tvb, offset, 2, ENC_BIG_ENDIAN);
4229
114
                offset += 2;
4230
114
                proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_block_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4231
114
                offset += 2;
4232
114
                proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_startaddr_awl, tvb, offset, 2, ENC_BIG_ENDIAN);
4233
114
                offset += 2;
4234
114
            }
4235
189
            if (tp_size >= 28) {
4236
114
                proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_saz, tvb, offset, 2, ENC_BIG_ENDIAN);
4237
114
                offset += 2;
4238
114
            }
4239
189
            if (tp_size >= 36) {
4240
100
                proto_tree_add_item_ret_uint(tp_tree, hf_s7comm_tis_p_callenv, tvb, offset, 2, ENC_BIG_ENDIAN, &callenv_setup);
4241
100
                offset += 2;
4242
100
                proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond, tvb, offset, 2, ENC_BIG_ENDIAN);
4243
100
                offset += 2;
4244
100
                if (callenv_setup == 2) {
4245
1
                    proto_tree_add_item(tp_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4246
1
                    offset += 2;
4247
1
                    proto_tree_add_item(tp_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4248
99
                } else {
4249
99
                    proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
4250
99
                    offset += 2;
4251
99
                    proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
4252
99
                    offset += 2;
4253
99
                    if (tp_size >= 38) {
4254
93
                        proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_address, tvb, offset, 2, ENC_BIG_ENDIAN);
4255
93
                    }
4256
99
                }
4257
100
            }
4258
189
        } else {
4259
22
            proto_tree_add_item(tp_tree, hf_s7comm_tis_res_param1, tvb, offset, 2, ENC_BIG_ENDIAN);
4260
22
            offset += 2;
4261
22
            proto_tree_add_item(tp_tree, hf_s7comm_tis_res_param2, tvb, offset, 2, ENC_BIG_ENDIAN);
4262
22
        }
4263
211
    }
4264
    /* May be we don't know all values when here, so set offset to the given length */
4265
304
    return start_offset + tp_size;
4266
304
}
4267
4268
/*******************************************************************************************************
4269
 *
4270
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Disable job (0x0d), Enable job (0x0e),
4271
 *                                                                   Delete job (0x0f), Read job list (0x10),
4272
 *                                                                   Read job (0x11)
4273
 *
4274
 *******************************************************************************************************/
4275
static uint32_t
4276
// NOLINTNEXTLINE(misc-no-recursion)
4277
s7comm_decode_ud_tis_jobs(tvbuff_t *tvb, packet_info* pinfo,
4278
                          proto_tree *td_tree,
4279
                          uint16_t td_size,
4280
                          uint8_t type,
4281
                          uint8_t subfunc,
4282
                          uint32_t offset)
4283
26
{
4284
26
    uint16_t i;
4285
26
    proto_item *item = NULL;
4286
26
    proto_tree *item_tree = NULL;
4287
26
    uint16_t job_tp_size;
4288
26
    uint16_t job_td_size;
4289
26
    proto_tree *job_td_tree = NULL;
4290
26
    uint8_t job_subfunc;
4291
4292
26
    if (type == S7COMM_UD_TYPE_REQ) {
4293
26
        switch (subfunc) {
4294
0
            case S7COMM_UD_SUBF_TIS_DELETEJOB:
4295
0
                proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4296
0
                offset += 2;
4297
                /* fallthrough */
4298
0
            case S7COMM_UD_SUBF_TIS_ENABLEJOB:
4299
1
            case S7COMM_UD_SUBF_TIS_DISABLEJOB:
4300
13
            case S7COMM_UD_SUBF_TIS_READJOB:
4301
13
                proto_tree_add_item(td_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
4302
13
                offset += 1;
4303
13
                proto_tree_add_item(td_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
4304
13
                offset += 1;
4305
13
                break;
4306
0
            case S7COMM_UD_SUBF_TIS_READJOBLIST:
4307
                /* 4 bytes, possible as filter? */
4308
0
                proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4309
0
                offset += 2;
4310
0
                proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4311
0
                offset += 2;
4312
0
                break;
4313
13
            case S7COMM_UD_SUBF_TIS_REPLACEJOB:
4314
13
                proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4315
13
                offset += 2;
4316
                /* The job which has to be replaced */
4317
13
                job_subfunc = tvb_get_uint8(tvb, offset);
4318
13
                proto_tree_add_item(td_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
4319
13
                offset += 1;
4320
13
                proto_tree_add_item(td_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
4321
13
                offset += 1;
4322
13
                job_tp_size = tvb_get_ntohs(tvb, offset);
4323
13
                proto_tree_add_item(td_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
4324
13
                offset += 2;
4325
13
                job_td_size = tvb_get_ntohs(tvb, offset);
4326
13
                proto_tree_add_item(td_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
4327
13
                offset += 2;
4328
                /* New job parameter tree */
4329
13
                if (job_tp_size > 0) {
4330
12
                    offset = s7comm_decode_ud_tis_param(tvb, td_tree, S7COMM_UD_TYPE_REQ, job_tp_size, offset);
4331
12
                }
4332
                /* New job data tree */
4333
13
                if (job_td_size > 0) {
4334
                    // We recurse here, but we'll run out of packet before we run out of stack.
4335
8
                    offset = s7comm_decode_ud_tis_data(tvb, pinfo, td_tree, S7COMM_UD_TYPE_REQ, job_subfunc, job_td_size, offset);
4336
8
                }
4337
13
                break;
4338
26
        }
4339
26
    } else {
4340
0
        switch (subfunc) {
4341
0
            case S7COMM_UD_SUBF_TIS_READJOBLIST:
4342
                /* 4 bytes each job:
4343
                 * - 2 bytes job id
4344
                 * - 2 bytes status: 1=active, 0=idle/pending?
4345
                 */
4346
0
                for (i = 0; i < td_size / 4; i++) {
4347
0
                    item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 4, ENC_NA);
4348
0
                    item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4349
0
                    proto_item_append_text(item, " [%d] Job", i + 1);
4350
4351
0
                    proto_tree_add_item(item_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
4352
0
                    offset += 1;
4353
0
                    proto_tree_add_item(item_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
4354
0
                    offset += 1;
4355
0
                    proto_tree_add_item(item_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4356
0
                    offset += 2;
4357
0
                }
4358
0
                break;
4359
0
            case S7COMM_UD_SUBF_TIS_READJOB:
4360
                /* This includes the same data as in the job request. With the disadvantage that is does
4361
                 * not contain information of the function, so the data can't be further dissected.
4362
                 * We need to know the function from the request.
4363
                 */
4364
0
                job_tp_size = tvb_get_ntohs(tvb, offset);
4365
0
                proto_tree_add_item(td_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
4366
0
                offset += 2;
4367
0
                job_td_size = tvb_get_ntohs(tvb, offset);
4368
0
                proto_tree_add_item(td_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
4369
0
                offset += 2;
4370
                /* Job parameter tree */
4371
0
                if (job_tp_size > 0) {
4372
0
                    offset = s7comm_decode_ud_tis_param(tvb, td_tree, S7COMM_UD_TYPE_REQ, job_tp_size, offset);
4373
0
                }
4374
                /* Job data tree */
4375
0
                if (job_td_size > 0) {
4376
0
                    item = proto_tree_add_item(td_tree, hf_s7comm_tis_data, tvb, offset, job_td_size, ENC_NA);
4377
0
                    job_td_tree = proto_item_add_subtree(item, ett_s7comm_prog_data);
4378
0
                    proto_tree_add_item(job_td_tree, hf_s7comm_tis_job_reserved, tvb, offset, job_td_size, ENC_NA);
4379
0
                    offset += job_td_size;
4380
0
                }
4381
0
                break;
4382
0
        }
4383
0
    }
4384
18
    return offset;
4385
26
}
4386
4387
/*******************************************************************************************************
4388
 *
4389
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Variable status (0x03)
4390
 *
4391
 *******************************************************************************************************/
4392
static uint32_t
4393
s7comm_decode_ud_tis_varstat(tvbuff_t *tvb, packet_info* pinfo,
4394
                             proto_tree *td_tree,
4395
                             uint8_t type,
4396
                             uint32_t offset)
4397
40
{
4398
40
    uint16_t item_count;
4399
40
    uint16_t i;
4400
4401
40
    switch (type) {
4402
14
        case S7COMM_UD_TYPE_REQ:
4403
14
            item_count = tvb_get_ntohs(tvb, offset);
4404
14
            proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4405
14
            offset += 2;
4406
629
            for (i = 0; i < item_count; i++) {
4407
615
                offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to read");
4408
615
            }
4409
14
            break;
4410
26
        case S7COMM_UD_TYPE_IND:
4411
26
            item_count = tvb_get_ntohs(tvb, offset);
4412
26
            proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4413
26
            offset += 2;
4414
262
            for (i = 0; i < item_count; i++) {
4415
236
                offset = s7comm_decode_ud_tis_item_value(tvb, pinfo, offset, td_tree, i, " Read data");
4416
236
            }
4417
26
            break;
4418
40
    }
4419
5
    return offset;
4420
40
}
4421
4422
/*******************************************************************************************************
4423
 *
4424
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Modify variable (0x08)
4425
 *
4426
 *******************************************************************************************************/
4427
static uint32_t
4428
s7comm_decode_ud_tis_modvar(tvbuff_t *tvb, packet_info* pinfo,
4429
                            proto_tree *td_tree,
4430
                            uint8_t type,
4431
                            uint32_t offset)
4432
18
{
4433
18
    uint16_t item_count;
4434
18
    uint16_t i;
4435
18
    uint8_t ret_val = 0;
4436
18
    proto_item *item = NULL;
4437
18
    proto_tree *item_tree = NULL;
4438
4439
18
    switch (type) {
4440
18
        case S7COMM_UD_TYPE_REQ:
4441
18
            item_count = tvb_get_ntohs(tvb, offset);
4442
18
            proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4443
18
            offset += 2;
4444
786
            for (i = 0; i < item_count; i++) {
4445
768
                offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to write");
4446
768
            }
4447
25
            for (i = 0; i < item_count; i++) {
4448
7
                offset = s7comm_decode_ud_tis_item_value(tvb, pinfo, offset, td_tree, i, " Data to write");
4449
7
            }
4450
18
            break;
4451
0
        case S7COMM_UD_TYPE_IND:
4452
0
            item_count = tvb_get_ntohs(tvb, offset);
4453
0
            proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4454
0
            offset += 2;
4455
0
            for (i = 0; i < item_count; i++) {
4456
0
                item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
4457
0
                item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4458
0
                ret_val = tvb_get_uint8(tvb, offset);
4459
0
                proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
4460
0
                proto_item_append_text(item, " [%d]: (%s)", i + 1, val_to_str(pinfo->pool, ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
4461
0
                offset += 1;
4462
0
            }
4463
0
            if (item_count % 2) {
4464
0
                proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
4465
0
                offset += 1;
4466
0
            }
4467
0
            break;
4468
18
    }
4469
2
    return offset;
4470
18
}
4471
4472
/*******************************************************************************************************
4473
 *
4474
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output ISTACK (0x03)
4475
 *
4476
 *******************************************************************************************************/
4477
static uint32_t
4478
s7comm_decode_ud_tis_istack(tvbuff_t *tvb,
4479
                            proto_tree *td_tree,
4480
                            uint8_t type,
4481
                            uint32_t offset)
4482
2
{
4483
2
    uint8_t ob_number = 0;
4484
2
    switch (type) {
4485
0
        case S7COMM_UD_TYPE_REQ:
4486
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4487
0
            offset += 2;
4488
0
            break;
4489
0
        case S7COMM_UD_TYPE_RES:
4490
2
        case S7COMM_UD_TYPE_IND:
4491
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_continued_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
4492
2
            offset += 2;
4493
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_continued_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
4494
2
            offset += 2;
4495
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_continued_address, tvb, offset, 2, ENC_BIG_ENDIAN);
4496
2
            offset += 2;
4497
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4498
2
            offset += 1;
4499
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4500
2
            offset += 1;
4501
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4502
2
            offset += 2;
4503
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4504
2
            offset += 2;
4505
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 4, ENC_NA);
4506
2
            offset += 4;
4507
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu1, tvb, offset, 4, ENC_BIG_ENDIAN);
4508
2
            offset += 4;
4509
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu2, tvb, offset, 4, ENC_BIG_ENDIAN);
4510
2
            offset += 4;
4511
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu3, tvb, offset, 4, ENC_BIG_ENDIAN);
4512
2
            offset += 4;
4513
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu4, tvb, offset, 4, ENC_BIG_ENDIAN);
4514
2
            offset += 4;
4515
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar1, tvb, offset, 4, ENC_BIG_ENDIAN);
4516
2
            offset += 4;
4517
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar2, tvb, offset, 4, ENC_BIG_ENDIAN);
4518
2
            offset += 4;
4519
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4520
2
            offset += 2;
4521
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_stw, tvb, offset, 2, ENC_BIG_ENDIAN);
4522
2
            offset += 2;
4523
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
4524
2
            offset += 2;
4525
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
4526
2
            offset += 2;
4527
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
4528
2
            offset += 2;
4529
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4530
2
            offset += 2;
4531
2
            proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 4, ENC_NA);
4532
2
            offset += 4;
4533
            /* read the OB number first */
4534
2
            ob_number = tvb_get_uint8(tvb, offset + 3);
4535
2
            switch (ob_number) {
4536
0
                case 1:     /* Cyclic execution */
4537
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4538
0
                    offset += 1;
4539
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_scan_1, tvb, offset, 1, ENC_NA);
4540
0
                    offset += 1;
4541
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4542
0
                    offset += 1;
4543
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4544
0
                    offset += 1;
4545
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4546
0
                    offset += 1;
4547
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4548
0
                    offset += 1;
4549
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_prev_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
4550
0
                    offset += 2;
4551
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_min_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
4552
0
                    offset += 2;
4553
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_max_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
4554
0
                    offset += 2;
4555
0
                    break;
4556
0
                case 10:    /* Time of day interrupt 0..7 */
4557
0
                case 11:
4558
0
                case 12:
4559
0
                case 13:
4560
1
                case 14:
4561
1
                case 15:
4562
1
                case 16:
4563
1
                case 17:
4564
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4565
1
                    offset += 1;
4566
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4567
1
                    offset += 1;
4568
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4569
1
                    offset += 1;
4570
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4571
1
                    offset += 1;
4572
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4573
1
                    offset += 1;
4574
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4575
1
                    offset += 1;
4576
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_period_exe, tvb, offset, 2, ENC_BIG_ENDIAN);
4577
1
                    offset += 2;
4578
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4579
1
                    offset += 2;
4580
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4, tvb, offset, 2, ENC_BIG_ENDIAN);
4581
1
                    offset += 2;
4582
1
                    break;
4583
0
                case 20:    /* Time delay interrupt 0..3 */
4584
0
                case 21:
4585
0
                case 22:
4586
0
                case 23:
4587
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4588
0
                    offset += 1;
4589
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4590
0
                    offset += 1;
4591
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4592
0
                    offset += 1;
4593
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_scan_1, tvb, offset, 1, ENC_NA);
4594
0
                    offset += 1;
4595
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4596
0
                    offset += 1;
4597
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4598
0
                    offset += 1;
4599
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4600
0
                    offset += 1;
4601
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_sign, tvb, offset, 2, ENC_BIG_ENDIAN);
4602
0
                    offset += 2;
4603
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_dtime, tvb, offset, 4, ENC_BIG_ENDIAN);
4604
0
                    offset += 4;
4605
0
                    break;
4606
0
                case 30:    /* Cyclic interrupt 0..8 */
4607
0
                case 31:
4608
1
                case 32:
4609
1
                case 33:
4610
1
                case 34:
4611
1
                case 35:
4612
1
                case 36:
4613
1
                case 37:
4614
1
                case 38:
4615
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4616
1
                    offset += 1;
4617
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4618
1
                    offset += 1;
4619
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4620
1
                    offset += 1;
4621
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4622
1
                    offset += 1;
4623
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4624
1
                    offset += 1;
4625
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4626
1
                    offset += 1;
4627
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_phase_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
4628
1
                    offset += 2;
4629
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4630
1
                    offset += 2;
4631
1
                    proto_tree_add_item(td_tree, hf_s7comm_ob_exec_freq, tvb, offset, 2, ENC_BIG_ENDIAN);
4632
1
                    offset += 2;
4633
1
                    break;
4634
0
                case 40:    /* Hardware interrupt 0..8 */
4635
0
                case 41:
4636
0
                case 42:
4637
0
                case 43:
4638
0
                case 44:
4639
0
                case 45:
4640
0
                case 46:
4641
0
                case 47:
4642
0
                case 48:
4643
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4644
0
                    offset += 1;
4645
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4646
0
                    offset += 1;
4647
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4648
0
                    offset += 1;
4649
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4650
0
                    offset += 1;
4651
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4652
0
                    offset += 1;
4653
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
4654
0
                    offset += 1;
4655
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4656
0
                    offset += 2;
4657
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_point_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
4658
0
                    offset += 4;
4659
0
                    break;
4660
0
                case 55:    /* DP Statusalarm */
4661
0
                case 56:    /* DP Updatealarm */
4662
0
                case 57:    /* DP Specific alarm */
4663
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4664
0
                    offset += 1;
4665
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4666
0
                    offset += 1;
4667
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4668
0
                    offset += 1;
4669
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4670
0
                    offset += 1;
4671
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4672
0
                    offset += 1;
4673
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
4674
0
                    offset += 1;
4675
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4676
0
                    offset += 2;
4677
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_inf_len, tvb, offset, 1, ENC_NA);
4678
0
                    offset += 1;
4679
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_type, tvb, offset, 1, ENC_NA);
4680
0
                    offset += 1;
4681
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_slot, tvb, offset, 1, ENC_NA);
4682
0
                    offset += 1;
4683
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_spec, tvb, offset, 1, ENC_NA);
4684
0
                    offset += 1;
4685
0
                    break;
4686
0
                case 80:    /* Cycle time fault */
4687
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4688
0
                    offset += 1;
4689
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4690
0
                    offset += 1;
4691
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4692
0
                    offset += 1;
4693
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4694
0
                    offset += 1;
4695
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4696
0
                    offset += 1;
4697
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4698
0
                    offset += 1;
4699
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_error_info, tvb, offset, 2, ENC_BIG_ENDIAN);
4700
0
                    offset += 2;
4701
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_class, tvb, offset, 1, ENC_NA);
4702
0
                    offset += 1;
4703
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_num, tvb, offset, 1, ENC_NA);
4704
0
                    offset += 1;
4705
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_priority, tvb, offset, 1, ENC_NA);
4706
0
                    offset += 1;
4707
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_num, tvb, offset, 1, ENC_NA);
4708
0
                    offset += 1;
4709
0
                    break;
4710
0
                case 81:    /* Power supply fault */
4711
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4712
0
                    offset += 1;
4713
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4714
0
                    offset += 1;
4715
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4716
0
                    offset += 1;
4717
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4718
0
                    offset += 1;
4719
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4720
0
                    offset += 1;
4721
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4722
0
                    offset += 1;
4723
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_rack_cpu, tvb, offset, 2, ENC_BIG_ENDIAN);
4724
0
                    offset += 2;
4725
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4726
0
                    offset += 2;
4727
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4, tvb, offset, 2, ENC_BIG_ENDIAN);
4728
0
                    offset += 2;
4729
0
                    break;
4730
0
                case 82:    /* I/O Point fault 1 */
4731
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4732
0
                    offset += 1;
4733
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4734
0
                    offset += 1;
4735
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4736
0
                    offset += 1;
4737
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4738
0
                    offset += 1;
4739
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4740
0
                    offset += 1;
4741
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
4742
0
                    offset += 1;
4743
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4744
0
                    offset += 2;
4745
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
4746
0
                    offset += 1;
4747
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_type_b, tvb, offset, 1, ENC_NA);
4748
0
                    offset += 1;
4749
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
4750
0
                    offset += 1;
4751
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
4752
0
                    offset += 1;
4753
0
                    break;
4754
0
                case 83:    /* I/O Point fault 2 */
4755
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4756
0
                    offset += 1;
4757
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4758
0
                    offset += 1;
4759
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4760
0
                    offset += 1;
4761
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4762
0
                    offset += 1;
4763
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4764
0
                    offset += 1;
4765
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
4766
0
                    offset += 1;
4767
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4768
0
                    offset += 2;
4769
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_rack_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4770
0
                    offset += 2;
4771
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_type_w, tvb, offset, 2, ENC_BIG_ENDIAN);
4772
0
                    offset += 2;
4773
0
                    break;
4774
0
                case 84:    /* CPU fault */
4775
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4776
0
                    offset += 1;
4777
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4778
0
                    offset += 1;
4779
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4780
0
                    offset += 1;
4781
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4782
0
                    offset += 1;
4783
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4784
0
                    offset += 1;
4785
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4786
0
                    offset += 1;
4787
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4788
0
                    offset += 2;
4789
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4_dw, tvb, offset, 4, ENC_BIG_ENDIAN);
4790
0
                    offset += 4;
4791
0
                    break;
4792
0
                case 85:    /* OB not loaded fault */
4793
0
                case 87:    /* Communication Fault */
4794
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4795
0
                    offset += 1;
4796
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4797
0
                    offset += 1;
4798
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4799
0
                    offset += 1;
4800
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4801
0
                    offset += 1;
4802
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4803
0
                    offset += 1;
4804
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4805
0
                    offset += 1;
4806
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4807
0
                    offset += 2;
4808
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_class, tvb, offset, 1, ENC_NA);
4809
0
                    offset += 1;
4810
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_num, tvb, offset, 1, ENC_NA);
4811
0
                    offset += 1;
4812
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_priority, tvb, offset, 1, ENC_NA);
4813
0
                    offset += 1;
4814
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_num, tvb, offset, 1, ENC_NA);
4815
0
                    offset += 1;
4816
0
                    break;
4817
0
                case 86:    /* Loss of rack fault */
4818
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4819
0
                    offset += 1;
4820
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4821
0
                    offset += 1;
4822
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4823
0
                    offset += 1;
4824
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4825
0
                    offset += 1;
4826
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4827
0
                    offset += 1;
4828
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4829
0
                    offset += 1;
4830
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4831
0
                    offset += 2;
4832
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_racks_flt, tvb, offset, 4, ENC_BIG_ENDIAN);
4833
0
                    offset += 4;
4834
0
                    break;
4835
0
                case 90:    /* Background cycle */
4836
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4837
0
                    offset += 1;
4838
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4839
0
                    offset += 1;
4840
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4841
0
                    offset += 1;
4842
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4843
0
                    offset += 1;
4844
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4845
0
                    offset += 1;
4846
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4847
0
                    offset += 1;
4848
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4849
0
                    offset += 2;
4850
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4_dw, tvb, offset, 4, ENC_BIG_ENDIAN);
4851
0
                    offset += 4;
4852
0
                    break;
4853
0
                case 100:    /* Complete restart */
4854
0
                case 101:    /* Restart */
4855
0
                case 102:    /* Cold restart */
4856
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4857
0
                    offset += 1;
4858
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_strtup, tvb, offset, 1, ENC_NA);
4859
0
                    offset += 1;
4860
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4861
0
                    offset += 1;
4862
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4863
0
                    offset += 1;
4864
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4865
0
                    offset += 1;
4866
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4867
0
                    offset += 1;
4868
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_stop, tvb, offset, 2, ENC_BIG_ENDIAN);
4869
0
                    offset += 2;
4870
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_strt_info, tvb, offset, 4, ENC_BIG_ENDIAN);
4871
0
                    offset += 4;
4872
0
                    break;
4873
0
                case 121:    /* Programming Error */
4874
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4875
0
                    offset += 1;
4876
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_sw_flt, tvb, offset, 1, ENC_NA);
4877
0
                    offset += 1;
4878
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4879
0
                    offset += 1;
4880
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4881
0
                    offset += 1;
4882
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_blk_type, tvb, offset, 1, ENC_NA);
4883
0
                    offset += 1;
4884
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4885
0
                    offset += 1;
4886
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_reg, tvb, offset, 2, ENC_BIG_ENDIAN);
4887
0
                    offset += 2;
4888
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_blk_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4889
0
                    offset += 2;
4890
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_prg_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4891
0
                    offset += 2;
4892
0
                    break;
4893
0
                case 122:    /* Module Access Error */
4894
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4895
0
                    offset += 1;
4896
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_sw_flt, tvb, offset, 1, ENC_NA);
4897
0
                    offset += 1;
4898
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4899
0
                    offset += 1;
4900
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4901
0
                    offset += 1;
4902
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_blk_type, tvb, offset, 1, ENC_NA);
4903
0
                    offset += 1;
4904
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mem_area, tvb, offset, 1, ENC_NA);
4905
0
                    offset += 1;
4906
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_mem_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4907
0
                    offset += 2;
4908
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_flt_blk_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4909
0
                    offset += 2;
4910
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_prg_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4911
0
                    offset += 2;
4912
0
                    break;
4913
0
                default:
4914
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4915
0
                    offset += 1;
4916
0
                    proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 1, ENC_NA);
4917
0
                    offset += 1;
4918
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4919
0
                    offset += 1;
4920
0
                    proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4921
0
                    offset += 1;
4922
0
                    proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4923
0
                    offset += 2;
4924
0
                    proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4925
0
                    offset += 2;
4926
0
                    proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4927
0
                    offset += 2;
4928
0
                    proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4929
0
                    offset += 2;
4930
0
                    break;
4931
2
            }
4932
0
            offset = s7comm_add_timestamp_to_tree(tvb, td_tree, offset, false, false);
4933
2
    }
4934
0
    return offset;
4935
2
}
4936
4937
/*******************************************************************************************************
4938
 *
4939
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output BSTACK (0x04)
4940
 *
4941
 *******************************************************************************************************/
4942
static uint32_t
4943
s7comm_decode_ud_tis_bstack(tvbuff_t *tvb, packet_info* pinfo,
4944
                            proto_tree *td_tree,
4945
                            uint16_t td_size,
4946
                            uint8_t type,
4947
                            uint32_t offset)
4948
9
{
4949
9
    uint16_t i;
4950
9
    uint16_t blocktype;
4951
9
    uint16_t blocknumber;
4952
9
    proto_item *item = NULL;
4953
9
    proto_tree *item_tree = NULL;
4954
9
    int rem;
4955
9
    uint32_t replen;
4956
4957
    /* Possible firmware bug in IM151-8 CPU, where also the date size information
4958
     * in the header is 4 bytes too short.
4959
     */
4960
9
    replen = tvb_reported_length_remaining(tvb, offset);
4961
9
    if (replen < td_size) {
4962
        /* TODO: Show this mismatch? We fix the length here. */
4963
9
        td_size = replen;
4964
9
    }
4965
9
    switch (type) {
4966
0
        case S7COMM_UD_TYPE_REQ:
4967
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 2, ENC_NA);
4968
0
            offset += 2;
4969
0
            break;
4970
0
        case S7COMM_UD_TYPE_RES:
4971
9
        case S7COMM_UD_TYPE_IND:
4972
9
            rem = td_size;
4973
9
            i = 1;
4974
142
            while (rem > 16) {
4975
133
                item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 16, ENC_NA);
4976
133
                item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4977
133
                proto_tree_add_item_ret_uint16(item_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN, &blocktype);
4978
133
                offset += 2;
4979
133
                proto_tree_add_item_ret_uint16(item_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN, &blocknumber);
4980
133
                offset += 2;
4981
133
                proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
4982
133
                offset += 2;
4983
133
                proto_tree_add_item(item_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4984
133
                offset += 1;
4985
133
                proto_tree_add_item(item_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4986
133
                offset += 1;
4987
133
                proto_tree_add_item(item_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4988
133
                offset += 2;
4989
133
                proto_tree_add_item(item_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4990
133
                offset += 2;
4991
133
                proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 4, ENC_NA);
4992
133
                offset += 4;
4993
133
                proto_item_append_text(item, " [%d] BSTACK entry for: %s %d", i++,
4994
133
                    val_to_str(pinfo->pool, blocktype, subblktype_names, "Unknown Subblk type: 0x%02x"), blocknumber);
4995
133
                rem -= 16;
4996
133
                if (blocktype == S7COMM_SUBBLKTYPE_OB) {
4997
0
                    proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
4998
0
                    offset += 1;
4999
0
                    proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 1, ENC_NA);
5000
0
                    offset += 1;
5001
0
                    proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 2, ENC_NA);
5002
0
                    offset += 2;
5003
0
                    rem -= 4;
5004
0
                    if (rem >= 8) {
5005
0
                        offset = s7comm_add_timestamp_to_tree(tvb, item_tree, offset, false, false);
5006
0
                        rem -= 8;
5007
0
                    } else {
5008
0
                        proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, rem, ENC_NA);
5009
0
                        offset += rem;
5010
0
                        break;
5011
0
                    }
5012
0
                }
5013
133
            }
5014
9
    }
5015
9
    return offset;
5016
9
}
5017
5018
/*******************************************************************************************************
5019
 *
5020
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output LSTACK (0x05)
5021
 *
5022
 *******************************************************************************************************/
5023
static uint32_t
5024
s7comm_decode_ud_tis_lstack(tvbuff_t *tvb,
5025
                            proto_tree *td_tree,
5026
                            uint8_t type,
5027
                            uint32_t offset)
5028
0
{
5029
0
    uint16_t len;
5030
5031
0
    if (type == S7COMM_UD_TYPE_REQ) {
5032
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
5033
0
        offset += 1;
5034
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_bstack_nest_depth, tvb, offset, 1, ENC_NA);
5035
0
        offset += 1;
5036
0
    } else {
5037
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
5038
0
        offset += 2;
5039
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
5040
0
        offset += 2;
5041
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
5042
0
        offset += 2;
5043
0
        len = tvb_get_ntohs(tvb, offset);
5044
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_size, tvb, offset, 2, ENC_BIG_ENDIAN);
5045
0
        offset += 2;
5046
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_data, tvb, offset, len, ENC_NA);
5047
0
        offset += len;
5048
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
5049
0
        offset += 1;
5050
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_reserved, tvb, offset, 1, ENC_NA);
5051
0
        offset += 1;
5052
0
        proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_reserved, tvb, offset, 2, ENC_NA);
5053
0
        offset += 2;
5054
0
        offset = s7comm_add_timestamp_to_tree(tvb, td_tree, offset, false, false);
5055
0
    }
5056
0
    return offset;
5057
0
}
5058
/*******************************************************************************************************
5059
 *
5060
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Exit Hold (0x0b)
5061
 *
5062
 *******************************************************************************************************/
5063
static uint32_t
5064
s7comm_decode_ud_tis_exithold(tvbuff_t *tvb,
5065
                              proto_tree *td_tree,
5066
                              uint8_t type,
5067
                              uint32_t offset)
5068
9
{
5069
    /* Only request with data payload was seen */
5070
9
    switch (type) {
5071
9
        case S7COMM_UD_TYPE_REQ:
5072
9
            proto_tree_add_item(td_tree, hf_s7comm_tis_exithold_until, tvb, offset, 1, ENC_NA);
5073
9
            offset += 1;
5074
9
            proto_tree_add_item(td_tree, hf_s7comm_tis_exithold_res1, tvb, offset, 1, ENC_NA);
5075
9
            offset += 1;
5076
9
            break;
5077
9
    }
5078
9
    return offset;
5079
9
}
5080
5081
/*******************************************************************************************************
5082
 *
5083
 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Breakpoint (0x0a)
5084
 *
5085
 *******************************************************************************************************/
5086
static uint32_t
5087
s7comm_decode_ud_tis_breakpoint(tvbuff_t *tvb,
5088
                                proto_tree *td_tree,
5089
                                uint8_t type,
5090
                                uint32_t offset)
5091
0
{
5092
0
    switch (type) {
5093
0
        case S7COMM_UD_TYPE_REQ:
5094
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_reserved, tvb, offset, 2, ENC_NA);
5095
0
            offset += 2;
5096
0
            break;
5097
0
        case S7COMM_UD_TYPE_RES:
5098
0
        case S7COMM_UD_TYPE_IND:
5099
            /* Info: Both blocknumbers and addresses are the same on online-blockview inside a block.
5100
             * On return out of a block, the first address contains the current breakpoint, the second
5101
             * address the address from where it was returned (previous block).
5102
             */
5103
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
5104
0
            offset += 2;
5105
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
5106
0
            offset += 2;
5107
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
5108
0
            offset += 2;
5109
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
5110
0
            offset += 2;
5111
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
5112
0
            offset += 2;
5113
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_address, tvb, offset, 2, ENC_BIG_ENDIAN);
5114
0
            offset += 2;
5115
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_reserved, tvb, offset, 2, ENC_NA);
5116
0
            offset += 2;
5117
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_stw, tvb, offset, 2, ENC_BIG_ENDIAN);
5118
0
            offset += 2;
5119
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu1, tvb, offset, 4, ENC_BIG_ENDIAN);
5120
0
            offset += 4;
5121
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu2, tvb, offset, 4, ENC_BIG_ENDIAN);
5122
0
            offset += 4;
5123
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar1, tvb, offset, 4, ENC_BIG_ENDIAN);
5124
0
            offset += 4;
5125
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar2, tvb, offset, 4, ENC_BIG_ENDIAN);
5126
0
            offset += 4;
5127
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5128
0
            offset += 1;
5129
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5130
0
            offset += 1;
5131
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
5132
0
            offset += 2;
5133
0
            proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
5134
0
            offset += 2;
5135
0
    }
5136
0
    return offset;
5137
0
}
5138
5139
/*******************************************************************************************************
5140
 *
5141
 * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
5142
 *           Dissects the data part
5143
 *
5144
 *******************************************************************************************************/
5145
static uint32_t
5146
// NOLINTNEXTLINE(misc-no-recursion)
5147
s7comm_decode_ud_tis_data(tvbuff_t *tvb, packet_info* pinfo,
5148
                          proto_tree *tree,
5149
                          uint8_t type,
5150
                          uint8_t subfunc,
5151
                          uint16_t td_size,
5152
                          uint32_t offset)
5153
293
{
5154
293
    proto_item *item = NULL;
5155
293
    proto_tree *td_tree = NULL;
5156
5157
293
    if (td_size > 0) {
5158
271
        item = proto_tree_add_item(tree, hf_s7comm_tis_data, tvb, offset, td_size, ENC_NA);
5159
271
        td_tree = proto_item_add_subtree(item, ett_s7comm_prog_data);
5160
271
        switch (subfunc) {
5161
2
            case S7COMM_UD_SUBF_TIS_OUTISTACK:
5162
2
                offset = s7comm_decode_ud_tis_istack(tvb, td_tree, type, offset);
5163
2
                break;
5164
9
            case S7COMM_UD_SUBF_TIS_OUTBSTACK:
5165
9
                offset = s7comm_decode_ud_tis_bstack(tvb, pinfo, td_tree, td_size, type, offset);
5166
9
                break;
5167
0
            case S7COMM_UD_SUBF_TIS_OUTLSTACK:
5168
0
                offset = s7comm_decode_ud_tis_lstack(tvb, td_tree, type, offset);
5169
0
                break;
5170
0
            case S7COMM_UD_SUBF_TIS_BREAKPOINT:
5171
0
                offset = s7comm_decode_ud_tis_breakpoint(tvb, td_tree, type, offset);
5172
0
                break;
5173
9
            case S7COMM_UD_SUBF_TIS_EXITHOLD:
5174
9
                offset = s7comm_decode_ud_tis_exithold(tvb, td_tree, type, offset);
5175
9
                break;
5176
33
            case S7COMM_UD_SUBF_TIS_BLOCKSTAT:
5177
56
            case S7COMM_UD_SUBF_TIS_BLOCKSTAT2:
5178
56
                offset = s7comm_decode_ud_tis_blockstat(tvb, td_tree, td_size, type, subfunc, offset);
5179
56
                break;
5180
40
            case S7COMM_UD_SUBF_TIS_VARSTAT:
5181
40
                offset = s7comm_decode_ud_tis_varstat(tvb, pinfo, td_tree, type, offset);
5182
40
                break;
5183
1
            case S7COMM_UD_SUBF_TIS_DISABLEJOB:
5184
1
            case S7COMM_UD_SUBF_TIS_ENABLEJOB:
5185
1
            case S7COMM_UD_SUBF_TIS_DELETEJOB:
5186
1
            case S7COMM_UD_SUBF_TIS_READJOBLIST:
5187
13
            case S7COMM_UD_SUBF_TIS_READJOB:
5188
26
            case S7COMM_UD_SUBF_TIS_REPLACEJOB:
5189
                // We recurse here, but we'll run out of packet before we run out of stack.
5190
26
                offset = s7comm_decode_ud_tis_jobs(tvb, pinfo, td_tree, td_size, type, subfunc, offset);
5191
26
                break;
5192
18
            case S7COMM_UD_SUBF_TIS_MODVAR:
5193
18
                offset = s7comm_decode_ud_tis_modvar(tvb, pinfo, td_tree, type, offset);
5194
18
                break;
5195
97
            case S7COMM_UD_SUBF_TIS_FORCE:
5196
97
                offset = s7comm_decode_ud_tis_force(tvb, pinfo, td_tree, type, offset);
5197
97
                break;
5198
3
            default:
5199
3
                proto_tree_add_item(td_tree, hf_s7comm_varstat_unknown, tvb, offset, td_size, ENC_NA);
5200
3
                offset += td_size;
5201
3
                break;
5202
271
        }
5203
271
    }
5204
88
    return offset;
5205
293
}
5206
5207
/*******************************************************************************************************
5208
 *
5209
 * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
5210
 *
5211
 *******************************************************************************************************/
5212
static uint32_t
5213
s7comm_decode_ud_tis_subfunc(tvbuff_t *tvb, packet_info* pinfo,
5214
                             proto_tree *data_tree,
5215
                             uint8_t type,
5216
                             uint8_t subfunc,
5217
                             uint32_t offset)
5218
293
{
5219
293
    uint16_t tp_size = 0;
5220
293
    uint16_t td_size = 0;
5221
5222
293
    tp_size = tvb_get_ntohs(tvb, offset);
5223
293
    proto_tree_add_item(data_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
5224
293
    offset += 2;
5225
293
    td_size = tvb_get_ntohs(tvb, offset);
5226
293
    proto_tree_add_item(data_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
5227
293
    offset += 2;
5228
    /* Parameter tree */
5229
293
    offset = s7comm_decode_ud_tis_param(tvb, data_tree, type, tp_size, offset);
5230
    /* Data tree */
5231
293
    offset = s7comm_decode_ud_tis_data(tvb, pinfo, data_tree, type, subfunc, td_size, offset);
5232
293
    return offset;
5233
293
}
5234
5235
/*******************************************************************************************************
5236
 *
5237
 * PDU Type: User Data -> Function group 5 -> Security functions?
5238
 *
5239
 *******************************************************************************************************/
5240
static uint32_t
5241
s7comm_decode_ud_security_subfunc(tvbuff_t *tvb,
5242
                                  proto_tree *data_tree,
5243
                                  uint32_t dlength,
5244
                                  uint32_t offset)
5245
4
{
5246
    /* Display dataset as raw bytes. Maybe this part can be extended with further knowledge. */
5247
4
    proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
5248
4
    offset += dlength;
5249
5250
4
    return offset;
5251
4
}
5252
5253
/*******************************************************************************************************
5254
 *
5255
 * PDU Type: User Data -> Function group 6 -> PBC, Programmable Block Functions (e.g. BSEND/BRECV), before reassembly
5256
 *
5257
 *******************************************************************************************************/
5258
static uint32_t
5259
s7comm_decode_ud_pbc_bsend_pre_reass(tvbuff_t *tvb,
5260
                                     packet_info *pinfo,
5261
                                     proto_tree *data_tree,
5262
                                     uint8_t type,
5263
                                     uint16_t *dlength,
5264
                                     uint32_t *r_id,              /* R_ID of the PBC communication */
5265
                                     uint32_t offset)
5266
44
{
5267
44
    if ((type == S7COMM_UD_TYPE_REQ || type == S7COMM_UD_TYPE_RES) && (*dlength >= 8)) {
5268
8
        proto_tree_add_item(data_tree, hf_s7comm_item_varspec, tvb, offset, 1, ENC_BIG_ENDIAN);
5269
8
        offset += 1;
5270
8
        proto_tree_add_item(data_tree, hf_s7comm_item_varspec_length, tvb, offset, 1, ENC_BIG_ENDIAN);
5271
8
        offset += 1;
5272
8
        proto_tree_add_item(data_tree, hf_s7comm_item_syntax_id, tvb, offset, 1, ENC_BIG_ENDIAN);
5273
8
        offset += 1;
5274
        /* 0x00 when passive partners is sending, 0xcc when active partner is sending? */
5275
8
        proto_tree_add_item(data_tree, hf_s7comm_pbc_unknown, tvb, offset, 1, ENC_BIG_ENDIAN);
5276
8
        offset += 1;
5277
8
        proto_tree_add_item(data_tree, hf_s7comm_pbc_bsend_r_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5278
8
        *r_id = tvb_get_ntohl(tvb, offset);
5279
8
        col_append_fstr(pinfo->cinfo, COL_INFO, " R_ID=0x%X", *r_id);
5280
8
        offset += 4;
5281
8
        *dlength -= 8;
5282
8
    }
5283
44
    return offset;
5284
44
}
5285
5286
/*******************************************************************************************************
5287
 *
5288
 * PDU Type: User Data -> Function group 6 -> PBC, Programmable Block Functions (e.g. BSEND/BRECV)
5289
 *
5290
 *******************************************************************************************************/
5291
static uint32_t
5292
s7comm_decode_ud_pbc_bsend_subfunc(tvbuff_t *tvb,
5293
                             proto_tree *data_tree,
5294
                             uint32_t dlength,
5295
                             uint32_t offset,
5296
                             packet_info *pinfo,
5297
                             proto_tree *tree)
5298
44
{
5299
44
    proto_tree_add_item(data_tree, hf_s7comm_pbc_bsend_len, tvb, offset, 2, ENC_BIG_ENDIAN);
5300
44
    offset += 2;
5301
44
    proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength - 2, ENC_NA);
5302
5303
    /* dissect data */
5304
44
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
5305
38
        struct tvbuff *next_tvb = tvb_new_subset_remaining(tvb,  offset);
5306
38
        heur_dtbl_entry_t *hdtbl_entry;
5307
38
        if (!dissector_try_heuristic(s7comm_heur_subdissector_list_bsend, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
5308
38
            call_data_dissector(next_tvb, pinfo, data_tree);
5309
38
        }
5310
38
    }
5311
5312
44
    offset += (dlength - 2);
5313
5314
44
    return offset;
5315
44
}
5316
5317
/*******************************************************************************************************
5318
 *
5319
 * PDU Type: User Data -> PBC, Programmable Block Function USEND
5320
 *
5321
 *******************************************************************************************************/
5322
static uint32_t
5323
s7comm_decode_ud_usend(tvbuff_t *tvb,
5324
                       proto_tree *tree,
5325
                       uint32_t dlength,
5326
                       uint32_t offset)
5327
7
{
5328
7
    proto_item *item = NULL;
5329
7
    proto_tree *data_tree = NULL;
5330
7
    proto_tree *item_tree = NULL;
5331
7
    uint8_t tsize;
5332
7
    uint16_t len;
5333
7
    uint16_t len2;
5334
7
    uint8_t ret_val;
5335
7
    uint8_t item_count;
5336
7
    uint8_t i;
5337
5338
7
    item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
5339
7
    data_tree = proto_item_add_subtree(item, ett_s7comm_data);
5340
5341
7
    ret_val = tvb_get_uint8(tvb, offset);
5342
7
    proto_tree_add_uint(data_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
5343
7
    offset += 1;
5344
5345
7
    proto_tree_add_item(data_tree, hf_s7comm_pbc_usend_unknown1, tvb, offset, 1, ENC_BIG_ENDIAN);
5346
7
    offset += 1;
5347
5348
7
    item_count = tvb_get_uint8(tvb, offset + 1); /* max. 4 possible */
5349
7
    proto_tree_add_uint(data_tree, hf_s7comm_param_itemcount, tvb, offset, 2, item_count);
5350
7
    offset += 2;
5351
5352
20
    for (i = 0; i < item_count; i++) {
5353
13
        tsize = tvb_get_uint8(tvb, offset + 1);
5354
13
        len = tvb_get_ntohs(tvb, offset + 2);
5355
        /* calculate length in bytes */
5356
13
        if (tsize == S7COMM_DATA_TRANSPORT_SIZE_BBIT ||
5357
13
            tsize == S7COMM_DATA_TRANSPORT_SIZE_BBYTE ||
5358
13
            tsize == S7COMM_DATA_TRANSPORT_SIZE_BINT
5359
13
            ) {
5360
1
            if (len % 8) {
5361
0
                len /= 8;
5362
0
                len = len + 1;
5363
1
            } else {
5364
1
                len /= 8;
5365
1
            }
5366
1
        }
5367
5368
13
        if ((len % 2) && (i < (item_count-1))) {
5369
6
            len2 = len + 1;
5370
7
        } else {
5371
7
            len2 = len;
5372
7
        }
5373
5374
13
        item = proto_tree_add_item(data_tree, hf_s7comm_data_item, tvb, offset, len + 4, ENC_NA);
5375
13
        item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
5376
13
        proto_item_append_text(item, " [%d]", i+1);
5377
13
        proto_tree_add_item(item_tree, hf_s7comm_pbc_usend_unknown2, tvb, offset, 1, ENC_BIG_ENDIAN);
5378
13
        proto_tree_add_uint(item_tree, hf_s7comm_data_transport_size, tvb, offset + 1, 1, tsize);
5379
13
        proto_tree_add_uint(item_tree, hf_s7comm_data_length, tvb, offset + 2, 2, len);
5380
13
        offset += 4;
5381
5382
13
        proto_tree_add_item(item_tree, hf_s7comm_readresponse_data, tvb, offset, len, ENC_NA);
5383
13
        offset += len;
5384
13
        if (len != len2) {
5385
0
            proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
5386
0
            offset += 1;
5387
0
        }
5388
13
    }
5389
5390
7
    return offset;
5391
7
}
5392
5393
/*******************************************************************************************************
5394
 *
5395
 * PDU Type: User Data -> NC programming functions (file download/upload), before reassembly
5396
 *
5397
 *******************************************************************************************************/
5398
static uint32_t
5399
s7comm_decode_ud_ncprg_pre_reass(tvbuff_t *tvb,
5400
                                 proto_tree *data_tree,
5401
                                 uint8_t type,
5402
                                 uint8_t subfunc,
5403
                                 uint16_t *dlength,
5404
                                 uint32_t offset)
5405
95
{
5406
95
    if ((type == S7COMM_UD_TYPE_RES || type == S7COMM_UD_TYPE_IND) &&
5407
25
        (subfunc == S7COMM_NCPRG_FUNCDOWNLOADBLOCK ||
5408
21
         subfunc == S7COMM_NCPRG_FUNCUPLOAD ||
5409
21
         subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD)) {
5410
18
        proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
5411
18
        offset += 2;
5412
18
        *dlength -= 2;
5413
18
    }
5414
95
    return offset;
5415
95
}
5416
5417
/*******************************************************************************************************
5418
 *
5419
 * PDU Type: User Data -> NC programming functions (file download/upload)
5420
 *
5421
 *******************************************************************************************************/
5422
static uint32_t
5423
s7comm_decode_ud_ncprg_subfunc(tvbuff_t *tvb,
5424
                               packet_info *pinfo,
5425
                               proto_tree *data_tree,
5426
                               uint8_t type,
5427
                               uint8_t subfunc,
5428
                               uint32_t dlength,
5429
                               uint32_t offset)
5430
95
{
5431
95
    const uint8_t *str_filename;
5432
95
    uint32_t string_end_offset;
5433
95
    uint32_t string_len;
5434
95
    uint32_t filelength;
5435
95
    uint32_t start_offset;
5436
5437
95
    if (dlength >= 2) {
5438
95
        if (type == S7COMM_UD_TYPE_REQ && subfunc == S7COMM_NCPRG_FUNCREQUESTDOWNLOAD) {
5439
0
            proto_tree_add_item_ret_string(data_tree, hf_s7comm_data_blockcontrol_filename, tvb, offset, dlength,
5440
0
                                           ENC_ASCII|ENC_NA, pinfo->pool, &str_filename);
5441
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " File:[%s]", str_filename);
5442
0
            offset += dlength;
5443
95
        } else if (type == S7COMM_UD_TYPE_REQ && subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD) {
5444
0
            proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA);
5445
0
            offset += 1;
5446
0
            dlength -= 1;
5447
0
            proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA);
5448
0
            offset += 1;
5449
0
            dlength -= 1;
5450
0
            proto_tree_add_item_ret_string(data_tree, hf_s7comm_data_blockcontrol_filename, tvb, offset, dlength,
5451
0
                                           ENC_ASCII|ENC_NA, pinfo->pool, &str_filename);
5452
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " File:[%s]", str_filename);
5453
0
            offset += dlength;
5454
95
        } else if (type == S7COMM_UD_TYPE_RES && subfunc == S7COMM_NCPRG_FUNCREQUESTDOWNLOAD) {
5455
0
                proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA);
5456
0
                offset += 1;
5457
0
                proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA);
5458
0
                offset += 1;
5459
95
        } else if (type == S7COMM_UD_TYPE_IND && (subfunc == S7COMM_NCPRG_FUNCCONTUPLOAD || subfunc == S7COMM_NCPRG_FUNCCONTDOWNLOAD)) {
5460
0
                proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA);
5461
0
                offset += 1;
5462
0
                proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA);
5463
0
                offset += 1;
5464
95
        } else if ((type == S7COMM_UD_TYPE_RES || type == S7COMM_UD_TYPE_IND) &&
5465
25
                (subfunc == S7COMM_NCPRG_FUNCDOWNLOADBLOCK ||
5466
21
                 subfunc == S7COMM_NCPRG_FUNCUPLOAD ||
5467
21
                 subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD)) {
5468
18
            start_offset = offset;
5469
            /* file length may be contain only spaces when downloading a directory */
5470
18
            proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_filelength, tvb, offset, 8, ENC_ASCII);
5471
18
            offset += 8;
5472
18
            proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_filetime, tvb, offset, 16, ENC_ASCII);
5473
18
            offset += 16;
5474
            /* File path and file data aren't always there */
5475
18
            if (dlength > 24) {
5476
16
                if (subfunc == S7COMM_NCPRG_FUNCDOWNLOADBLOCK || subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD || subfunc == S7COMM_NCPRG_FUNCUPLOAD) {
5477
16
                    if (tvb_find_uint8_length(tvb, offset, dlength-8-16, 0x0a, &string_end_offset)) {
5478
1
                        string_len = string_end_offset - offset + 1;    /* include 0x0a */
5479
1
                        proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_filepath, tvb, offset, string_len, ENC_ASCII);
5480
1
                        offset += string_len;
5481
1
                        filelength = dlength - (offset - start_offset);
5482
1
                        proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_filedata, tvb, offset, filelength, ENC_NA);
5483
1
                        offset += filelength;
5484
1
                    }
5485
16
                }
5486
16
            }
5487
77
        } else {
5488
77
            proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
5489
77
            offset += 2;
5490
77
            dlength -= 2;
5491
77
            if (dlength >= 4) {
5492
24
                proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
5493
24
                offset += dlength;
5494
24
            }
5495
77
        }
5496
95
    }
5497
95
    return offset;
5498
95
}
5499
5500
/*******************************************************************************************************
5501
 *
5502
 * PDU Type: User Data -> Data record routing to Profibus
5503
 *
5504
 *******************************************************************************************************/
5505
static uint32_t
5506
s7comm_decode_ud_drr_subfunc(tvbuff_t *tvb,
5507
                             proto_tree *tree,
5508
                             uint32_t dlength,
5509
                             uint32_t offset)
5510
5
{
5511
    /* As a start add only a data block. At least there are min. 6 bytes of a header.
5512
     * At some point of the data, parts of the Profinet dissector may be reusable,
5513
     * as there's an overlap between the Profibus and Profinet Specification.
5514
     */
5515
5
    if (dlength > 0) {
5516
5
        proto_tree_add_item(tree, hf_s7comm_data_drr_data, tvb, offset, dlength, ENC_NA);
5517
5
        offset += dlength;
5518
5
    }
5519
5520
5
    return offset;
5521
5
}
5522
5523
/*******************************************************************************************************
5524
 *
5525
 * PDU Type: User Data -> Message services -> AR_SEND parameters on initiate/abort
5526
 *
5527
 *******************************************************************************************************/
5528
static uint32_t
5529
s7comm_decode_message_service_ar_send_args(tvbuff_t *tvb,
5530
                                           packet_info *pinfo,
5531
                                           proto_tree *tree,
5532
                                           uint8_t type,
5533
                                           uint32_t offset)
5534
2
{
5535
2
    uint8_t item_count;
5536
2
    uint8_t i;
5537
2
    uint32_t ar_id;
5538
2
    proto_item *item = NULL;
5539
2
    proto_tree *item_tree = NULL;
5540
5541
2
    item_count = tvb_get_uint8(tvb, offset);
5542
2
    proto_tree_add_uint(tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
5543
2
    offset += 1;
5544
5545
8
    for (i = 0; i < item_count; i++) {
5546
6
        if (type == S7COMM_UD_TYPE_REQ) {
5547
6
            item = proto_tree_add_item(tree, hf_s7comm_data_item, tvb, offset, 8, ENC_NA);
5548
6
            item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
5549
6
            proto_tree_add_item(item_tree, hf_s7comm_item_varspec, tvb, offset, 1, ENC_BIG_ENDIAN);
5550
6
            offset += 1;
5551
6
            proto_tree_add_item(item_tree, hf_s7comm_item_varspec_length, tvb, offset, 1, ENC_BIG_ENDIAN);
5552
6
            offset += 1;
5553
6
            proto_tree_add_item(item_tree, hf_s7comm_item_syntax_id, tvb, offset, 1, ENC_BIG_ENDIAN);
5554
6
            offset += 1;
5555
6
            proto_tree_add_item(item_tree, hf_s7comm_pbc_arsend_unknown, tvb, offset, 1, ENC_BIG_ENDIAN);
5556
6
            offset += 1;
5557
6
            proto_tree_add_item_ret_uint(item_tree, hf_s7comm_pbc_arsend_ar_id, tvb, offset, 4, ENC_BIG_ENDIAN, &ar_id);
5558
6
            col_append_fstr(pinfo->cinfo, COL_INFO, "%s0x%X", (i == 0) ? " AR_ID=" : ",", ar_id);
5559
6
            proto_item_append_text(item, " [%d]: AR_ID=0x%X", i+1, ar_id);
5560
6
            offset += 4;
5561
6
        } else if (type == S7COMM_UD_TYPE_RES) {
5562
0
            item = proto_tree_add_item(tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
5563
0
            item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
5564
0
            proto_item_append_text(item, " [%d]", i+1);
5565
            /* Kind of return code. But from what was captured, it doesn't matter if the AR_ID of the request is not available */
5566
0
            proto_tree_add_item(item_tree, hf_s7comm_pbc_arsend_ret, tvb, offset, 1, ENC_BIG_ENDIAN);
5567
0
            offset += 1;
5568
0
        }
5569
6
    }
5570
    /* Fill byte on response if number of items is uneven */
5571
2
    if (type == S7COMM_UD_TYPE_RES && (item_count % 2)) {
5572
0
        proto_tree_add_item(tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
5573
0
        offset += 1;
5574
0
    }
5575
2
    return offset;
5576
2
}
5577
5578
/*******************************************************************************************************
5579
 *
5580
 * PDU Type: User Data -> Message services
5581
 *
5582
 *******************************************************************************************************/
5583
static uint32_t
5584
s7comm_decode_message_service(tvbuff_t *tvb,
5585
                              packet_info *pinfo,
5586
                              proto_tree *data_tree,
5587
                              uint8_t type,
5588
                              uint32_t dlength,
5589
                              uint32_t offset)
5590
39
{
5591
39
    uint8_t events;
5592
39
    uint8_t almtype;
5593
39
    char events_string[42];
5594
5595
39
    switch (type) {
5596
38
        case S7COMM_UD_TYPE_REQ:
5597
38
            events = tvb_get_uint8(tvb, offset);
5598
38
            proto_tree_add_bitmask(data_tree, tvb, offset, hf_s7comm_cpu_msgservice_subscribe_events,
5599
38
                ett_s7comm_cpu_msgservice_subscribe_events, s7comm_cpu_msgservice_subscribe_events_fields, ENC_BIG_ENDIAN);
5600
38
            offset += 1;
5601
38
            proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_req_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
5602
38
            offset += 1;
5603
5604
38
            (void) g_strlcpy(events_string, "", sizeof(events_string));
5605
38
            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 */
5606
38
            if (events & 0x02) (void) g_strlcat(events_string, "SYS,", sizeof(events_string));     /* System diagnostics */
5607
38
            if (events & 0x04) (void) g_strlcat(events_string, "USR,", sizeof(events_string));     /* User-defined diagnostic messages */
5608
38
            if (events & 0x08) (void) g_strlcat(events_string, "-4-,", sizeof(events_string));     /* currently unknown flag */
5609
38
            if (events & 0x10) (void) g_strlcat(events_string, "-5-,", sizeof(events_string));     /* currently unknown flag */
5610
38
            if (events & 0x20) (void) g_strlcat(events_string, "-6-,", sizeof(events_string));     /* currently unknown flag */
5611
38
            if (events & 0x40) (void) g_strlcat(events_string, "-7-,", sizeof(events_string));     /* currently unknown flag */
5612
38
            if (events & 0x80) (void) g_strlcat(events_string, "ALM,", sizeof(events_string));     /* Program block message, type of message in additional field */
5613
38
            if (strlen(events_string) > 2)
5614
26
                events_string[strlen(events_string) - 1 ] = '\0';
5615
38
            col_append_fstr(pinfo->cinfo, COL_INFO, " SubscribedEvents=(%s)", events_string);
5616
5617
38
            proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_username, tvb, offset, 8, ENC_ASCII);
5618
38
            offset += 8;
5619
38
            if ((events & 0x80) && (dlength > 10)) {
5620
13
                proto_tree_add_item_ret_uint8(data_tree, hf_s7comm_cpu_msgservice_almtype, tvb, offset, 1, ENC_BIG_ENDIAN, &almtype);
5621
13
                col_append_fstr(pinfo->cinfo, COL_INFO, " AlmType=%s", val_to_str(pinfo->pool, almtype, cpu_msgservice_almtype_names, "Unknown type: 0x%02x"));
5622
13
                offset += 1;
5623
13
                if (almtype == S7COMM_CPU_MSG_ALMTYPE_AR_SEND_INITIATE || almtype == S7COMM_CPU_MSG_ALMTYPE_AR_SEND_ABORT) {
5624
2
                    offset = s7comm_decode_message_service_ar_send_args(tvb, pinfo, data_tree, type, offset);
5625
11
                } else {
5626
11
                    proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_req_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
5627
11
                    offset += 1;
5628
11
                }
5629
13
            }
5630
38
            break;
5631
1
        case S7COMM_UD_TYPE_RES:
5632
1
            proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_res_result, tvb, offset, 1, ENC_BIG_ENDIAN);
5633
1
            offset += 1;
5634
1
            proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_res_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
5635
1
            offset += 1;
5636
1
            if (dlength > 2) {
5637
1
                proto_tree_add_item_ret_uint8(data_tree, hf_s7comm_cpu_msgservice_almtype, tvb, offset, 1, ENC_BIG_ENDIAN, &almtype);
5638
1
                col_append_fstr(pinfo->cinfo, COL_INFO, " AlmType=%s", val_to_str(pinfo->pool, almtype, cpu_msgservice_almtype_names, "Unknown type: 0x%02x"));
5639
1
                offset += 1;
5640
1
                if (almtype == S7COMM_CPU_MSG_ALMTYPE_AR_SEND_INITIATE || almtype == S7COMM_CPU_MSG_ALMTYPE_AR_SEND_ABORT) {
5641
0
                    offset = s7comm_decode_message_service_ar_send_args(tvb, pinfo, data_tree, type, offset);
5642
1
                } else {
5643
1
                    proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_res_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
5644
1
                    offset += 1;
5645
1
                    proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_res_reserved3, tvb, offset, 1, ENC_BIG_ENDIAN);
5646
1
                    offset += 1;
5647
1
                }
5648
1
            }
5649
1
            break;
5650
39
    }
5651
5652
39
    return offset;
5653
39
}
5654
5655
/*******************************************************************************************************
5656
 *
5657
 *  PDU Type: User Data -> AR_SEND, before reassembly
5658
 *
5659
 *******************************************************************************************************/
5660
static uint32_t
5661
s7comm_decode_ud_cpu_ar_send_pre_reass(tvbuff_t *tvb,
5662
                                       packet_info *pinfo,
5663
                                       proto_tree *data_tree,
5664
                                       uint16_t *dlength,
5665
                                       uint32_t offset)
5666
0
{
5667
0
    uint32_t ar_id;
5668
5669
0
    if (*dlength >= 8) {
5670
0
        proto_tree_add_item(data_tree, hf_s7comm_item_varspec, tvb, offset, 1, ENC_BIG_ENDIAN);
5671
0
        offset += 1;
5672
0
        proto_tree_add_item(data_tree, hf_s7comm_item_varspec_length, tvb, offset, 1, ENC_BIG_ENDIAN);
5673
0
        offset += 1;
5674
0
        proto_tree_add_item(data_tree, hf_s7comm_item_syntax_id, tvb, offset, 1, ENC_BIG_ENDIAN);
5675
0
        offset += 1;
5676
0
        proto_tree_add_item(data_tree, hf_s7comm_pbc_arsend_unknown, tvb, offset, 1, ENC_BIG_ENDIAN);
5677
0
        offset += 1;
5678
0
        proto_tree_add_item_ret_uint(data_tree, hf_s7comm_pbc_arsend_ar_id, tvb, offset, 4, ENC_BIG_ENDIAN, &ar_id);
5679
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " AR_ID=0x%X", ar_id);
5680
0
        offset += 4;
5681
5682
0
        *dlength -= 8;
5683
0
    }
5684
0
    return offset;
5685
0
}
5686
5687
/*******************************************************************************************************
5688
 *
5689
 * PDU Type: User Data -> AR_SEND
5690
 *
5691
 *******************************************************************************************************/
5692
static uint32_t
5693
s7comm_decode_ud_cpu_ar_send(tvbuff_t *tvb,
5694
                             proto_tree *data_tree,
5695
                             uint32_t offset)
5696
0
{
5697
0
    uint32_t len;
5698
5699
    /* Only the first fragment contains the length. As we get the length after reassembly, it's ok. */
5700
0
    proto_tree_add_item_ret_uint(data_tree, hf_s7comm_pbc_arsend_len, tvb, offset, 2, ENC_LITTLE_ENDIAN, &len);
5701
0
    offset += 2;
5702
5703
0
    proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, len, ENC_NA);
5704
0
    offset += len;
5705
5706
0
    return offset;
5707
0
}
5708
/*******************************************************************************************************
5709
 *
5710
 * PDU Type: User Data -> Function group 4 -> alarm, main tree for all except query response
5711
 *
5712
 *******************************************************************************************************/
5713
static uint32_t
5714
s7comm_decode_ud_cpu_alarm_main(tvbuff_t *tvb,
5715
                                packet_info *pinfo,
5716
                                proto_tree *data_tree,
5717
                                uint8_t type,
5718
                                uint8_t subfunc,
5719
                                uint32_t offset)
5720
46
{
5721
46
    uint32_t start_offset;
5722
46
    uint32_t asc_start_offset;
5723
46
    uint32_t msg_obj_start_offset;
5724
46
    uint32_t ev_id;
5725
46
    proto_item *msg_item = NULL;
5726
46
    proto_tree *msg_item_tree = NULL;
5727
46
    proto_item *msg_obj_item = NULL;
5728
46
    proto_tree *msg_obj_item_tree = NULL;
5729
46
    proto_item *msg_work_item = NULL;
5730
46
    proto_tree *msg_work_item_tree = NULL;
5731
46
    uint8_t nr_objects;
5732
46
    uint8_t i;
5733
46
    uint8_t syntax_id;
5734
46
    uint8_t nr_of_additional_values;
5735
46
    uint8_t signalstate;
5736
46
    uint8_t sig_nr;
5737
46
    uint8_t ret_val;
5738
46
    uint8_t querytype;
5739
46
    uint8_t varspec_length;
5740
5741
46
    start_offset = offset;
5742
5743
46
    msg_item = proto_tree_add_item(data_tree, hf_s7comm_cpu_alarm_message_item, tvb, offset, 0, ENC_NA);
5744
46
    msg_item_tree = proto_item_add_subtree(msg_item, ett_s7comm_cpu_alarm_message);
5745
5746
46
    switch (subfunc) {
5747
15
        case S7COMM_UD_SUBF_CPU_SCAN_IND:
5748
15
            proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_scan_unknown1, tvb, offset, 2, ENC_BIG_ENDIAN);
5749
15
            offset += 2;
5750
15
            msg_work_item = proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_timestamp_coming, tvb, offset, 8, ENC_NA);
5751
15
            msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_timestamp);
5752
15
            offset = s7comm_add_timestamp_to_tree(tvb, msg_work_item_tree, offset, true, false);
5753
15
            proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_scan_unknown2, tvb, offset, 2, ENC_BIG_ENDIAN);
5754
15
            offset += 2;
5755
15
            break;
5756
0
        case S7COMM_UD_SUBF_CPU_ALARM8_IND:
5757
0
        case S7COMM_UD_SUBF_CPU_ALARMACK_IND:
5758
0
        case S7COMM_UD_SUBF_CPU_ALARMSQ_IND:
5759
0
        case S7COMM_UD_SUBF_CPU_ALARMS_IND:
5760
28
        case S7COMM_UD_SUBF_CPU_NOTIFY_IND:
5761
28
        case S7COMM_UD_SUBF_CPU_NOTIFY8_IND:
5762
28
            msg_work_item = proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_timestamp_coming, tvb, offset, 8, ENC_NA);
5763
28
            msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_timestamp);
5764
28
            offset = s7comm_add_timestamp_to_tree(tvb, msg_work_item_tree, offset, true, false);
5765
28
            break;
5766
46
    }
5767
46
    proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_function, tvb, offset, 1, ENC_BIG_ENDIAN);
5768
46
    offset += 1;
5769
46
    nr_objects = tvb_get_uint8(tvb, offset);
5770
46
    proto_tree_add_uint(msg_item_tree, hf_s7comm_cpu_alarm_message_nr_objects, tvb, offset, 1, nr_objects);
5771
46
    offset += 1;
5772
465
    for (i = 0; i < nr_objects; i++) {
5773
420
        msg_obj_start_offset = offset;
5774
420
        msg_obj_item = proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_obj_item, tvb, offset, 0, ENC_NA);
5775
420
        msg_obj_item_tree = proto_item_add_subtree(msg_obj_item, ett_s7comm_cpu_alarm_message_object);
5776
420
        proto_item_append_text(msg_obj_item_tree, " [%d]", i+1);
5777
420
        if (type == S7COMM_UD_TYPE_REQ || type == S7COMM_UD_TYPE_IND) {
5778
158
            proto_tree_add_item(msg_obj_item_tree, hf_s7comm_item_varspec, tvb, offset, 1, ENC_BIG_ENDIAN);
5779
158
            offset += 1;
5780
158
            varspec_length = tvb_get_uint8(tvb, offset);
5781
158
            proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_item_varspec_length, tvb, offset, 1, varspec_length);
5782
158
            offset += 1;
5783
158
            syntax_id = tvb_get_uint8(tvb, offset);
5784
158
            proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_item_syntax_id, tvb, offset, 1, syntax_id);
5785
158
            offset += 1;
5786
158
            switch (syntax_id) {
5787
0
                case S7COMM_SYNTAXID_ALARM_LOCKFREESET:
5788
0
                case S7COMM_SYNTAXID_ALARM_INDSET:
5789
0
                case S7COMM_SYNTAXID_NOTIFY_INDSET:
5790
0
                case S7COMM_SYNTAXID_ALARM_ACKSET:
5791
0
                    nr_of_additional_values = tvb_get_uint8(tvb, offset);
5792
0
                    proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_nr_add_values, tvb, offset, 1, nr_of_additional_values);
5793
0
                    offset += 1;
5794
0
                    ev_id = tvb_get_ntohl(tvb, offset);
5795
0
                    proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_eventid, tvb, offset, 4, ev_id);
5796
0
                    offset += 4;
5797
0
                    proto_item_append_text(msg_obj_item_tree, ": EventID=0x%08x", ev_id);
5798
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " EventID=0x%08x", ev_id);
5799
0
                    if (syntax_id == S7COMM_SYNTAXID_ALARM_INDSET || syntax_id == S7COMM_SYNTAXID_NOTIFY_INDSET) {
5800
0
                        signalstate = tvb_get_uint8(tvb, offset);
5801
0
                        proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_eventstate,
5802
0
                            ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5803
0
                        offset += 1;
5804
                        /* show SIG with True values for a quick overview in info-column */
5805
0
                        if (signalstate > 0) {
5806
0
                            col_append_str(pinfo->cinfo, COL_INFO, " On=[");
5807
0
                            for (sig_nr = 0; sig_nr < 8; sig_nr++) {
5808
0
                                if (signalstate & 0x01) {
5809
0
                                    signalstate >>= 1;
5810
0
                                    if (signalstate == 0) {
5811
0
                                        col_append_fstr(pinfo->cinfo, COL_INFO, "SIG_%d", sig_nr + 1);
5812
0
                                    } else {
5813
0
                                        col_append_fstr(pinfo->cinfo, COL_INFO, "SIG_%d,", sig_nr + 1);
5814
0
                                    }
5815
0
                                } else {
5816
0
                                    signalstate >>= 1;
5817
0
                                }
5818
0
                            }
5819
0
                            col_append_str(pinfo->cinfo, COL_INFO, "]");
5820
0
                        }
5821
0
                        proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_state,
5822
0
                            ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5823
0
                        offset += 1;
5824
0
                    }
5825
0
                    if (syntax_id == S7COMM_SYNTAXID_ALARM_INDSET || syntax_id == S7COMM_SYNTAXID_ALARM_ACKSET || syntax_id == S7COMM_SYNTAXID_NOTIFY_INDSET) {
5826
0
                        proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_ackstate_going,
5827
0
                            ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5828
0
                        offset += 1;
5829
0
                        proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_ackstate_coming,
5830
0
                            ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5831
0
                        offset += 1;
5832
0
                    }
5833
0
                    if (syntax_id == S7COMM_SYNTAXID_NOTIFY_INDSET) {
5834
0
                        proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_event_going,
5835
0
                            ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5836
0
                        offset += 1;
5837
0
                        proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_event_coming,
5838
0
                            ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5839
0
                        offset += 1;
5840
0
                        proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_event_lastchanged,
5841
0
                            ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5842
0
                        offset += 1;
5843
0
                        proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_event_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
5844
0
                        offset += 1;
5845
0
                    }
5846
0
                    if (syntax_id == S7COMM_SYNTAXID_ALARM_INDSET || syntax_id == S7COMM_SYNTAXID_NOTIFY_INDSET) {
5847
0
                        if (nr_of_additional_values > 0) {
5848
0
                            asc_start_offset = offset;
5849
0
                            msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_associated_value, tvb, offset, 0, ENC_NA);
5850
0
                            msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_associated_value);
5851
0
                            offset = s7comm_decode_response_read_data(tvb, pinfo, msg_work_item_tree, nr_of_additional_values, offset);
5852
0
                            proto_item_set_len(msg_work_item_tree, offset - asc_start_offset);
5853
0
                        }
5854
0
                    }
5855
0
                    break;
5856
0
                case S7COMM_SYNTAXID_ALARM_QUERYREQSET:
5857
0
                    proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_unknown1, tvb, offset, 1, ENC_BIG_ENDIAN);
5858
0
                    offset += 1;
5859
0
                    querytype = tvb_get_uint8(tvb, offset);
5860
0
                    proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_querytype, tvb, offset, 1, querytype);
5861
0
                    offset += 1;
5862
0
                    proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_unknown2, tvb, offset, 1, ENC_BIG_ENDIAN);
5863
0
                    offset += 1;
5864
0
                    ev_id = tvb_get_ntohl(tvb, offset);
5865
                    /* there is a querytype=8, which only occurs when a previous SZL request 0x131 index 0x10 has a missing flag in funk_1 */
5866
0
                    switch (querytype) {
5867
0
                        case S7COMM_ALARM_MESSAGE_QUERYTYPE_BYALARMTYPE:
5868
0
                            proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_alarmtype, tvb, offset, 4, ENC_BIG_ENDIAN);
5869
0
                            col_append_fstr(pinfo->cinfo, COL_INFO, " ByAlarmtype=%s",
5870
0
                                val_to_str(pinfo->pool, ev_id, alarm_message_query_alarmtype_names, "Unknown Alarmtype: %u"));
5871
0
                            break;
5872
0
                        case S7COMM_ALARM_MESSAGE_QUERYTYPE_BYEVENTID:
5873
0
                            proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_eventid, tvb, offset, 4, ENC_BIG_ENDIAN);
5874
0
                            col_append_fstr(pinfo->cinfo, COL_INFO, " ByEventID=0x%08x", ev_id);
5875
0
                            break;
5876
0
                        default:
5877
0
                            break;
5878
0
                    }
5879
0
                    offset += 4;
5880
0
                    break;
5881
157
                default:
5882
                    /* for current unknown syntax id, set offset to end of dataset. The varspec_length includes
5883
                     * the byte for the syntax_id, so minus one.
5884
                     */
5885
157
                    offset += (varspec_length - 1);
5886
157
                    break;
5887
158
            }
5888
262
        } else if (type == S7COMM_UD_TYPE_RES) {
5889
245
            ret_val = tvb_get_uint8(tvb, offset);
5890
245
            proto_item_append_text(msg_obj_item_tree, ": (%s)", val_to_str(pinfo->pool, ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
5891
245
            proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
5892
245
            offset += 1;
5893
245
        }
5894
419
        proto_item_set_len(msg_obj_item_tree, offset - msg_obj_start_offset);
5895
419
    }
5896
45
    proto_item_set_len(msg_item_tree, offset - start_offset);
5897
45
    return offset;
5898
46
}
5899
5900
/*******************************************************************************************************
5901
 *
5902
 * PDU Type: User Data -> Function group 4 -> alarm query response
5903
 *
5904
 *******************************************************************************************************/
5905
static uint32_t
5906
s7comm_decode_ud_cpu_alarm_query_response(tvbuff_t *tvb, packet_info* pinfo,
5907
                                          proto_tree *data_tree,
5908
                                          uint32_t offset)
5909
3
{
5910
3
    proto_item *msg_item = NULL;
5911
3
    proto_tree *msg_item_tree = NULL;
5912
3
    proto_item *msg_obj_item = NULL;
5913
3
    proto_tree *msg_obj_item_tree = NULL;
5914
3
    proto_item *msg_work_item = NULL;
5915
3
    proto_tree *msg_work_item_tree = NULL;
5916
3
    uint32_t start_offset;
5917
3
    uint32_t msg_obj_start_offset;
5918
3
    uint32_t asc_start_offset;
5919
3
    uint32_t ev_id;
5920
3
    uint8_t returncode;
5921
3
    uint8_t alarmtype;
5922
3
    uint16_t complete_length;
5923
3
    int32_t remaining_length;
5924
3
    bool cont;
5925
5926
3
    start_offset = offset;
5927
3
    msg_item = proto_tree_add_item(data_tree, hf_s7comm_cpu_alarm_message_item, tvb, offset, 0, ENC_NA);
5928
3
    msg_item_tree = proto_item_add_subtree(msg_item, ett_s7comm_cpu_alarm_message);
5929
5930
    /* Maybe this value here is something different, always 0x00 or 0x01 */
5931
3
    proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_function, tvb, offset, 1, ENC_BIG_ENDIAN);
5932
3
    offset += 1;
5933
3
    proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_nr_objects, tvb, offset, 1, ENC_BIG_ENDIAN);
5934
3
    offset += 1;
5935
3
    returncode = tvb_get_uint8(tvb, offset);
5936
3
    proto_tree_add_uint(msg_item_tree, hf_s7comm_data_returncode, tvb, offset, 1, returncode);
5937
3
    offset += 1;
5938
3
    proto_tree_add_item(msg_item_tree, hf_s7comm_data_transport_size, tvb, offset, 1, ENC_BIG_ENDIAN);
5939
3
    offset += 1;
5940
3
    complete_length = tvb_get_ntohs(tvb, offset);
5941
3
    proto_tree_add_uint(msg_item_tree, hf_s7comm_cpu_alarm_query_completelen, tvb, offset, 2, complete_length);
5942
3
    remaining_length = (int32_t)complete_length;
5943
3
    offset += 2;
5944
5945
3
    if (returncode == S7COMM_ITEM_RETVAL_DATA_OK) {
5946
20
        do {
5947
20
            msg_obj_start_offset = offset;
5948
20
            msg_obj_item = proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_obj_item, tvb, offset, 0, ENC_NA);
5949
20
            msg_obj_item_tree = proto_item_add_subtree(msg_obj_item, ett_s7comm_cpu_alarm_message_object);
5950
5951
20
            proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_datasetlen, tvb, offset, 1, ENC_BIG_ENDIAN);
5952
20
            offset += 1;
5953
20
            proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_resunknown1, tvb, offset, 2, ENC_BIG_ENDIAN);
5954
20
            offset += 2;
5955
            /* begin of count dataset length */
5956
20
            alarmtype = tvb_get_uint8(tvb, offset);
5957
20
            proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_alarmtype, tvb, offset, 1, alarmtype);
5958
20
            proto_item_append_text(msg_obj_item_tree, " (Alarmtype=%s)", val_to_str(pinfo->pool, alarmtype, alarm_message_query_alarmtype_names, "Unknown Alarmtype: %u"));
5959
20
            offset += 1;
5960
20
            ev_id = tvb_get_ntohl(tvb, offset);
5961
20
            proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_eventid, tvb, offset, 4, ev_id);
5962
20
            proto_item_append_text(msg_obj_item_tree, ": EventID=0x%08x", ev_id);
5963
20
            offset += 4;
5964
20
            proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_resunknown1, tvb, offset, 1, ENC_BIG_ENDIAN);
5965
20
            offset += 1;
5966
20
            proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_eventstate,
5967
20
                ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5968
20
            offset += 1;
5969
20
            proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_ackstate_going,
5970
20
                ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5971
20
            offset += 1;
5972
20
            proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_ackstate_coming,
5973
20
                ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5974
20
            offset += 1;
5975
20
            if (alarmtype == S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_S) {
5976
                /* 8 bytes timestamp (coming)*/
5977
2
                msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_timestamp_coming, tvb, offset, 8, ENC_NA);
5978
2
                msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_timestamp);
5979
2
                offset = s7comm_add_timestamp_to_tree(tvb, msg_work_item_tree, offset, true, false);
5980
                /* Associated value of coming alarm */
5981
2
                asc_start_offset = offset;
5982
2
                msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_associated_value, tvb, offset, 0, ENC_NA);
5983
2
                msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_associated_value);
5984
2
                offset = s7comm_decode_response_read_data(tvb, pinfo, msg_work_item_tree, 1, offset);
5985
2
                proto_item_set_len(msg_work_item_tree, offset - asc_start_offset);
5986
                /* 8 bytes timestamp (going)
5987
                 * If all bytes in timestamp are zero, then the message is still active. */
5988
2
                msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_timestamp_going, tvb, offset, 8, ENC_NA);
5989
2
                msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_timestamp);
5990
2
                offset = s7comm_add_timestamp_to_tree(tvb, msg_work_item_tree, offset, true, false);
5991
                /* Associated value of going alarm  */
5992
2
                asc_start_offset = offset;
5993
2
                msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_associated_value, tvb, offset, 0, ENC_NA);
5994
2
                msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_associated_value);
5995
2
                offset = s7comm_decode_response_read_data(tvb, pinfo, msg_work_item_tree, 1, offset);
5996
2
                proto_item_set_len(msg_work_item_tree, offset - asc_start_offset);
5997
2
            }
5998
20
            remaining_length = remaining_length - (offset - msg_obj_start_offset);
5999
20
            proto_item_set_len(msg_obj_item_tree, offset - msg_obj_start_offset);
6000
            /* when complete_length is 0xffff, then loop until terminating null */
6001
20
            if (complete_length == 0xffff) {
6002
0
                cont = (tvb_get_uint8(tvb, offset) > 0);
6003
20
            } else {
6004
20
                cont = (remaining_length > 0);
6005
20
            }
6006
20
        } while (cont);
6007
3
    }
6008
3
    proto_item_set_len(msg_item_tree, offset - start_offset);
6009
6010
3
    return offset;
6011
3
}
6012
6013
/*******************************************************************************************************
6014
 *
6015
 * PDU Type: User Data -> Function group 4 -> diagnostic message
6016
 * Also used as a dataset in the diagnostic buffer, read with SZL-ID 0x00a0 index 0.
6017
 *
6018
 *******************************************************************************************************/
6019
uint32_t
6020
s7comm_decode_ud_cpu_diagnostic_message(tvbuff_t *tvb,
6021
                                        packet_info *pinfo,
6022
                                        bool add_info_to_col,
6023
                                        proto_tree *data_tree,
6024
                                        uint32_t offset)
6025
0
{
6026
0
    proto_item *msg_item = NULL;
6027
0
    proto_tree *msg_item_tree = NULL;
6028
0
    uint16_t eventid;
6029
0
    uint16_t eventid_masked;
6030
0
    const char *event_text;
6031
0
    bool has_text = false;
6032
6033
0
    msg_item = proto_tree_add_item(data_tree, hf_s7comm_cpu_diag_msg_item, tvb, offset, 20, ENC_NA);
6034
0
    msg_item_tree = proto_item_add_subtree(msg_item, ett_s7comm_cpu_diag_msg);
6035
6036
0
    eventid = tvb_get_ntohs(tvb, offset);
6037
0
    if ((eventid >= 0x8000) && (eventid <= 0x9fff)) {
6038
0
        eventid_masked = eventid & 0xf0ff;
6039
0
        if ((event_text = try_val_to_str_ext(eventid_masked, &cpu_diag_eventid_0x8_0x9_names_ext))) {
6040
0
            if (add_info_to_col) {
6041
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " Event='%s'", event_text);
6042
0
            }
6043
0
            has_text = true;
6044
0
        } else {
6045
0
            if (add_info_to_col) {
6046
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " EventID=0x%04x", eventid);
6047
0
            }
6048
0
        }
6049
0
    } else if ((eventid >= 0x1000) && (eventid < 0x8000)) {
6050
0
        if ((event_text = try_val_to_str_ext(eventid, &cpu_diag_eventid_fix_names_ext))) {
6051
0
            if (add_info_to_col) {
6052
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " Event='%s'", event_text);
6053
0
            }
6054
0
            has_text = true;
6055
0
        } else {
6056
0
            if (add_info_to_col) {
6057
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " EventID=0x%04x", eventid);
6058
0
            }
6059
0
        }
6060
0
    } else {
6061
0
        if (add_info_to_col) {
6062
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " EventID=0x%04x", eventid);
6063
0
        }
6064
0
    }
6065
0
    proto_tree_add_bitmask(msg_item_tree, tvb, offset, hf_s7comm_cpu_diag_msg_eventid,
6066
0
            ett_s7comm_cpu_diag_msg_eventid, s7comm_cpu_diag_msg_eventid_fields, ENC_BIG_ENDIAN);
6067
0
    if (has_text) {
6068
0
        proto_item_append_text(msg_item_tree, ": Event='%s'", event_text);
6069
0
    } else {
6070
0
        proto_item_append_text(msg_item_tree, ": EventID=0x%04x", eventid);
6071
0
    }
6072
0
    offset += 2;
6073
0
    proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_prioclass, tvb, offset, 1, ENC_BIG_ENDIAN);
6074
0
    offset += 1;
6075
0
    proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_obnumber, tvb, offset, 1, ENC_BIG_ENDIAN);
6076
0
    offset += 1;
6077
0
    proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_datid, tvb, offset, 2, ENC_BIG_ENDIAN);
6078
0
    offset += 2;
6079
0
    proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_info1, tvb, offset, 2, ENC_BIG_ENDIAN);
6080
0
    offset += 2;
6081
0
    proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_info2, tvb, offset, 4, ENC_BIG_ENDIAN);
6082
0
    offset += 4;
6083
0
    offset = s7comm_add_timestamp_to_tree(tvb, msg_item_tree, offset, false, false);
6084
6085
0
    return offset;
6086
0
}
6087
6088
/*******************************************************************************************************
6089
 *
6090
 * PDU Type: User Data -> Function group 7 -> time functions
6091
 *
6092
 *******************************************************************************************************/
6093
static uint32_t
6094
s7comm_decode_ud_time_subfunc(tvbuff_t *tvb,
6095
                              proto_tree *data_tree,
6096
                              uint8_t type,
6097
                              uint8_t subfunc,
6098
                              uint8_t ret_val,             /* Return value in data part */
6099
                              uint32_t dlength,
6100
                              uint32_t offset)
6101
8
{
6102
8
    bool know_data = false;
6103
6104
8
    switch (subfunc) {
6105
4
        case S7COMM_UD_SUBF_TIME_READ:
6106
4
        case S7COMM_UD_SUBF_TIME_READF:
6107
4
            if (type == S7COMM_UD_TYPE_RES) {
6108
0
                if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
6109
0
                    proto_item_append_text(data_tree, ": ");
6110
0
                    offset = s7comm_add_timestamp_to_tree(tvb, data_tree, offset, true, true);
6111
0
                }
6112
0
                know_data = true;
6113
0
            }
6114
4
            break;
6115
0
        case S7COMM_UD_SUBF_TIME_SET:
6116
0
        case S7COMM_UD_SUBF_TIME_SET2:
6117
0
            if (type == S7COMM_UD_TYPE_REQ) {
6118
0
                if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
6119
0
                    proto_item_append_text(data_tree, ": ");
6120
0
                    offset = s7comm_add_timestamp_to_tree(tvb, data_tree, offset, true, true);
6121
0
                }
6122
0
                know_data = true;
6123
0
            }
6124
0
            break;
6125
4
        default:
6126
4
            break;
6127
8
    }
6128
6129
8
    if (know_data == false && dlength > 0) {
6130
8
        proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
6131
8
        offset += dlength;
6132
8
    }
6133
8
    return offset;
6134
8
}
6135
6136
/*******************************************************************************************************
6137
 *
6138
 * PDU Type: User Data -> Function group 3 -> block functions
6139
 *
6140
 *******************************************************************************************************/
6141
static uint32_t
6142
s7comm_decode_ud_block_subfunc(tvbuff_t *tvb,
6143
                               packet_info *pinfo,
6144
                               proto_tree *data_tree,
6145
                               uint8_t type,
6146
                               uint8_t subfunc,
6147
                               uint8_t ret_val,             /* Return value in data part */
6148
                               uint8_t tsize,               /* transport size in data part */
6149
                               uint32_t dlength,
6150
                               uint32_t offset)
6151
9
{
6152
9
    uint32_t count;
6153
9
    uint32_t i;
6154
9
    const uint8_t *pBlocknumber;
6155
9
    uint16_t blocknumber;
6156
9
    uint8_t blocktype;
6157
9
    uint16_t blocktype16;
6158
9
    bool know_data = false;
6159
9
    proto_item *item = NULL;
6160
9
    proto_tree *item_tree = NULL;
6161
9
    proto_item *itemadd = NULL;
6162
9
    char str_timestamp[30];
6163
9
    char str_version[10];
6164
6165
9
    switch (subfunc) {
6166
        /*************************************************
6167
         * List blocks
6168
         */
6169
0
        case S7COMM_UD_SUBF_BLOCK_LIST:
6170
0
            if (type == S7COMM_UD_TYPE_REQ) {
6171
                /* Is this a possible combination? Never seen it... */
6172
6173
0
            } else if (type == S7COMM_UD_TYPE_RES) {
6174
0
                count = dlength / 4;
6175
0
                for (i = 0; i < count; i++) {
6176
                    /* Insert a new tree of 4 byte length for every item */
6177
0
                    item = proto_tree_add_item(data_tree, hf_s7comm_data_item, tvb, offset, 4, ENC_NA);
6178
0
                    item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
6179
0
                    blocktype16 = tvb_get_ntohs(tvb, offset);
6180
0
                    proto_item_append_text(item, " [%d]: (Block type %s)", i+1, val_to_str(pinfo->pool, blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
6181
0
                    itemadd = proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_type, tvb, offset, 2, ENC_ASCII);
6182
0
                    proto_item_append_text(itemadd, " (%s)", val_to_str(pinfo->pool, blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
6183
0
                    offset += 2;
6184
0
                    proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_cnt, tvb, offset, 2, ENC_BIG_ENDIAN);
6185
0
                    offset += 2;
6186
0
                }
6187
0
                know_data = true;
6188
0
            }
6189
0
            break;
6190
        /*************************************************
6191
         * List blocks of type
6192
         */
6193
0
        case S7COMM_UD_SUBF_BLOCK_LISTTYPE:
6194
0
            if (type == S7COMM_UD_TYPE_REQ) {
6195
0
                if (tsize != S7COMM_DATA_TRANSPORT_SIZE_NULL) {
6196
0
                    blocktype16 = tvb_get_ntohs(tvb, offset);
6197
0
                    itemadd = proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_block_type, tvb, offset, 2, ENC_ASCII);
6198
0
                    proto_item_append_text(itemadd, " (%s)", val_to_str(pinfo->pool, blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
6199
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " Type:[%s]",
6200
0
                        val_to_str(pinfo->pool, blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
6201
0
                    proto_item_append_text(data_tree, ": (%s)",
6202
0
                        val_to_str(pinfo->pool, blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
6203
0
                    offset += 2;
6204
0
                }
6205
0
                know_data = true;
6206
6207
0
            } else if (type == S7COMM_UD_TYPE_RES) {
6208
0
                if (tsize != S7COMM_DATA_TRANSPORT_SIZE_NULL) {
6209
0
                    count = dlength / 4;
6210
6211
0
                    for (i = 0; i < count; i++) {
6212
                        /* Insert a new tree of 4 byte length for every item */
6213
0
                        item = proto_tree_add_item(data_tree, hf_s7comm_data_item, tvb, offset, 4, ENC_NA);
6214
0
                        item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
6215
6216
0
                        proto_item_append_text(item, " [%d]: (Block number %d)", i+1, tvb_get_ntohs(tvb, offset));
6217
0
                        proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_num, tvb, offset, 2, ENC_BIG_ENDIAN);
6218
0
                        offset += 2;
6219
                        /* The first Byte is unknown, kind of flags? */
6220
0
                        proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
6221
0
                        offset += 1;
6222
0
                        proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
6223
0
                        offset += 1;
6224
0
                    }
6225
0
                }
6226
0
                know_data = true;
6227
0
            }
6228
0
            break;
6229
        /*************************************************
6230
         * Get block infos
6231
         */
6232
4
        case S7COMM_UD_SUBF_BLOCK_BLOCKINFO:
6233
4
            if (type == S7COMM_UD_TYPE_REQ) {
6234
0
                if (tsize != S7COMM_DATA_TRANSPORT_SIZE_NULL) {
6235
0
                    int32_t num = -1;
6236
0
                    bool num_valid;
6237
                    /* 8 Bytes of Data follow, 1./ 2. type, 3-7 blocknumber as ascii number */
6238
0
                    blocktype16 = tvb_get_ntohs(tvb, offset);
6239
0
                    itemadd = proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_block_type, tvb, offset, 2, ENC_ASCII);
6240
0
                    proto_item_append_text(itemadd, " (%s)", val_to_str(pinfo->pool, blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
6241
0
                    offset += 2;
6242
0
                    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);
6243
0
                    num_valid = ws_strtoi32((const char*)pBlocknumber, NULL, &num);
6244
0
                    proto_item_append_text(data_tree, " [%s ",
6245
0
                        val_to_str(pinfo->pool, blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
6246
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " -> Block:[%s ",
6247
0
                        val_to_str(pinfo->pool, blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
6248
0
                    if (num_valid) {
6249
0
                        proto_item_append_text(data_tree, "%d]", num);
6250
0
                        col_append_fstr(pinfo->cinfo, COL_INFO, "%d]", num);
6251
0
                    } else {
6252
0
                        expert_add_info(pinfo, data_tree, &ei_s7comm_ud_blockinfo_block_num_ascii_invalid);
6253
0
                        proto_item_append_text(data_tree, "NaN]");
6254
0
                        col_append_str(pinfo->cinfo, COL_INFO, "NaN]");
6255
0
                    }
6256
0
                    offset += 5;
6257
0
                    itemadd = proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_filesys, tvb, offset, 1, ENC_ASCII);
6258
0
                    proto_item_append_text(itemadd, " (%s)", val_to_str_const(tvb_get_uint8(tvb, offset), blocktype_attribute2_names, "Unknown filesys"));
6259
0
                    offset += 1;
6260
0
                }
6261
0
                know_data = true;
6262
6263
4
            } else if (type == S7COMM_UD_TYPE_RES) {
6264
                /* 78 Bytes */
6265
0
                if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
6266
0
                    itemadd = proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_block_type, tvb, offset, 2, ENC_ASCII);
6267
0
                    proto_item_append_text(itemadd, " (%s)", val_to_str(pinfo->pool, tvb_get_ntohs(tvb, offset), blocktype_names, "Unknown Block type: 0x%04x"));
6268
0
                    offset += 2;
6269
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_infolength, tvb, offset, 2, ENC_BIG_ENDIAN);
6270
0
                    offset += 2;
6271
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_unknown2, tvb, offset, 2, ENC_BIG_ENDIAN);
6272
0
                    offset += 2;
6273
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_const3, tvb, offset, 2, ENC_ASCII);
6274
0
                    offset += 2;
6275
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_unknown, tvb, offset, 1, ENC_NA);
6276
0
                    offset += 1;
6277
0
                    proto_tree_add_bitmask(data_tree, tvb, offset, hf_s7comm_userdata_blockinfo_flags,
6278
0
                        ett_s7comm_userdata_blockinfo_flags, s7comm_userdata_blockinfo_flags_fields, ENC_BIG_ENDIAN);
6279
0
                    offset += 1;
6280
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_block_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
6281
0
                    offset += 1;
6282
0
                    blocktype = tvb_get_uint8(tvb, offset);
6283
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_subblk_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6284
0
                    offset += 1;
6285
0
                    blocknumber = tvb_get_ntohs(tvb, offset);
6286
0
                    proto_tree_add_uint(data_tree, hf_s7comm_ud_blockinfo_block_num, tvb, offset, 2, blocknumber);
6287
                    /* Add block type and number to info column */
6288
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " -> Block:[%s %d]",
6289
0
                        val_to_str(pinfo->pool, blocktype, subblktype_names, "Unknown Subblk type: 0x%02x"),
6290
0
                        blocknumber);
6291
0
                    proto_item_append_text(data_tree, ": (Block:[%s %d])",
6292
0
                        val_to_str(pinfo->pool, blocktype, subblktype_names, "Unknown Subblk type: 0x%02x"),
6293
0
                        blocknumber);
6294
0
                    offset += 2;
6295
                    /* "Length Load mem" -> the length in Step7 Manager seems to be this length +6 bytes */
6296
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_load_mem_len, tvb, offset, 4, ENC_BIG_ENDIAN);
6297
0
                    offset += 4;
6298
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_blocksecurity, tvb, offset, 4, ENC_BIG_ENDIAN);
6299
0
                    offset += 4;
6300
0
                    s7comm_get_timestring_from_s7time(tvb, offset, str_timestamp, sizeof(str_timestamp));
6301
0
                    proto_tree_add_string(data_tree, hf_s7comm_ud_blockinfo_code_timestamp, tvb, offset, 6, str_timestamp);
6302
0
                    offset += 6;
6303
0
                    s7comm_get_timestring_from_s7time(tvb, offset, str_timestamp, sizeof(str_timestamp));
6304
0
                    proto_tree_add_string(data_tree, hf_s7comm_ud_blockinfo_interface_timestamp, tvb, offset, 6, str_timestamp);
6305
0
                    offset += 6;
6306
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_ssb_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6307
0
                    offset += 2;
6308
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_add_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6309
0
                    offset += 2;
6310
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_localdata_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6311
0
                    offset += 2;
6312
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_mc7_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6313
0
                    offset += 2;
6314
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_author, tvb, offset, 8, ENC_ASCII);
6315
0
                    offset += 8;
6316
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_family, tvb, offset, 8, ENC_ASCII);
6317
0
                    offset += 8;
6318
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_headername, tvb, offset, 8, ENC_ASCII);
6319
0
                    offset += 8;
6320
0
                    snprintf(str_version, sizeof(str_version), "%d.%d", ((tvb_get_uint8(tvb, offset) & 0xf0) >> 4), tvb_get_uint8(tvb, offset) & 0x0f);
6321
0
                    proto_tree_add_string(data_tree, hf_s7comm_ud_blockinfo_headerversion, tvb, offset, 1, str_version);
6322
0
                    offset += 1;
6323
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_unknown, tvb, offset, 1, ENC_NA);
6324
0
                    offset += 1;
6325
0
                    proto_tree_add_checksum(data_tree, tvb, offset, hf_s7comm_ud_blockinfo_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
6326
0
                    offset += 2;
6327
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_reserved1, tvb, offset, 4, ENC_BIG_ENDIAN);
6328
0
                    offset += 4;
6329
0
                    proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_reserved2, tvb, offset, 4, ENC_BIG_ENDIAN);
6330
0
                    offset += 4;
6331
0
                }
6332
0
                know_data = true;
6333
0
            }
6334
4
            break;
6335
5
        default:
6336
5
            break;
6337
9
    }
6338
9
    if (know_data == false && dlength > 0) {
6339
9
        proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
6340
9
        offset += dlength;
6341
9
    }
6342
9
    return offset;
6343
9
}
6344
6345
/*******************************************************************************************************
6346
 *
6347
 * PDU Type: User Data -> Function group 2 -> Read record
6348
 *
6349
 *******************************************************************************************************/
6350
static uint32_t
6351
s7comm_decode_ud_readrec(tvbuff_t *tvb, packet_info* pinfo,
6352
                         proto_tree *tree,
6353
                         uint8_t type,
6354
                         uint32_t offset)
6355
0
{
6356
0
    uint32_t ret_val;
6357
0
    uint32_t statuslen;
6358
0
    uint32_t reclen;
6359
0
    uint8_t item_count;
6360
6361
0
    if (type == S7COMM_UD_TYPE_REQ) {
6362
0
        proto_tree_add_item(tree, hf_s7comm_rdrec_reserved1, tvb, offset, 1, ENC_NA);
6363
0
        offset += 1;
6364
        /* Although here is an item_count field, values above 1 aren't allowed or at least never seen */
6365
0
        item_count = tvb_get_uint8(tvb, offset);
6366
0
        proto_tree_add_uint(tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
6367
0
        offset += 1;
6368
0
        if (item_count > 0) {
6369
0
            offset = s7comm_decode_param_item(tvb, pinfo, offset, tree, 0);
6370
0
        }
6371
0
    } else if (type == S7COMM_UD_TYPE_RES) {
6372
        /* The item with data is used for optional status code similar to the
6373
         * STATUS output of SFB52 RDREC used in Plc code.
6374
         */
6375
0
        proto_tree_add_item(tree, hf_s7comm_rdrec_reserved1, tvb, offset, 1, ENC_NA);
6376
0
        offset += 1;
6377
0
        item_count = tvb_get_uint8(tvb, offset);
6378
0
        proto_tree_add_uint(tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
6379
0
        offset += 1;
6380
        /* As all testsubjects have shown that no more than one item is allowed,
6381
         * we decode only the first item here.
6382
         */
6383
0
        if (item_count > 0) {
6384
0
            proto_tree_add_item_ret_uint(tree, hf_s7comm_data_returncode, tvb, offset, 1, ENC_BIG_ENDIAN, &ret_val);
6385
0
            offset += 1;
6386
0
            if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
6387
0
                proto_tree_add_item(tree, hf_s7comm_data_transport_size, tvb, offset, 1, ENC_BIG_ENDIAN);
6388
0
                offset += 1;
6389
0
            }
6390
0
            proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_statuslen, tvb, offset, 1, ENC_BIG_ENDIAN, &statuslen);
6391
0
            offset += 1;
6392
0
            if (statuslen > 0) {
6393
0
                proto_tree_add_item(tree, hf_s7comm_rdrec_statusdata, tvb, offset, statuslen, ENC_NA);
6394
0
                offset += statuslen;
6395
0
            } else {
6396
0
                offset += 1;    /* Fillbyte */
6397
0
            }
6398
0
            if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
6399
0
                proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_recordlen, tvb, offset, 2, ENC_BIG_ENDIAN, &reclen);
6400
0
                offset += 2;
6401
0
                if (reclen > 0) {
6402
0
                    proto_tree_add_item(tree, hf_s7comm_rdrec_data, tvb, offset, reclen, ENC_NA);
6403
0
                    offset += reclen;
6404
0
                }
6405
0
            }
6406
0
        }
6407
0
    }
6408
0
    return offset;
6409
0
}
6410
6411
/*******************************************************************************************************
6412
 *
6413
 * PDU Type: User Data -> Function group 2 -> cyclic services
6414
 *
6415
 *******************************************************************************************************/
6416
static uint32_t
6417
s7comm_decode_ud_cyclic_subfunc(tvbuff_t *tvb,
6418
                                packet_info *pinfo,
6419
                                uint8_t seq_num,
6420
                                proto_tree *data_tree,
6421
                                uint8_t type,
6422
                                uint8_t subfunc,
6423
                                uint32_t dlength,
6424
                                uint32_t offset)
6425
33
{
6426
33
    bool know_data = false;
6427
33
    uint32_t offset_old;
6428
33
    uint32_t len_item;
6429
33
    uint8_t item_count;
6430
33
    uint8_t i;
6431
33
    uint8_t job_id;
6432
6433
33
    switch (subfunc)
6434
33
    {
6435
0
        case S7COMM_UD_SUBF_CYCLIC_CHANGE_MOD:
6436
0
            if (type == S7COMM_UD_TYPE_REQ) {
6437
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " JobID=%d", seq_num);
6438
0
            }
6439
            /* fall through */
6440
27
        case S7COMM_UD_SUBF_CYCLIC_TRANSF:
6441
27
        case S7COMM_UD_SUBF_CYCLIC_CHANGE:
6442
27
            item_count = tvb_get_uint8(tvb, offset + 1);     /* first byte reserved??? */
6443
27
            proto_tree_add_uint(data_tree, hf_s7comm_param_itemcount, tvb, offset, 2, item_count);
6444
27
            offset += 2;
6445
27
            if (type == S7COMM_UD_TYPE_REQ) {
6446
3
                proto_tree_add_item(data_tree, hf_s7comm_cycl_interval_timebase, tvb, offset, 1, ENC_BIG_ENDIAN);
6447
3
                offset += 1;
6448
3
                proto_tree_add_item(data_tree, hf_s7comm_cycl_interval_time, tvb, offset, 1, ENC_BIG_ENDIAN);
6449
3
                offset += 1;
6450
20
                for (i = 0; i < item_count; i++) {
6451
17
                    offset_old = offset;
6452
17
                    offset = s7comm_decode_param_item(tvb, pinfo, offset, data_tree, i);
6453
                    /* if length is not a multiple of 2 and this is not the last item, then add a fill-byte */
6454
17
                    len_item = offset - offset_old;
6455
17
                    if ((len_item % 2) && (i < (item_count-1))) {
6456
8
                        offset += 1;
6457
8
                    }
6458
17
                }
6459
24
            } else if (type == S7COMM_UD_TYPE_RES || type == S7COMM_UD_TYPE_IND) {
6460
24
                col_append_fstr(pinfo->cinfo, COL_INFO, " JobID=%d", seq_num);
6461
24
                offset = s7comm_decode_response_read_data(tvb, pinfo, data_tree, item_count, offset);
6462
24
            }
6463
27
            know_data = true;
6464
27
            break;
6465
0
        case S7COMM_UD_SUBF_CYCLIC_UNSUBSCRIBE:
6466
0
            if (type == S7COMM_UD_TYPE_REQ) {
6467
0
                proto_tree_add_item(data_tree, hf_s7comm_cycl_function, tvb, offset, 1, ENC_BIG_ENDIAN);
6468
0
                offset += 1;
6469
0
                proto_tree_add_item(data_tree, hf_s7comm_cycl_jobid, tvb, offset, 1, ENC_BIG_ENDIAN);
6470
0
                job_id = tvb_get_uint8(tvb, offset);
6471
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " JobID=%d", job_id);
6472
0
                offset += 1;
6473
0
                know_data = true;
6474
0
            } else if (type == S7COMM_UD_TYPE_RES) {
6475
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " JobID=%d", seq_num);
6476
0
            }
6477
0
            break;
6478
0
        case S7COMM_UD_SUBF_CYCLIC_RDREC:
6479
0
            offset = s7comm_decode_ud_readrec(tvb, pinfo, data_tree, type, offset);
6480
0
            know_data = true;
6481
0
            break;
6482
33
    }
6483
6484
19
    if (know_data == false && dlength > 0) {
6485
6
        proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
6486
6
        offset += dlength;
6487
6
    }
6488
19
    return offset;
6489
33
}
6490
6491
/*******************************************************************************************************
6492
 *
6493
 * PDU Type: User Data: Data part and reassembly
6494
 *
6495
 *******************************************************************************************************/
6496
static uint32_t
6497
s7comm_decode_ud_data(tvbuff_t *tvb,
6498
                      packet_info *pinfo,
6499
                      proto_tree *tree,
6500
                      uint16_t dlength,
6501
                      uint8_t type,
6502
                      uint8_t funcgroup,
6503
                      uint8_t subfunc,
6504
                      uint8_t seq_num,
6505
                      uint8_t data_unit_ref,
6506
                      uint8_t last_data_unit,
6507
                      uint32_t offset,
6508
                      proto_tree *root_tree)
6509
760
{
6510
760
    proto_item *item = NULL;
6511
760
    proto_tree *data_tree = NULL;
6512
760
    uint8_t tsize;
6513
760
    uint16_t len;
6514
760
    uint8_t ret_val;
6515
760
    uint32_t length_rem = 0;
6516
760
    bool save_fragmented;
6517
760
    uint32_t frag_id = 0;
6518
760
    bool more_frags = false;
6519
760
    bool is_fragmented = false;
6520
760
    tvbuff_t* new_tvb = NULL;
6521
760
    tvbuff_t* next_tvb = NULL;
6522
760
    fragment_head *fd_head;
6523
760
    char str_fragadd[32];
6524
6525
    /* The first 4 bytes of the data part of a userdata telegram are the same for all types.
6526
     * This is also the minimum length of the data part.
6527
     */
6528
760
    if (dlength >= 4) {
6529
753
        item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6530
753
        data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6531
6532
753
        ret_val = tvb_get_uint8(tvb, offset);
6533
753
        proto_tree_add_uint(data_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
6534
753
        offset += 1;
6535
        /* Not definitely known part, kind of "transport size"? constant 0x09, 1 byte
6536
         * The position is the same as in a data response/write telegram,
6537
         */
6538
753
        tsize = tvb_get_uint8(tvb, offset);
6539
753
        proto_tree_add_uint(data_tree, hf_s7comm_data_transport_size, tvb, offset, 1, tsize);
6540
753
        offset += 1;
6541
753
        len = tvb_get_ntohs(tvb, offset);
6542
753
        proto_tree_add_uint(data_tree, hf_s7comm_data_length, tvb, offset, 2, len);
6543
753
        offset += 2;
6544
6545
753
        if (len >= 2) {
6546
643
            more_frags = (last_data_unit == S7COMM_UD_LASTDATAUNIT_NO);
6547
            /* Some packets have an additional header before the payload, which must be
6548
             * extracted from the data before reassembly.
6549
             */
6550
643
            switch (funcgroup) {
6551
95
                case S7COMM_UD_FUNCGROUP_NCPRG:
6552
95
                    offset = s7comm_decode_ud_ncprg_pre_reass(tvb, data_tree, type, subfunc, &len, offset);
6553
                    /* Unfortunately on NC programming the first PDU is always shown as reassembled also when not fragmented,
6554
                     * because data_unit_ref may overflow and start again at 0 on big file transfers.
6555
                     */
6556
95
                    is_fragmented = true;
6557
95
                    frag_id = seq_num;
6558
95
                    break;
6559
44
                case S7COMM_UD_FUNCGROUP_PBC_BSEND:
6560
                    /* The R_ID is used for fragment identification */
6561
44
                    offset = s7comm_decode_ud_pbc_bsend_pre_reass(tvb, pinfo, data_tree, type, &len, &frag_id, offset);
6562
44
                    is_fragmented = data_unit_ref > 0 || seq_num > 0;
6563
44
                    break;
6564
130
                case S7COMM_UD_FUNCGROUP_CPU:
6565
130
                    if (subfunc == S7COMM_UD_SUBF_CPU_AR_SEND_IND) {
6566
0
                        offset = s7comm_decode_ud_cpu_ar_send_pre_reass(tvb, pinfo, data_tree, &len, offset);
6567
0
                    }
6568
                    /* fragment identification is always the same here */
6569
130
                    is_fragmented = (data_unit_ref > 0);
6570
130
                    frag_id = data_unit_ref;
6571
130
                    break;
6572
374
                default:
6573
374
                    is_fragmented = (data_unit_ref > 0);
6574
374
                    frag_id = data_unit_ref;
6575
374
                    break;
6576
643
            }
6577
            /* Reassembly of fragmented data part */
6578
643
            save_fragmented = pinfo->fragmented;
6579
643
            if (is_fragmented) {            /* fragmented */
6580
141
                pinfo->fragmented = true;
6581
                /* NC programming uses a different method of fragment indication. The sequence number is used as reference-id,
6582
                 * the data unit reference number is increased with every packet, as the sender does not need to wait for
6583
                 * the acknowledge of the packet. Also different in NC programming is, that also when a packet is not
6584
                 * fragmented, data_unit_ref is > 0 and "reassembled" would be displayed even when not fragmented (count number of fragments?)
6585
                 * Using fragment number does not work here, as it's only one byte. And if there are more than 255 fragments this would fail.
6586
                 */
6587
141
                fd_head = fragment_add_seq_next(&s7comm_reassembly_table,
6588
141
                                                tvb, offset, pinfo,
6589
141
                                                frag_id,               /* ID for fragments belonging together */
6590
141
                                                NULL,                  /* void *data */
6591
141
                                                len,                   /* fragment length - to the end */
6592
141
                                                more_frags);           /* More fragments? */
6593
141
                snprintf(str_fragadd, sizeof(str_fragadd), " id=%d", frag_id);
6594
141
                new_tvb = process_reassembled_data(tvb, offset, pinfo,
6595
141
                    "Reassembled S7COMM", fd_head, &s7comm_frag_items,
6596
141
                    NULL, tree);
6597
141
                if (new_tvb) { /* take it all */
6598
                    /* add reassembly info only when there's more than one fragment */
6599
140
                    if (fd_head && fd_head->next) {
6600
0
                        col_append_fstr(pinfo->cinfo, COL_INFO, " (S7COMM reassembled%s)", str_fragadd);
6601
0
                        proto_item_append_text(data_tree, " (S7COMM reassembled%s)", str_fragadd);
6602
0
                    }
6603
140
                    next_tvb = new_tvb;
6604
140
                    offset = 0;
6605
140
                } else { /* make a new subset */
6606
1
                    next_tvb = tvb_new_subset_remaining(tvb, offset);
6607
1
                    col_append_fstr(pinfo->cinfo, COL_INFO, " (S7COMM fragment%s)", str_fragadd);
6608
1
                    proto_item_append_text(data_tree, " (S7COMM fragment%s)", str_fragadd);
6609
1
                    offset = 0;
6610
1
                }
6611
502
            } else { /* Not fragmented */
6612
502
                next_tvb = tvb;
6613
502
            }
6614
643
            pinfo->fragmented = save_fragmented;
6615
643
            length_rem = tvb_reported_length_remaining(next_tvb, offset);
6616
6617
643
            if (last_data_unit == S7COMM_UD_LASTDATAUNIT_YES && length_rem > 0) {
6618
641
                switch (funcgroup) {
6619
293
                    case S7COMM_UD_FUNCGROUP_TIS:
6620
293
                        offset = s7comm_decode_ud_tis_subfunc(next_tvb, pinfo, data_tree, type, subfunc, offset);
6621
293
                        break;
6622
33
                    case S7COMM_UD_FUNCGROUP_CYCLIC:
6623
33
                        offset = s7comm_decode_ud_cyclic_subfunc(next_tvb, pinfo, seq_num, data_tree, type, subfunc, length_rem, offset);
6624
33
                        break;
6625
9
                    case S7COMM_UD_FUNCGROUP_BLOCK:
6626
9
                        offset = s7comm_decode_ud_block_subfunc(next_tvb, pinfo, data_tree, type, subfunc, ret_val, tsize, length_rem, offset);
6627
9
                        break;
6628
129
                    case S7COMM_UD_FUNCGROUP_CPU:
6629
129
                        switch (subfunc) {
6630
36
                            case S7COMM_UD_SUBF_CPU_READSZL:
6631
36
                                offset = s7comm_decode_ud_cpu_szl_subfunc(next_tvb, pinfo, data_tree, type, ret_val, length_rem, offset);
6632
36
                                break;
6633
28
                            case S7COMM_UD_SUBF_CPU_NOTIFY_IND:
6634
28
                            case S7COMM_UD_SUBF_CPU_NOTIFY8_IND:
6635
28
                            case S7COMM_UD_SUBF_CPU_ALARMSQ_IND:
6636
28
                            case S7COMM_UD_SUBF_CPU_ALARMS_IND:
6637
43
                            case S7COMM_UD_SUBF_CPU_SCAN_IND:
6638
43
                            case S7COMM_UD_SUBF_CPU_ALARMACK:
6639
43
                            case S7COMM_UD_SUBF_CPU_ALARMACK_IND:
6640
43
                            case S7COMM_UD_SUBF_CPU_ALARM8_IND:
6641
43
                            case S7COMM_UD_SUBF_CPU_ALARM8LOCK:
6642
43
                            case S7COMM_UD_SUBF_CPU_ALARM8LOCK_IND:
6643
46
                            case S7COMM_UD_SUBF_CPU_ALARM8UNLOCK:
6644
46
                            case S7COMM_UD_SUBF_CPU_ALARM8UNLOCK_IND:
6645
46
                                offset = s7comm_decode_ud_cpu_alarm_main(next_tvb, pinfo, data_tree, type, subfunc, offset);
6646
46
                                break;
6647
3
                            case S7COMM_UD_SUBF_CPU_ALARMQUERY:
6648
3
                                if (type == S7COMM_UD_TYPE_RES) {
6649
3
                                    offset = s7comm_decode_ud_cpu_alarm_query_response(next_tvb, pinfo, data_tree, offset);
6650
3
                                } else {
6651
0
                                    offset = s7comm_decode_ud_cpu_alarm_main(next_tvb, pinfo, data_tree, type, subfunc, offset);
6652
0
                                }
6653
3
                                break;
6654
0
                            case S7COMM_UD_SUBF_CPU_DIAGMSG:
6655
0
                                offset = s7comm_decode_ud_cpu_diagnostic_message(next_tvb, pinfo, true, data_tree, offset);
6656
0
                                break;
6657
39
                            case S7COMM_UD_SUBF_CPU_MSGS:
6658
39
                                offset = s7comm_decode_message_service(next_tvb, pinfo, data_tree, type, length_rem, offset);
6659
39
                                break;
6660
0
                            case S7COMM_UD_SUBF_CPU_AR_SEND_IND:
6661
0
                                offset = s7comm_decode_ud_cpu_ar_send(next_tvb, data_tree, offset);
6662
0
                                break;
6663
5
                            default:
6664
                                /* print other currently unknown data as raw bytes */
6665
5
                                proto_tree_add_item(data_tree, hf_s7comm_userdata_data, next_tvb, offset, length_rem, ENC_NA);
6666
5
                                break;
6667
129
                        }
6668
106
                        break;
6669
106
                    case S7COMM_UD_FUNCGROUP_SEC:
6670
4
                        offset = s7comm_decode_ud_security_subfunc(next_tvb, data_tree, length_rem, offset);
6671
4
                        break;
6672
44
                    case S7COMM_UD_FUNCGROUP_PBC_BSEND:
6673
44
                        offset = s7comm_decode_ud_pbc_bsend_subfunc(next_tvb, data_tree, length_rem, offset, pinfo, root_tree);
6674
44
                        break;
6675
8
                    case S7COMM_UD_FUNCGROUP_TIME:
6676
8
                        offset = s7comm_decode_ud_time_subfunc(next_tvb, data_tree, type, subfunc, ret_val, length_rem, offset);
6677
8
                        break;
6678
95
                    case S7COMM_UD_FUNCGROUP_NCPRG:
6679
95
                        offset = s7comm_decode_ud_ncprg_subfunc(next_tvb, pinfo, data_tree, type, subfunc, length_rem, offset);
6680
95
                        break;
6681
5
                    case S7COMM_UD_FUNCGROUP_DRR:
6682
5
                        offset = s7comm_decode_ud_drr_subfunc(next_tvb, data_tree, length_rem, offset);
6683
5
                        break;
6684
21
                    default:
6685
21
                        break;
6686
641
                }
6687
641
            }
6688
643
        }
6689
753
    }
6690
483
    return offset;
6691
760
}
6692
6693
/*******************************************************************************************************
6694
 *******************************************************************************************************
6695
 *
6696
 * PDU Type: User Data
6697
 *
6698
 *******************************************************************************************************
6699
 *******************************************************************************************************/
6700
static uint32_t
6701
s7comm_decode_ud(tvbuff_t *tvb,
6702
                 packet_info *pinfo,
6703
                 proto_tree *tree,
6704
                 uint16_t plength,
6705
                 uint16_t dlength,
6706
                 uint32_t offset,
6707
                 proto_tree *root_tree)
6708
793
{
6709
793
    proto_item *item = NULL;
6710
793
    proto_tree *param_tree = NULL;
6711
6712
793
    uint32_t errorcode;
6713
793
    uint32_t offset_temp;
6714
793
    uint8_t function;
6715
793
    uint8_t type;
6716
793
    uint8_t funcgroup;
6717
793
    uint8_t subfunc;
6718
793
    uint8_t mode;
6719
793
    uint8_t data_unit_ref = 0;
6720
793
    uint8_t last_data_unit = 0;
6721
793
    uint8_t seq_num;
6722
793
    uint32_t r_id;
6723
793
    uint8_t varspec_syntax_id = 0;
6724
6725
    /* Add parameter tree */
6726
793
    item = proto_tree_add_item(tree, hf_s7comm_param, tvb, offset, plength, ENC_NA);
6727
793
    param_tree = proto_item_add_subtree(item, ett_s7comm_param);
6728
6729
793
    offset_temp = offset;
6730
6731
793
    function = tvb_get_uint8(tvb, offset_temp);
6732
793
    proto_tree_add_uint(param_tree, hf_s7comm_param_service, tvb, offset_temp, 1, function);
6733
793
    offset_temp += 1;
6734
6735
    /* It's like an itemcounter, but only the value of 1 is allowed. */
6736
793
    proto_tree_add_item(param_tree, hf_s7comm_param_itemcount, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6737
793
    offset_temp += 1;
6738
6739
793
    if (function == S7COMM_SERV_MODETRANS) {
6740
        /* Mode transition indication needs a separate handling */
6741
5
        proto_item_append_text(param_tree, ": ->(Mode transition indication)");
6742
5
        col_append_str(pinfo->cinfo, COL_INFO, " Function:[Mode transition indication]");
6743
5
        proto_tree_add_item(param_tree, hf_s7comm_modetrans_param_unknown1, tvb, offset_temp, 4, ENC_BIG_ENDIAN);
6744
5
        offset_temp += 4;
6745
5
        mode = tvb_get_uint8(tvb, offset_temp);
6746
5
        proto_tree_add_uint(param_tree, hf_s7comm_modetrans_param_mode, tvb, offset_temp, 1, mode);
6747
5
        offset_temp += 1;
6748
5
        col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6749
5
            val_to_str(pinfo->pool, mode, modetrans_param_mode_names, "Unknown mode: 0x%02x"));
6750
5
        proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, mode, modetrans_param_mode_names, "Unknown mode: 0x%02x"));
6751
5
        proto_tree_add_item(param_tree, hf_s7comm_modetrans_param_unknown2, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6752
5
        offset_temp += 1;
6753
        /* No data part here */
6754
5
        return offset_temp;
6755
5
    }
6756
6757
788
    proto_tree_add_item(param_tree, hf_s7comm_item_varspec, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6758
788
    offset_temp += 1;
6759
788
    proto_tree_add_item(param_tree, hf_s7comm_item_varspec_length, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6760
788
    offset_temp += 1;
6761
788
    varspec_syntax_id = tvb_get_uint8(tvb, offset_temp);
6762
788
    proto_tree_add_item(param_tree, hf_s7comm_item_syntax_id, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6763
788
    offset_temp += 1;
6764
6765
788
    if (varspec_syntax_id == S7COMM_SYNTAXID_PBC_ID) {
6766
        /* When the R_ID occurs here, it's USEND and needs a separate handling */
6767
7
        proto_item_append_text(param_tree, ": (Indication) ->(USEND)");
6768
7
        col_append_str(pinfo->cinfo, COL_INFO, " Function:[Indication] -> [USEND]");
6769
7
        proto_tree_add_item(param_tree, hf_s7comm_pbc_unknown, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6770
7
        offset_temp += 1;
6771
7
        proto_tree_add_item_ret_uint(param_tree, hf_s7comm_pbc_usend_r_id, tvb, offset_temp, 4, ENC_BIG_ENDIAN, &r_id);
6772
7
        col_append_fstr(pinfo->cinfo, COL_INFO, " R_ID=0x%X", r_id);
6773
        /* USEND data must fit in a single PDU. Fragmentation is not possible and we can dissect the data part here. */
6774
7
        offset += plength; /* To start of data part */
6775
7
        offset = s7comm_decode_ud_usend(tvb, tree, dlength, offset);
6776
        /* Return here as all data is decoded */
6777
7
        return offset;
6778
7
    }
6779
6780
    /* Left 2 bits for indication/request/response
6781
     * Right 6 bits for the function group
6782
     */
6783
781
    type = (tvb_get_uint8(tvb, offset_temp) & 0xc0) >> 6;
6784
781
    funcgroup = (tvb_get_uint8(tvb, offset_temp) & 0x3f);
6785
781
    proto_tree_add_item(param_tree, hf_s7comm_userdata_param_type, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6786
781
    proto_tree_add_item(param_tree, hf_s7comm_userdata_param_funcgroup, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6787
781
    offset_temp += 1;
6788
6789
781
    col_append_fstr(pinfo->cinfo, COL_INFO, " Function:[%s] -> [%s]",
6790
781
        val_to_str(pinfo->pool, type, userdata_type_names, "Unknown type: 0x%02x"),
6791
781
        val_to_str(pinfo->pool, funcgroup, userdata_functiongroup_names, "Unknown function group: 0x%02x")
6792
781
        );
6793
781
    proto_item_append_text(param_tree, ": (%s)", val_to_str(pinfo->pool, type, userdata_type_names, "Unknown type: 0x%02x"));
6794
781
    proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, funcgroup, userdata_functiongroup_names, "Unknown function group: 0x%02x"));
6795
6796
    /* 1 Byte subfunction */
6797
781
    subfunc = tvb_get_uint8(tvb, offset_temp);
6798
781
    switch (funcgroup) {
6799
306
        case S7COMM_UD_FUNCGROUP_TIS:
6800
306
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_prog, tvb, offset_temp, 1, subfunc);
6801
306
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6802
306
                val_to_str(pinfo->pool, subfunc, userdata_tis_subfunc_names, "Unknown subfunc: 0x%02x"));
6803
306
            proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, subfunc, userdata_tis_subfunc_names, "Unknown subfunc: 0x%02x"));
6804
306
            break;
6805
57
        case S7COMM_UD_FUNCGROUP_CYCLIC:
6806
57
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_cyclic, tvb, offset_temp, 1, subfunc);
6807
57
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6808
57
                val_to_str(pinfo->pool, subfunc, userdata_cyclic_subfunc_names, "Unknown subfunc: 0x%02x"));
6809
57
            proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, subfunc, userdata_cyclic_subfunc_names, "Unknown subfunc: 0x%02x"));
6810
57
            break;
6811
11
        case S7COMM_UD_FUNCGROUP_BLOCK:
6812
11
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_block, tvb, offset_temp, 1, subfunc);
6813
11
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6814
11
                val_to_str(pinfo->pool, subfunc, userdata_block_subfunc_names, "Unknown subfunc: 0x%02x"));
6815
11
            proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, subfunc, userdata_block_subfunc_names, "Unknown subfunc: 0x%02x"));
6816
11
            break;
6817
133
        case S7COMM_UD_FUNCGROUP_CPU:
6818
133
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_cpu, tvb, offset_temp, 1, subfunc);
6819
133
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6820
133
                val_to_str(pinfo->pool, subfunc, userdata_cpu_subfunc_names, "Unknown subfunc: 0x%02x"));
6821
133
            proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, subfunc, userdata_cpu_subfunc_names, "Unknown subfunc: 0x%02x"));
6822
133
            break;
6823
4
        case S7COMM_UD_FUNCGROUP_SEC:
6824
4
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_sec, tvb, offset_temp, 1, subfunc);
6825
4
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6826
4
                val_to_str(pinfo->pool, subfunc, userdata_sec_subfunc_names, "Unknown subfunc: 0x%02x"));
6827
4
            proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, subfunc, userdata_sec_subfunc_names, "Unknown subfunc: 0x%02x"));
6828
4
            break;
6829
10
        case S7COMM_UD_FUNCGROUP_TIME:
6830
10
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_time, tvb, offset_temp, 1, subfunc);
6831
10
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6832
10
                val_to_str(pinfo->pool, subfunc, userdata_time_subfunc_names, "Unknown subfunc: 0x%02x"));
6833
10
            proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, subfunc, userdata_time_subfunc_names, "Unknown subfunc: 0x%02x"));
6834
10
            break;
6835
6
        case S7COMM_UD_FUNCGROUP_DRR:
6836
6
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_drr, tvb, offset_temp, 1, subfunc);
6837
6
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6838
6
                val_to_str(pinfo->pool, subfunc, userdata_drr_subfunc_names, "Unknown subfunc: 0x%02x"));
6839
6
            proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, subfunc, userdata_drr_subfunc_names, "Unknown subfunc: 0x%02x"));
6840
6
            break;
6841
116
        case S7COMM_UD_FUNCGROUP_NCPRG:
6842
116
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_ncprg, tvb, offset_temp, 1, subfunc);
6843
116
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6844
116
                val_to_str(pinfo->pool, subfunc, userdata_ncprg_subfunc_names, "Unknown subfunc: 0x%02x"));
6845
116
            proto_item_append_text(param_tree, " ->(%s)", val_to_str(pinfo->pool, subfunc, userdata_ncprg_subfunc_names, "Unknown subfunc: 0x%02x"));
6846
116
            break;
6847
119
        default:
6848
119
            proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc, tvb, offset_temp, 1, subfunc);
6849
119
            break;
6850
781
    }
6851
762
    offset_temp += 1;
6852
    /* 1 Byte sequence number */
6853
762
    proto_tree_add_item_ret_uint8(param_tree, hf_s7comm_userdata_param_seq_num, tvb, offset_temp, 1, ENC_BIG_ENDIAN, &seq_num);
6854
762
    offset_temp += 1;
6855
762
    if (varspec_syntax_id == S7COMM_SYNTAXID_EXT) {
6856
        /* 1 Byte data unit reference. If packet is fragmented, all packets with this number belong together.
6857
         * But there are function which use a different fragment identification methon.
6858
         */
6859
9
        proto_tree_add_item_ret_uint8(param_tree, hf_s7comm_userdata_param_dataunitref, tvb, offset_temp, 1, ENC_BIG_ENDIAN, &data_unit_ref);
6860
9
        offset_temp += 1;
6861
        /* 1 Byte fragmented flag, if this is not the last data unit (telegram is fragmented) this is != 0 */
6862
9
        proto_tree_add_item_ret_uint8(param_tree, hf_s7comm_userdata_param_dataunit, tvb, offset_temp, 1, ENC_BIG_ENDIAN, &last_data_unit);
6863
9
        offset_temp += 1;
6864
9
        proto_tree_add_item_ret_uint(param_tree, hf_s7comm_param_errcod, tvb, offset_temp, 2, ENC_BIG_ENDIAN, &errorcode);
6865
9
        if (errorcode > 0) {
6866
9
            col_append_fstr(pinfo->cinfo, COL_INFO, " -> Errorcode:[0x%04x]", errorcode);
6867
9
        }
6868
9
    }
6869
762
    offset += plength;
6870
6871
762
    offset = s7comm_decode_ud_data(tvb, pinfo, tree, dlength, type, funcgroup, subfunc, seq_num, data_unit_ref, last_data_unit, offset, root_tree);
6872
6873
762
    return offset;
6874
781
}
6875
6876
/*******************************************************************************************************
6877
 *
6878
 * PDU Type: Request or Response
6879
 *
6880
 *******************************************************************************************************/
6881
static uint32_t
6882
s7comm_decode_req_resp(tvbuff_t *tvb,
6883
                       packet_info *pinfo,
6884
                       proto_tree *tree,
6885
                       uint16_t plength,
6886
                       uint16_t dlength,
6887
                       uint32_t offset,
6888
                       uint8_t rosctr)
6889
37
{
6890
37
    proto_item *item = NULL;
6891
37
    proto_tree *param_tree = NULL;
6892
37
    proto_tree *data_tree = NULL;
6893
37
    uint8_t function = 0;
6894
37
    uint8_t item_count = 0;
6895
37
    uint8_t i;
6896
37
    uint32_t offset_old;
6897
37
    uint32_t len;
6898
6899
37
    if (plength > 0) {
6900
        /* Add parameter tree */
6901
29
        item = proto_tree_add_item(tree, hf_s7comm_param, tvb, offset, plength, ENC_NA);
6902
29
        param_tree = proto_item_add_subtree(item, ett_s7comm_param);
6903
        /* Analyze function */
6904
29
        function = tvb_get_uint8(tvb, offset);
6905
        /* add param.function to info column */
6906
29
        col_append_fstr(pinfo->cinfo, COL_INFO, " Function:[%s]", val_to_str(pinfo->pool, function, param_functionnames, "Unknown function: 0x%02x"));
6907
29
        proto_tree_add_uint(param_tree, hf_s7comm_param_service, tvb, offset, 1, function);
6908
        /* show param.function code at the tree */
6909
29
        proto_item_append_text(param_tree, ": (%s)", val_to_str(pinfo->pool, function, param_functionnames, "Unknown function: 0x%02x"));
6910
29
        offset += 1;
6911
6912
29
        if (rosctr == S7COMM_ROSCTR_JOB) {
6913
23
            switch (function){
6914
6
                case S7COMM_SERV_READVAR:
6915
7
                case S7COMM_SERV_WRITEVAR:
6916
7
                    item_count = tvb_get_uint8(tvb, offset);
6917
7
                    proto_tree_add_uint(param_tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
6918
7
                    offset += 1;
6919
                    /* parse item data */
6920
48
                    for (i = 0; i < item_count; i++) {
6921
41
                        offset_old = offset;
6922
41
                        offset = s7comm_decode_param_item(tvb, pinfo, offset, param_tree, i);
6923
                        /* if length is not a multiple of 2 and this is not the last item, then add a fill-byte */
6924
41
                        len = offset - offset_old;
6925
41
                        if ((len % 2) && (i < (item_count-1))) {
6926
18
                            offset += 1;
6927
18
                        }
6928
41
                    }
6929
                    /* in write-function there is a data part */
6930
7
                    if ((function == S7COMM_SERV_WRITEVAR) && (dlength > 0)) {
6931
0
                        item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6932
0
                        data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6933
                        /* Add returned data to data-tree */
6934
0
                        offset = s7comm_decode_response_read_data(tvb, pinfo, data_tree, item_count, offset);
6935
0
                    }
6936
7
                    break;
6937
0
                case S7COMM_SERV_SETUPCOMM:
6938
0
                    offset = s7comm_decode_pdu_setup_communication(tvb, param_tree, offset);
6939
0
                    break;
6940
                /* Special functions */
6941
0
                case S7COMM_FUNCREQUESTDOWNLOAD:
6942
0
                case S7COMM_FUNCDOWNLOADBLOCK:
6943
0
                case S7COMM_FUNCDOWNLOADENDED:
6944
0
                case S7COMM_FUNCSTARTUPLOAD:
6945
0
                case S7COMM_FUNCUPLOAD:
6946
3
                case S7COMM_FUNCENDUPLOAD:
6947
3
                    offset = s7comm_decode_plc_controls_updownload(tvb, pinfo, tree, param_tree, plength, dlength, offset -1, rosctr);
6948
3
                    break;
6949
0
                case S7COMM_FUNCPISERVICE:
6950
0
                    offset = s7comm_decode_pi_service(tvb, pinfo, param_tree, plength, offset -1);
6951
0
                    break;
6952
0
                case S7COMM_FUNC_PLC_STOP:
6953
0
                    offset = s7comm_decode_plc_controls_param_hex29(tvb, param_tree, offset -1);
6954
0
                    break;
6955
6956
13
                default:
6957
                    /* Print unknown part as raw bytes */
6958
13
                    if (plength > 1) {
6959
8
                        proto_tree_add_item(param_tree, hf_s7comm_param_data, tvb, offset, plength - 1, ENC_NA);
6960
8
                    }
6961
13
                    offset += plength - 1; /* 1 byte function code */
6962
13
                    if (dlength > 0) {
6963
                        /* Add data tree
6964
                         * First 2 bytes in data seem to be a length indicator of (dlength -4 ), so next 2 bytes
6965
                         * seem to indicate something else. But I'm not sure, so leave it as it is.....
6966
                         */
6967
6
                        item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6968
6
                        data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6969
6
                        proto_tree_add_item(data_tree, hf_s7comm_readresponse_data, tvb, offset, dlength, ENC_NA);
6970
6
                        offset += dlength;
6971
6
                    }
6972
13
                    break;
6973
23
            }
6974
23
        } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
6975
6
            switch (function){
6976
0
                case S7COMM_SERV_READVAR:
6977
1
                case S7COMM_SERV_WRITEVAR:
6978
                    /* This is a read-response, so the requested data may follow when address in request was ok */
6979
1
                    item_count = tvb_get_uint8(tvb, offset);
6980
1
                    proto_tree_add_uint(param_tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
6981
1
                    offset += 1;
6982
                    /* Add data tree */
6983
1
                    item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6984
1
                    data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6985
                    /* Add returned data to data-tree */
6986
1
                    if ((function == S7COMM_SERV_READVAR) && (dlength > 0)) {
6987
0
                        offset = s7comm_decode_response_read_data(tvb, pinfo, data_tree, item_count, offset);
6988
1
                    } else if ((function == S7COMM_SERV_WRITEVAR) && (dlength > 0)) {
6989
1
                        offset = s7comm_decode_response_write_data(tvb, pinfo, data_tree, item_count, offset);
6990
1
                    }
6991
1
                    break;
6992
0
                case S7COMM_SERV_SETUPCOMM:
6993
0
                    offset = s7comm_decode_pdu_setup_communication(tvb, param_tree, offset);
6994
0
                    break;
6995
0
                case S7COMM_FUNCREQUESTDOWNLOAD:
6996
1
                case S7COMM_FUNCDOWNLOADBLOCK:
6997
1
                case S7COMM_FUNCDOWNLOADENDED:
6998
1
                case S7COMM_FUNCSTARTUPLOAD:
6999
1
                case S7COMM_FUNCUPLOAD:
7000
1
                case S7COMM_FUNCENDUPLOAD:
7001
1
                    offset = s7comm_decode_plc_controls_updownload(tvb, pinfo, tree, param_tree, plength, dlength, offset -1, rosctr);
7002
1
                    break;
7003
0
                case S7COMM_FUNCPISERVICE:
7004
0
                    if (plength >= 2) {
7005
0
                        proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
7006
0
                            ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
7007
0
                        offset += 1;
7008
0
                    }
7009
0
                    break;
7010
4
                default:
7011
                    /* Print unknown part as raw bytes */
7012
4
                    if (plength > 1) {
7013
4
                        proto_tree_add_item(param_tree, hf_s7comm_param_data, tvb, offset, plength - 1, ENC_NA);
7014
4
                    }
7015
4
                    offset += plength - 1; /* 1 byte function code */
7016
4
                    if (dlength > 0) {
7017
                        /* Add data tree
7018
                         * First 2 bytes in data seem to be a length indicator of (dlength -4 ), so next 2 bytes
7019
                         * seem to indicate something else. But I'm not sure, so leave it as it is.....
7020
                         */
7021
2
                        item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
7022
2
                        data_tree = proto_item_add_subtree(item, ett_s7comm_data);
7023
2
                        proto_tree_add_item(data_tree, hf_s7comm_readresponse_data, tvb, offset, dlength, ENC_NA);
7024
2
                        offset += dlength;
7025
2
                    }
7026
4
                    break;
7027
6
            }
7028
6
        }
7029
29
    }
7030
18
    return offset;
7031
37
}
7032
7033
/*******************************************************************************************************
7034
 *******************************************************************************************************
7035
 *
7036
 * S7-Protocol (main tree)
7037
 *
7038
 *******************************************************************************************************
7039
 *******************************************************************************************************/
7040
static bool
7041
dissect_s7comm(tvbuff_t *tvb,
7042
               packet_info *pinfo,
7043
               proto_tree *tree,
7044
               void *data _U_)
7045
3.18k
{
7046
3.18k
    proto_item *s7comm_item = NULL;
7047
3.18k
    proto_item *s7comm_sub_item = NULL;
7048
3.18k
    proto_tree *s7comm_tree = NULL;
7049
3.18k
    proto_tree *s7comm_header_tree = NULL;
7050
7051
3.18k
    uint32_t offset = 0;
7052
7053
3.18k
    uint8_t rosctr = 0;
7054
3.18k
    uint8_t hlength = 10;                /* Header 10 Bytes, when type 2 or 3 (Response) -> 12 Bytes */
7055
3.18k
    uint16_t plength = 0;
7056
3.18k
    uint16_t dlength = 0;
7057
3.18k
    uint16_t errorcode = 0;
7058
7059
    /*----------------- Heuristic Checks - Begin */
7060
    /* 1) check for minimum length */
7061
3.18k
    if(tvb_captured_length(tvb) < S7COMM_MIN_TELEGRAM_LENGTH)
7062
799
        return false;
7063
    /* 2) first byte must be 0x32 */
7064
2.39k
    if (tvb_get_uint8(tvb, 0) != S7COMM_PROT_ID)
7065
1.45k
        return false;
7066
    /* 3) second byte is a type field and only can contain values between 0x01-0x07 (1/2/3/7) */
7067
934
    if (tvb_get_uint8(tvb, 1) < 0x01 || tvb_get_uint8(tvb, 1) > 0x07)
7068
96
        return false;
7069
    /*----------------- Heuristic Checks - End */
7070
7071
838
    col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_S7COMM);
7072
838
    col_clear(pinfo->cinfo, COL_INFO);
7073
838
    col_append_sep_str(pinfo->cinfo, COL_INFO, " | ", "");
7074
7075
838
    rosctr = tvb_get_uint8(tvb, 1);                            /* Get the type byte */
7076
838
    if (rosctr == 2 || rosctr == 3) hlength = 12;               /* Header 10 Bytes, when type 2 or 3 (response) -> 12 Bytes */
7077
7078
    /* display some infos in info-column of wireshark */
7079
838
    col_append_fstr(pinfo->cinfo, COL_INFO, "ROSCTR:[%-8s]", val_to_str(pinfo->pool, rosctr, rosctr_names, "Unknown: 0x%02x"));
7080
7081
838
    s7comm_item = proto_tree_add_item(tree, proto_s7comm, tvb, 0, -1, ENC_NA);
7082
838
    s7comm_tree = proto_item_add_subtree(s7comm_item, ett_s7comm);
7083
7084
    /* insert header tree */
7085
838
    s7comm_sub_item = proto_tree_add_item(s7comm_tree, hf_s7comm_header,
7086
838
                      tvb, offset, hlength, ENC_NA);
7087
7088
    /* insert sub-items in header tree */
7089
838
    s7comm_header_tree = proto_item_add_subtree(s7comm_sub_item, ett_s7comm_header);
7090
7091
    /* Protocol Identifier, constant 0x32 */
7092
838
    proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_protid, tvb, offset, 1, ENC_BIG_ENDIAN);
7093
838
    offset += 1;
7094
7095
    /* ROSCTR (Remote Operating Service Control) - PDU Type */
7096
838
    proto_tree_add_uint(s7comm_header_tree, hf_s7comm_header_rosctr, tvb, offset, 1, rosctr);
7097
    /* Show pdu type beside the header tree */
7098
838
    proto_item_append_text(s7comm_header_tree, ": (%s)", val_to_str(pinfo->pool, rosctr, rosctr_names, "Unknown ROSCTR: 0x%02x"));
7099
838
    offset += 1;
7100
    /* Redundancy ID, reserved */
7101
838
    proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_redid, tvb, offset, 2, ENC_BIG_ENDIAN);
7102
838
    offset += 2;
7103
    /* Protocol Data Unit Reference */
7104
838
    proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_pduref, tvb, offset, 2, ENC_BIG_ENDIAN);
7105
838
    offset += 2;
7106
    /* Parameter length */
7107
838
    plength = tvb_get_ntohs(tvb, offset);
7108
838
    proto_tree_add_uint(s7comm_header_tree, hf_s7comm_header_parlg, tvb, offset, 2, plength);
7109
838
    offset += 2;
7110
    /* Data length */
7111
838
    dlength = tvb_get_ntohs(tvb, offset);
7112
838
    proto_tree_add_uint(s7comm_header_tree, hf_s7comm_header_datlg, tvb, offset, 2, dlength);
7113
838
    offset += 2;
7114
    /* when type is 2 or 3 there are 2 bytes with errorclass and errorcode */
7115
838
    if (hlength == 12) {
7116
21
        errorcode = tvb_get_ntohs(tvb, offset);     /* this uses the same errorcodes (combined) from parameter part */
7117
21
        proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_errcls, tvb, offset, 1, ENC_BIG_ENDIAN);
7118
21
        offset += 1;
7119
21
        proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_errcod, tvb, offset, 1, ENC_BIG_ENDIAN);
7120
21
        offset += 1;
7121
        /* when there is an error, use the errorcode from parameterpart*/
7122
21
        if (errorcode > 0) {
7123
19
            s7comm_item = proto_tree_add_item(s7comm_header_tree, hf_s7comm_param_errcod, tvb, offset-2, 2, ENC_BIG_ENDIAN);
7124
19
            proto_item_set_generated (s7comm_item);
7125
19
        }
7126
21
    }
7127
7128
838
    switch (rosctr) {
7129
24
        case S7COMM_ROSCTR_JOB:
7130
37
        case S7COMM_ROSCTR_ACK_DATA:
7131
37
            s7comm_decode_req_resp(tvb, pinfo, s7comm_tree, plength, dlength, offset, rosctr);
7132
37
            break;
7133
793
        case S7COMM_ROSCTR_USERDATA:
7134
793
            s7comm_decode_ud(tvb, pinfo, s7comm_tree, plength, dlength, offset, tree);
7135
793
            break;
7136
838
    }
7137
    /* Add the errorcode from header as last entry in info column */
7138
414
    if (errorcode > 0) {
7139
13
        col_append_fstr(pinfo->cinfo, COL_INFO, " -> Errorcode:[0x%04x]", errorcode);
7140
13
    }
7141
    /* set fence as there may be more than one S7comm PDU in one frame */
7142
414
    col_set_fence(pinfo->cinfo, COL_INFO);
7143
414
    return true;
7144
838
}
7145
7146
/*******************************************************************************************************
7147
 * Reassembly of S7COMM
7148
 *******************************************************************************************************/
7149
static void
7150
s7comm_defragment_init(void)
7151
14
{
7152
14
    reassembly_table_init(&s7comm_reassembly_table,
7153
14
                          &addresses_ports_reassembly_table_functions);
7154
14
}
7155
7156
/*******************************************************************************************************
7157
 *******************************************************************************************************/
7158
void
7159
proto_register_s7comm (void)
7160
14
{
7161
14
    expert_module_t* expert_s7comm;
7162
7163
    /* format:
7164
     * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
7165
     */
7166
14
    static hf_register_info hf[] = {
7167
14
        { &hf_s7comm_header,
7168
14
        { "Header", "s7comm.header", FT_NONE, BASE_NONE, NULL, 0x0,
7169
14
          "This is the header of S7 communication", HFILL }},
7170
14
        { &hf_s7comm_header_protid,
7171
14
        { "Protocol Id", "s7comm.header.protid", FT_UINT8, BASE_HEX, NULL, 0x0,
7172
14
          "Protocol Identification, 0x32 for S7", HFILL }},
7173
14
        { &hf_s7comm_header_rosctr,
7174
14
        { "ROSCTR", "s7comm.header.rosctr", FT_UINT8, BASE_DEC, VALS(rosctr_names), 0x0,
7175
14
          "Remote Operating Service Control", HFILL }},
7176
14
        { &hf_s7comm_header_redid,
7177
14
        { "Redundancy Identification (Reserved)", "s7comm.header.redid", FT_UINT16, BASE_HEX, NULL, 0x0,
7178
14
          "Redundancy Identification (Reserved), should be always 0x0000", HFILL }},
7179
14
        { &hf_s7comm_header_pduref,
7180
14
        { "Protocol Data Unit Reference", "s7comm.header.pduref", FT_UINT16, BASE_DEC, NULL, 0x0,
7181
14
          NULL, HFILL }},
7182
14
        { &hf_s7comm_header_parlg,
7183
14
        { "Parameter length", "s7comm.header.parlg", FT_UINT16, BASE_DEC, NULL, 0x0,
7184
14
          "Specifies the entire length of the parameter block in bytes", HFILL }},
7185
14
        { &hf_s7comm_header_datlg,
7186
14
        { "Data length", "s7comm.header.datlg", FT_UINT16, BASE_DEC, NULL, 0x0,
7187
14
          "Specifies the entire length of the data block in bytes", HFILL }},
7188
14
        { &hf_s7comm_header_errcls,
7189
14
        { "Error class", "s7comm.header.errcls", FT_UINT8, BASE_HEX, VALS(errcls_names), 0x0,
7190
14
          NULL, HFILL }},
7191
14
        { &hf_s7comm_header_errcod,
7192
14
        { "Error code", "s7comm.header.errcod", FT_UINT8, BASE_HEX, NULL, 0x0,
7193
14
          NULL, HFILL }},
7194
7195
14
        { &hf_s7comm_param,
7196
14
        { "Parameter", "s7comm.param", FT_NONE, BASE_NONE, NULL, 0x0,
7197
14
          "This is the parameter part of S7 communication", HFILL }},
7198
14
        { &hf_s7comm_param_errcod,
7199
14
        { "Error code", "s7comm.param.errcod", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &param_errcode_names_ext, 0x0,
7200
14
          NULL, HFILL }},
7201
14
        { &hf_s7comm_param_service,
7202
14
        { "Function", "s7comm.param.func", FT_UINT8, BASE_HEX, VALS(param_functionnames), 0x0,
7203
14
          "Indicates the function of parameter/data", HFILL }},
7204
14
        { &hf_s7comm_param_maxamq_calling,
7205
14
        { "Max AmQ (parallel jobs with ack) calling", "s7comm.param.maxamq_calling", FT_UINT16, BASE_DEC, NULL, 0x0,
7206
14
          NULL, HFILL }},
7207
14
        { &hf_s7comm_param_maxamq_called,
7208
14
        { "Max AmQ (parallel jobs with ack) called", "s7comm.param.maxamq_called", FT_UINT16, BASE_DEC, NULL, 0x0,
7209
14
          NULL, HFILL }},
7210
14
        { &hf_s7comm_param_setup_reserved1,
7211
14
        { "Reserved", "s7comm.param.setup_reserved1", FT_UINT8, BASE_HEX, NULL, 0x0,
7212
14
          NULL, HFILL }},
7213
14
        { &hf_s7comm_param_neg_pdu_length,
7214
14
        { "PDU length", "s7comm.param.pdu_length", FT_UINT16, BASE_DEC, NULL, 0x0,
7215
14
          "Negotiated PDU length", HFILL }},
7216
14
        { &hf_s7comm_param_itemcount,
7217
14
        { "Item count", "s7comm.param.itemcount", FT_UINT8, BASE_DEC, NULL, 0x0,
7218
14
          "Number of Items in parameter/data part", HFILL }},
7219
14
        { &hf_s7comm_param_data,
7220
14
        { "Parameter data", "s7comm.param.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7221
14
          NULL, HFILL }},
7222
14
        { &hf_s7comm_param_item,
7223
14
        { "Item", "s7comm.param.item", FT_NONE, BASE_NONE, NULL, 0x0,
7224
14
          NULL, HFILL }},
7225
14
        { &hf_s7comm_param_subitem,
7226
14
        { "Subitem", "s7comm.param.subitem", FT_NONE, BASE_NONE, NULL, 0x0,
7227
14
          NULL, HFILL }},
7228
14
        { &hf_s7comm_item_varspec,
7229
14
        { "Variable specification", "s7comm.param.item.varspec", FT_UINT8, BASE_HEX, NULL, 0x0,
7230
14
          NULL, HFILL }},
7231
14
        { &hf_s7comm_item_varspec_length,
7232
14
        { "Length of following address specification", "s7comm.param.item.varspec_length", FT_UINT8, BASE_DEC, NULL, 0x0,
7233
14
          NULL, HFILL }},
7234
14
        { &hf_s7comm_item_syntax_id,
7235
14
        { "Syntax Id", "s7comm.param.item.syntaxid", FT_UINT8, BASE_HEX, VALS(item_syntaxid_names), 0x0,
7236
14
          "Syntax Id, format type of following address specification", HFILL }},
7237
14
        { &hf_s7comm_item_transport_size,
7238
14
        { "Transport size", "s7comm.param.item.transp_size", FT_UINT8, BASE_DEC, VALS(item_transportsizenames), 0x0,
7239
14
          NULL, HFILL }},
7240
14
        { &hf_s7comm_item_length,
7241
14
        { "Length", "s7comm.param.item.length", FT_UINT16, BASE_DEC, NULL, 0x0,
7242
14
          NULL, HFILL }},
7243
14
        { &hf_s7comm_item_db,
7244
14
        { "DB number", "s7comm.param.item.db", FT_UINT16, BASE_DEC, NULL, 0x0,
7245
14
          NULL, HFILL }},
7246
14
        { &hf_s7comm_item_area,
7247
14
        { "Area", "s7comm.param.item.area", FT_UINT8, BASE_HEX, VALS(item_areanames), 0x0,
7248
14
          NULL, HFILL }},
7249
14
        { &hf_s7comm_item_address,
7250
14
        { "Address", "s7comm.param.item.address", FT_UINT24, BASE_HEX, NULL, 0x0,
7251
14
          NULL, HFILL }},
7252
14
        { &hf_s7comm_item_address_byte,
7253
14
        { "Byte Address", "s7comm.param.item.address.byte", FT_UINT24, BASE_DEC, NULL, 0x07fff8,
7254
14
          NULL, HFILL }},
7255
14
        { &hf_s7comm_item_address_bit,
7256
14
        { "Bit Address", "s7comm.param.item.address.bit", FT_UINT24, BASE_DEC, NULL, 0x000007,
7257
14
          NULL, HFILL }},
7258
14
        { &hf_s7comm_item_address_nr,
7259
14
        { "Number (T/C/BLOCK)", "s7comm.param.item.address.number", FT_UINT24, BASE_DEC, NULL, 0x00ffff,
7260
14
          NULL, HFILL }},
7261
        /* Special variable read with Syntax-Id 0xb0 (DBREAD) */
7262
14
        { &hf_s7comm_item_dbread_numareas,
7263
14
        { "Number of areas", "s7comm.param.item.dbread.numareas", FT_UINT8, BASE_DEC, NULL, 0x0,
7264
14
          "Number of area specifications following", HFILL }},
7265
14
        { &hf_s7comm_item_dbread_length,
7266
14
        { "Bytes to read", "s7comm.param.item.dbread.length", FT_UINT8, BASE_DEC, NULL, 0x0,
7267
14
          "Number of bytes to read", HFILL }},
7268
14
        { &hf_s7comm_item_dbread_db,
7269
14
        { "DB number", "s7comm.param.item.dbread.db", FT_UINT16, BASE_DEC, NULL, 0x0,
7270
14
          NULL, HFILL }},
7271
14
        { &hf_s7comm_item_dbread_startadr,
7272
14
        { "Start address", "s7comm.param.item.dbread.startaddress", FT_UINT16, BASE_DEC, NULL, 0x0,
7273
14
          NULL, HFILL }},
7274
        /* Reading frequency inverter parameters via routing */
7275
14
        { &hf_s7comm_item_driveesany_unknown1,
7276
14
        { "DriveES Unknown 1", "s7comm.param.item.driveesany.unknown1", FT_UINT8, BASE_DEC, NULL, 0x0,
7277
14
          NULL, HFILL }},
7278
14
        { &hf_s7comm_item_driveesany_unknown2,
7279
14
        { "DriveES Unknown 2", "s7comm.param.item.driveesany.unknown2", FT_UINT16, BASE_DEC, NULL, 0x0,
7280
14
          NULL, HFILL }},
7281
14
        { &hf_s7comm_item_driveesany_unknown3,
7282
14
        { "DriveES Unknown 3", "s7comm.param.item.driveesany.unknown3", FT_UINT16, BASE_HEX, NULL, 0x0,
7283
14
          NULL, HFILL }},
7284
14
        { &hf_s7comm_item_driveesany_parameter_nr,
7285
14
        { "DriveES Parameter number", "s7comm.param.item.driveesany.parameternr", FT_UINT16, BASE_DEC, NULL, 0x0,
7286
14
          NULL, HFILL }},
7287
14
        { &hf_s7comm_item_driveesany_parameter_idx,
7288
14
        { "DriveES Parameter index", "s7comm.param.item.driveesany.parameteridx", FT_UINT16, BASE_DEC, NULL, 0x0,
7289
14
          NULL, HFILL }},
7290
        /* NCK access with Syntax-Id 0x82 */
7291
14
        { &hf_s7comm_item_nck_areaunit,
7292
14
        { "NCK Area/Unit", "s7comm.param.item.nck.area_unit", FT_UINT8, BASE_HEX, NULL, 0x0,
7293
14
          "NCK Area/Unit: Bitmask aaauuuuu: a=area, u=unit", HFILL }},
7294
14
        { &hf_s7comm_item_nck_area,
7295
14
        { "NCK Area", "s7comm.param.item.nck.area", FT_UINT8, BASE_DEC, VALS(nck_area_names), 0xe0,
7296
14
          NULL, HFILL }},
7297
14
        { &hf_s7comm_item_nck_unit,
7298
14
        { "NCK Unit", "s7comm.param.item.nck.unit", FT_UINT8, BASE_DEC, NULL, 0x1f,
7299
14
          NULL, HFILL }},
7300
14
        { &hf_s7comm_item_nck_column,
7301
14
        { "NCK Column number", "s7comm.param.item.nck.column", FT_UINT16, BASE_DEC, NULL, 0x0,
7302
14
          NULL, HFILL }},
7303
14
        { &hf_s7comm_item_nck_line,
7304
14
        { "NCK Line number", "s7comm.param.item.nck.line", FT_UINT16, BASE_DEC, NULL, 0x0,
7305
14
          NULL, HFILL }},
7306
14
        { &hf_s7comm_item_nck_module,
7307
14
        { "NCK Module", "s7comm.param.item.nck.module", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &nck_module_names_ext, 0x0,
7308
14
          NULL, HFILL }},
7309
14
        { &hf_s7comm_item_nck_linecount,
7310
14
        { "NCK Linecount", "s7comm.param.item.nck.linecount", FT_UINT8, BASE_DEC, NULL, 0x0,
7311
14
          NULL, HFILL }},
7312
7313
14
        { &hf_s7comm_data,
7314
14
        { "Data", "s7comm.data", FT_NONE, BASE_NONE, NULL, 0x0,
7315
14
          "This is the data part of S7 communication", HFILL }},
7316
14
        { &hf_s7comm_data_returncode,
7317
14
        { "Return code", "s7comm.data.returncode", FT_UINT8, BASE_HEX, VALS(s7comm_item_return_valuenames), 0x0,
7318
14
          NULL, HFILL }},
7319
14
        { &hf_s7comm_data_transport_size,
7320
14
        { "Transport size", "s7comm.data.transportsize", FT_UINT8, BASE_HEX, VALS(data_transportsizenames), 0x0,
7321
14
          "Data type / Transport size. If 3, 4 or 5 the following length gives the number of bits, otherwise the number of bytes.", HFILL }},
7322
14
        { &hf_s7comm_data_length,
7323
14
        { "Length", "s7comm.data.length", FT_UINT16, BASE_DEC, NULL, 0x0,
7324
14
          "Length of data", HFILL }},
7325
7326
14
        { &hf_s7comm_data_item,
7327
14
        { "Item", "s7comm.data.item", FT_NONE, BASE_NONE, NULL, 0x0,
7328
14
          NULL, HFILL }},
7329
7330
14
        { &hf_s7comm_readresponse_data,
7331
14
        { "Data", "s7comm.resp.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7332
14
          NULL, HFILL }},
7333
14
        { &hf_s7comm_data_fillbyte,
7334
14
        { "Fill byte", "s7comm.data.fillbyte", FT_UINT8, BASE_HEX, NULL, 0x0,
7335
14
          NULL, HFILL }},
7336
7337
14
        { &hf_s7comm_userdata_data,
7338
14
        { "Data", "s7comm.data.userdata", FT_BYTES, BASE_NONE, NULL, 0x0,
7339
14
          "Userdata data", HFILL }},
7340
7341
        /* Userdata parameter 8/12 Bytes len*/
7342
14
        { &hf_s7comm_userdata_param_type,
7343
14
        { "Type", "s7comm.param.userdata.type", FT_UINT8, BASE_DEC, VALS(userdata_type_names), 0xc0,
7344
14
          "Type of parameter", HFILL }},
7345
14
        { &hf_s7comm_userdata_param_funcgroup,
7346
14
        { "Function group", "s7comm.param.userdata.funcgroup", FT_UINT8, BASE_DEC, VALS(userdata_functiongroup_names), 0x3f,
7347
14
          NULL, HFILL }},
7348
7349
14
        { &hf_s7comm_userdata_param_subfunc_prog,
7350
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_tis_subfunc_names), 0x0,
7351
14
          NULL, HFILL }},
7352
14
        { &hf_s7comm_userdata_param_subfunc_cyclic,
7353
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_cyclic_subfunc_names), 0x0,
7354
14
          NULL, HFILL }},
7355
14
        { &hf_s7comm_userdata_param_subfunc_block,
7356
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_block_subfunc_names), 0x0,
7357
14
          NULL, HFILL }},
7358
14
        { &hf_s7comm_userdata_param_subfunc_cpu,
7359
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_cpu_subfunc_names), 0x0,
7360
14
          NULL, HFILL }},
7361
14
        { &hf_s7comm_userdata_param_subfunc_sec,
7362
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_sec_subfunc_names), 0x0,
7363
14
          NULL, HFILL }},
7364
14
        { &hf_s7comm_userdata_param_subfunc_time,
7365
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_time_subfunc_names), 0x0,
7366
14
          NULL, HFILL }},
7367
14
        { &hf_s7comm_userdata_param_subfunc,
7368
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_HEX, NULL, 0x0,
7369
14
          NULL, HFILL }},
7370
14
        { &hf_s7comm_userdata_param_subfunc_ncprg,
7371
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_ncprg_subfunc_names), 0x0,
7372
14
          NULL, HFILL }},
7373
14
        { &hf_s7comm_userdata_param_subfunc_drr,
7374
14
        { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_drr_subfunc_names), 0x0,
7375
14
          NULL, HFILL }},
7376
7377
14
        { &hf_s7comm_userdata_param_seq_num,
7378
14
        { "Sequence number", "s7comm.param.userdata.seq_num", FT_UINT8, BASE_DEC, NULL, 0x0,
7379
14
          NULL, HFILL }},
7380
7381
14
        { &hf_s7comm_userdata_param_dataunitref,
7382
14
        { "Data unit reference number", "s7comm.param.userdata.dataunitref", FT_UINT8, BASE_DEC, NULL, 0x0,
7383
14
          "Data unit reference number if PDU is fragmented", HFILL }},
7384
7385
14
        { &hf_s7comm_userdata_param_dataunit,
7386
14
        { "Last data unit", "s7comm.param.userdata.lastdataunit", FT_UINT8, BASE_HEX, VALS(userdata_lastdataunit_names), 0x0,
7387
14
          NULL, HFILL }},
7388
7389
        /* block functions / info */
7390
14
        { &hf_s7comm_ud_blockinfo_block_type,
7391
14
        { "Block type", "s7comm.blockinfo.blocktype", FT_STRING, BASE_NONE, NULL, 0x0,
7392
14
          NULL, HFILL }},
7393
14
        { &hf_s7comm_ud_blockinfo_block_cnt,
7394
14
        { "Block count", "s7comm.blockinfo.block_count", FT_UINT16, BASE_DEC, NULL, 0x0,
7395
14
          NULL, HFILL }},
7396
14
        { &hf_s7comm_ud_blockinfo_block_num,
7397
14
        { "Block number", "s7comm.blockinfo.block_num", FT_UINT16, BASE_DEC, NULL, 0x0,
7398
14
          NULL, HFILL }},
7399
14
        { &hf_s7comm_ud_blockinfo_block_flags,
7400
14
        { "Block flags (unknown)", "s7comm.blockinfo.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
7401
14
          NULL, HFILL }},
7402
14
        { &hf_s7comm_ud_blockinfo_block_lang,
7403
14
        { "Block language", "s7comm.blockinfo.block_lang", FT_UINT8, BASE_DEC, VALS(blocklanguage_names), 0x0,
7404
14
          NULL, HFILL }},
7405
14
        { &hf_s7comm_ud_blockinfo_block_num_ascii,
7406
14
        { "Block number", "s7comm.data.blockinfo.block_number", FT_STRING, BASE_NONE, NULL, 0x0,
7407
14
          NULL, HFILL }},
7408
14
        { &hf_s7comm_ud_blockinfo_filesys,
7409
14
        { "Filesystem", "s7comm.data.blockinfo.filesys", FT_STRING, BASE_NONE, NULL, 0x0,
7410
14
          NULL, HFILL }},
7411
14
        { &hf_s7comm_ud_blockinfo_res_infolength,
7412
14
        { "Length of Info", "s7comm.blockinfo.res_infolength", FT_UINT16, BASE_DEC, NULL, 0x0,
7413
14
          "Length of Info in bytes", HFILL }},
7414
14
        { &hf_s7comm_ud_blockinfo_res_unknown2,
7415
14
        { "Unknown blockinfo 2", "s7comm.blockinfo.res_unknown2", FT_UINT16, BASE_HEX, NULL, 0x0,
7416
14
          NULL, HFILL }},
7417
14
        { &hf_s7comm_ud_blockinfo_res_const3,
7418
14
        { "Constant 3", "s7comm.blockinfo.res_const3", FT_STRING, BASE_NONE, NULL, 0x0,
7419
14
          "Possible constant 3, seems to be always 'pp'", HFILL }},
7420
14
        { &hf_s7comm_ud_blockinfo_res_unknown,
7421
14
        { "Unknown byte(s) blockinfo", "s7comm.blockinfo.res_unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
7422
14
          NULL, HFILL }},
7423
14
        { &hf_s7comm_ud_blockinfo_subblk_type,
7424
14
        { "Subblk type", "s7comm.blockinfo.subblk_type", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
7425
14
          NULL, HFILL }},
7426
14
        { &hf_s7comm_ud_blockinfo_load_mem_len,
7427
14
        { "Length load memory", "s7comm.blockinfo.load_mem_len", FT_UINT32, BASE_DEC, NULL, 0x0,
7428
14
          "Length of load memory in bytes", HFILL }},
7429
14
        { &hf_s7comm_ud_blockinfo_blocksecurity,
7430
14
        { "Block Security", "s7comm.blockinfo.blocksecurity", FT_UINT32, BASE_DEC, VALS(blocksecurity_names), 0x0,
7431
14
          NULL, HFILL }},
7432
14
        { &hf_s7comm_ud_blockinfo_interface_timestamp,
7433
14
        { "Interface timestamp", "s7comm.blockinfo.interface_timestamp", FT_STRING, BASE_NONE, NULL, 0x0,
7434
14
          NULL, HFILL }},
7435
14
        { &hf_s7comm_ud_blockinfo_code_timestamp,
7436
14
        { "Code timestamp", "s7comm.blockinfo.code_timestamp", FT_STRING, BASE_NONE, NULL, 0x0,
7437
14
          NULL, HFILL }},
7438
14
        { &hf_s7comm_ud_blockinfo_ssb_len,
7439
14
        { "SSB length", "s7comm.blockinfo.ssb_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7440
14
          NULL, HFILL }},
7441
14
        { &hf_s7comm_ud_blockinfo_add_len,
7442
14
        { "ADD length", "s7comm.blockinfo.add_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7443
14
          NULL, HFILL }},
7444
14
        { &hf_s7comm_ud_blockinfo_localdata_len,
7445
14
        { "Localdata length", "s7comm.blockinfo.localdata_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7446
14
          "Length of localdata in bytes", HFILL }},
7447
14
        { &hf_s7comm_ud_blockinfo_mc7_len,
7448
14
        { "MC7 code length", "s7comm.blockinfo.mc7_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7449
14
          "Length of MC7 code in bytes", HFILL }},
7450
14
        { &hf_s7comm_ud_blockinfo_author,
7451
14
        { "Author", "s7comm.blockinfo.author", FT_STRING, BASE_NONE, NULL, 0x0,
7452
14
          NULL, HFILL }},
7453
14
        { &hf_s7comm_ud_blockinfo_family,
7454
14
        { "Family", "s7comm.blockinfo.family", FT_STRING, BASE_NONE, NULL, 0x0,
7455
14
          NULL, HFILL }},
7456
14
        { &hf_s7comm_ud_blockinfo_headername,
7457
14
        { "Name (Header)", "s7comm.blockinfo.headername", FT_STRING, BASE_NONE, NULL, 0x0,
7458
14
          NULL, HFILL }},
7459
14
        { &hf_s7comm_ud_blockinfo_headerversion,
7460
14
        { "Version (Header)", "s7comm.blockinfo.headerversion", FT_STRING, BASE_NONE, NULL, 0x0,
7461
14
          NULL, HFILL }},
7462
14
        { &hf_s7comm_ud_blockinfo_checksum,
7463
14
        { "Block checksum", "s7comm.blockinfo.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
7464
14
          NULL, HFILL }},
7465
14
        { &hf_s7comm_ud_blockinfo_reserved1,
7466
14
        { "Reserved 1", "s7comm.blockinfo.reserved1", FT_UINT32, BASE_HEX, NULL, 0x0,
7467
14
          NULL, HFILL }},
7468
14
        { &hf_s7comm_ud_blockinfo_reserved2,
7469
14
        { "Reserved 2", "s7comm.blockinfo.reserved2", FT_UINT32, BASE_HEX, NULL, 0x0,
7470
14
          NULL, HFILL }},
7471
7472
        /* Flags in blockinfo response */
7473
14
        { &hf_s7comm_userdata_blockinfo_flags,
7474
14
        { "Block flags", "s7comm.param.userdata.blockinfo.flags", FT_UINT8, BASE_HEX, NULL, 0xff,
7475
14
          "Some block configuration flags", HFILL }},
7476
         /* Bit : 0 -> DB Linked = true */
7477
14
        { &hf_s7comm_userdata_blockinfo_linked,
7478
14
        { "Linked", "s7comm.param.userdata.blockinfo.linked", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
7479
14
          NULL, HFILL }},
7480
        /* Bit : 1 -> Standard block = true */
7481
14
        { &hf_s7comm_userdata_blockinfo_standard_block,
7482
14
        { "Standard block", "s7comm.param.userdata.blockinfo.standard_block", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
7483
14
          NULL, HFILL }},
7484
        /* Bit : 5 -> DB Non Retain = true */
7485
14
        { &hf_s7comm_userdata_blockinfo_nonretain,
7486
14
        { "Non Retain", "s7comm.param.userdata.blockinfo.nonretain", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
7487
14
          NULL, HFILL }},
7488
7489
        /* Programmer commands / Test and installation (TIS) functions */
7490
14
        { &hf_s7comm_tis_parameter,
7491
14
        { "TIS Parameter", "s7comm.tis.parameter", FT_NONE, BASE_NONE, NULL, 0x0,
7492
14
          "TIS Test and Installation: Parameter", HFILL }},
7493
14
        { &hf_s7comm_tis_data,
7494
14
        { "TIS Data", "s7comm.cpu.tis.data", FT_NONE, BASE_NONE, NULL, 0x0,
7495
14
          "TIS Test and Installation: Data", HFILL }},
7496
14
        { &hf_s7comm_tis_parametersize,
7497
14
        { "TIS Parameter size", "s7comm.tis.parametersize", FT_UINT16, BASE_DEC, NULL, 0x0,
7498
14
          NULL, HFILL }},
7499
14
        { &hf_s7comm_tis_datasize,
7500
14
        { "TIS Data size", "s7comm.tis.datasize", FT_UINT16, BASE_DEC, NULL, 0x0,
7501
14
          NULL, HFILL }},
7502
14
        { &hf_s7comm_tis_param1,
7503
14
        { "TIS Parameter 1", "s7comm.tis.param1", FT_UINT16, BASE_DEC, NULL, 0x0,
7504
14
          NULL, HFILL }},
7505
14
        { &hf_s7comm_tis_param2,
7506
14
        { "TIS Parameter 2 - Trigger type", "s7comm.tis.param2", FT_UINT16, BASE_DEC, VALS(tis_param2_names), 0x0,
7507
14
          NULL, HFILL }},
7508
14
        { &hf_s7comm_tis_param3,
7509
14
        { "TIS Parameter 3 - Trigger frequency", "s7comm.tis.param3", FT_UINT16, BASE_DEC, VALS(tis_param3_names), 0x0,
7510
14
          NULL, HFILL }},
7511
14
        { &hf_s7comm_tis_answersize,
7512
14
        { "TIS Parameter 4 - Answer size", "s7comm.tis.answersize", FT_UINT16, BASE_DEC, NULL, 0x0,
7513
14
          "TIS Answer size: Expected data size of PLC answer to this job", HFILL }},
7514
14
        { &hf_s7comm_tis_param5,
7515
14
        { "TIS Parameter 5", "s7comm.tis.param5", FT_UINT16, BASE_DEC, NULL, 0x0,
7516
14
          NULL, HFILL }},
7517
14
        { &hf_s7comm_tis_param6,
7518
14
        { "TIS Parameter 6", "s7comm.tis.param6", FT_UINT16, BASE_DEC, NULL, 0x0,
7519
14
          NULL, HFILL }},
7520
14
        { &hf_s7comm_tis_param7,
7521
14
        { "TIS Parameter 7", "s7comm.tis.param7", FT_UINT16, BASE_DEC, NULL, 0x0,
7522
14
          NULL, HFILL }},
7523
14
        { &hf_s7comm_tis_param8,
7524
14
        { "TIS Parameter 8", "s7comm.tis.param8", FT_UINT16, BASE_DEC, NULL, 0x0,
7525
14
          NULL, HFILL }},
7526
14
        { &hf_s7comm_tis_param9,
7527
14
        { "TIS Parameter 9", "s7comm.tis.param9", FT_UINT16, BASE_DEC, NULL, 0x0,
7528
14
          NULL, HFILL }},
7529
14
        { &hf_s7comm_tis_trgevent,
7530
14
        { "TIS Parameter 10 - Trigger event", "s7comm.varstat.trgevent", FT_UINT16, BASE_HEX, VALS(userdata_varstat_trgevent_names), 0x0,
7531
14
          NULL, HFILL }},
7532
14
        { &hf_s7comm_tis_res_param1,
7533
14
        { "TIS Response Parameter 1", "s7comm.tis.res.param1", FT_UINT16, BASE_HEX, NULL, 0x0,
7534
14
          NULL, HFILL }},
7535
14
        { &hf_s7comm_tis_res_param2,
7536
14
        { "TIS Response Parameter 2", "s7comm.tis.res.param2", FT_UINT16, BASE_HEX, NULL, 0x0,
7537
14
          NULL, HFILL }},
7538
14
        { &hf_s7comm_tis_job_function,
7539
14
        { "Job function", "s7comm.tis.job.function", FT_UINT8, BASE_DEC, VALS(userdata_tis_subfunc_names), 0x0,
7540
14
          NULL, HFILL }},
7541
14
        { &hf_s7comm_tis_job_seqnr,
7542
14
        { "Job reference sequence number", "s7comm.tis.job.response_seq_num", FT_UINT8, BASE_DEC, NULL, 0x0,
7543
14
          "Job reference sequence number (find function setup with s7comm.param.userdata.seq_num)", HFILL }},
7544
14
        { &hf_s7comm_tis_job_reserved,
7545
14
        { "Job Reserved / Unknown", "s7comm.tis.job.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7546
14
          NULL, HFILL }},
7547
14
        { &hf_s7comm_tis_interrupted_blocktype,
7548
14
        { "Interrupted block type", "s7comm.tis.interrupted.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7549
14
          NULL, HFILL }},
7550
14
        { &hf_s7comm_tis_interrupted_blocknr,
7551
14
        { "Interrupted block number", "s7comm.tis.interrupted.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7552
14
          NULL, HFILL }},
7553
14
        { &hf_s7comm_tis_interrupted_address,
7554
14
        { "Interrupted code address", "s7comm.tis.interrupted.address", FT_UINT16, BASE_DEC, NULL, 0x0,
7555
14
          NULL, HFILL }},
7556
14
        { &hf_s7comm_tis_interrupted_prioclass,
7557
14
        { "Interrupted priority class", "s7comm.tis.interrupted.priorityclass", FT_UINT8, BASE_DEC, NULL, 0x0,
7558
14
          NULL, HFILL }},
7559
14
        { &hf_s7comm_tis_continued_blocktype,
7560
14
        { "Continued block type", "s7comm.tis.continued.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7561
14
          NULL, HFILL }},
7562
14
        { &hf_s7comm_tis_continued_blocknr,
7563
14
        { "Continued block number", "s7comm.tis.continued.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7564
14
          NULL, HFILL }},
7565
14
        { &hf_s7comm_tis_continued_address,
7566
14
        { "Continued code address", "s7comm.tis.continued.address", FT_UINT16, BASE_DEC, NULL, 0x0,
7567
14
          NULL, HFILL }},
7568
14
        { &hf_s7comm_tis_breakpoint_blocktype,
7569
14
        { "Breakpoint block type", "s7comm.tis.breakpoint.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7570
14
          NULL, HFILL }},
7571
14
        { &hf_s7comm_tis_breakpoint_blocknr,
7572
14
        { "Breakpoint block number", "s7comm.tis.breakpoint.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7573
14
          NULL, HFILL }},
7574
14
        { &hf_s7comm_tis_breakpoint_address,
7575
14
        { "Breakpoint code address", "s7comm.tis.breakpoint.address", FT_UINT16, BASE_DEC, NULL, 0x0,
7576
14
          NULL, HFILL }},
7577
14
        { &hf_s7comm_tis_breakpoint_reserved,
7578
14
        { "Breakpoint Reserved / Unknown", "s7comm.tis.breakpoint.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7579
14
          NULL, HFILL }},
7580
7581
14
        { &hf_s7comm_tis_p_callenv,
7582
14
        { "Call environment setup", "s7comm.tis.callenv_setup", FT_UINT16, BASE_DEC, VALS(tis_p_callenv_names), 0x0,
7583
14
          NULL, HFILL }},
7584
14
        { &hf_s7comm_tis_p_callcond,
7585
14
        { "Call condition", "s7comm.tis.callenv_cond", FT_UINT16, BASE_DEC, VALS(tis_p_callcond_names), 0x0,
7586
14
          NULL, HFILL }},
7587
14
        { &hf_s7comm_tis_p_callcond_blocktype,
7588
14
        { "Call condition block type", "s7comm.tis.callenv_cond_blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7589
14
          NULL, HFILL }},
7590
14
        { &hf_s7comm_tis_p_callcond_blocknr,
7591
14
        { "Call condition block number", "s7comm.tis.callenv_cond_blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7592
14
          NULL, HFILL }},
7593
14
        { &hf_s7comm_tis_p_callcond_address,
7594
14
        { "Call condition code address", "s7comm.tis.callenv_cond_blockaddress", FT_UINT16, BASE_DEC, NULL, 0x0,
7595
14
          NULL, HFILL }},
7596
7597
14
        { &hf_s7comm_tis_register_db1_type,
7598
14
        { "Register DB1 content type", "s7comm.tis.db1.type", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
7599
14
          NULL, HFILL }},
7600
14
        { &hf_s7comm_tis_register_db2_type,
7601
14
        { "Register DB2 content type", "s7comm.tis.db2.type", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
7602
14
          NULL, HFILL }},
7603
14
        { &hf_s7comm_tis_register_db1_nr,
7604
14
        { "Register DB1 block number", "s7comm.tis.db1.number", FT_UINT16, BASE_DEC, NULL, 0x0,
7605
14
          NULL, HFILL }},
7606
14
        { &hf_s7comm_tis_register_db2_nr,
7607
14
        { "Register DB2 block number", "s7comm.tis.db2.number", FT_UINT16, BASE_DEC, NULL, 0x0,
7608
14
          NULL, HFILL }},
7609
14
        { &hf_s7comm_tis_register_accu1,
7610
14
        { "Register ACCU1", "s7comm.tis.accu1", FT_UINT32, BASE_HEX, NULL, 0x0,
7611
14
          NULL, HFILL }},
7612
14
        { &hf_s7comm_tis_register_accu2,
7613
14
        { "Register ACCU2", "s7comm.tis.accu2", FT_UINT32, BASE_HEX, NULL, 0x0,
7614
14
          NULL, HFILL }},
7615
14
        { &hf_s7comm_tis_register_accu3,
7616
14
        { "Register ACCU3", "s7comm.tis.accu3", FT_UINT32, BASE_HEX, NULL, 0x0,
7617
14
          NULL, HFILL }},
7618
14
        { &hf_s7comm_tis_register_accu4,
7619
14
        { "Register ACCU4", "s7comm.tis.accu4", FT_UINT32, BASE_HEX, NULL, 0x0,
7620
14
          NULL, HFILL }},
7621
14
        { &hf_s7comm_tis_register_ar1,
7622
14
        { "Register AR1", "s7comm.tis.ar1", FT_UINT32, BASE_HEX, NULL, 0x0,
7623
14
          NULL, HFILL }},
7624
14
        { &hf_s7comm_tis_register_ar2,
7625
14
        { "Register AR2", "s7comm.tis.ar2", FT_UINT32, BASE_HEX, NULL, 0x0,
7626
14
          NULL, HFILL }},
7627
14
        { &hf_s7comm_tis_register_stw,
7628
14
        { "Register STW", "s7comm.tis.stw", FT_UINT16, BASE_HEX, NULL, 0x0,
7629
14
          NULL, HFILL }},
7630
14
        { &hf_s7comm_tis_exithold_until,
7631
14
        { "Exit HOLD state until", "s7comm.tis.exithold_until", FT_UINT8, BASE_DEC, VALS(tis_exithold_until_names), 0x0,
7632
14
          NULL, HFILL }},
7633
14
        { &hf_s7comm_tis_exithold_res1 ,
7634
14
        { "Exit HOLD Reserved / Unknown", "s7comm.tis.exithold_res1", FT_UINT8, BASE_DEC, NULL, 0x0,
7635
14
          NULL, HFILL }},
7636
14
        { &hf_s7comm_tis_bstack_nest_depth,
7637
14
        { "BSTACK nesting depth", "s7comm.tis.bstack.neting_depth", FT_UINT8, BASE_DEC, NULL, 0x0,
7638
14
          NULL, HFILL }},
7639
14
        { &hf_s7comm_tis_bstack_reserved,
7640
14
        { "BSTACK Reserved / Unknown", "s7comm.tis.bstack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7641
14
          NULL, HFILL }},
7642
14
        { &hf_s7comm_tis_istack_reserved,
7643
14
        { "ISTACK Reserved / Unknown", "s7comm.tis.istack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7644
14
          NULL, HFILL }},
7645
14
        { &hf_s7comm_tis_lstack_reserved,
7646
14
        { "LSTACK Reserved / Unknown", "s7comm.tis.lstack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7647
14
          NULL, HFILL }},
7648
14
        { &hf_s7comm_tis_lstack_size,
7649
14
        { "Localdata stack size", "s7comm.tis.lstack.size", FT_UINT16, BASE_DEC, NULL, 0x0,
7650
14
          NULL, HFILL }},
7651
14
        { &hf_s7comm_tis_lstack_data,
7652
14
        { "Localdata stack data", "s7comm.tis.lstack.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7653
14
          NULL, HFILL }},
7654
14
        { &hf_s7comm_tis_blockstat_flagsunknown,
7655
14
        { "Blockstat flags", "s7comm.tis.blockstat.flagsunknown", FT_UINT8, BASE_HEX, NULL, 0x0,
7656
14
          NULL, HFILL }},
7657
14
        { &hf_s7comm_tis_blockstat_number_of_lines,
7658
14
        { "Number of lines", "s7comm.tis.blockstat.number_of_lines", FT_UINT8, BASE_DEC, NULL, 0x0,
7659
14
          NULL, HFILL }},
7660
14
        { &hf_s7comm_tis_blockstat_line_address,
7661
14
        { "Address", "s7comm.tis.blockstat.line_address", FT_UINT16, BASE_DEC, NULL, 0x0,
7662
14
          NULL, HFILL }},
7663
14
        { &hf_s7comm_tis_blockstat_data,
7664
14
        { "Blockstatus data", "s7comm.tis.blockstat.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7665
14
          NULL, HFILL }},
7666
14
        { &hf_s7comm_tis_blockstat_reserved,
7667
14
        { "Blockstatus Reserved / Unknown", "s7comm.tis.blockstat.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7668
14
          NULL, HFILL }},
7669
        /* Organization block local data */
7670
14
        { &hf_s7comm_ob_ev_class,
7671
14
        { "OB Event class", "s7comm.ob.ev_class", FT_UINT8, BASE_HEX, NULL, 0x0,
7672
14
          "OB Event class (Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1))", HFILL }},
7673
14
        { &hf_s7comm_ob_scan_1,
7674
14
        { "OB Scan 1", "s7comm.ob.scan_1", FT_UINT8, BASE_HEX, NULL, 0x0,
7675
14
          "OB Scan 1 (1=Cold restart scan 1 of OB 1), (3=Scan 2-n of OB 1)", HFILL }},
7676
14
        { &hf_s7comm_ob_strt_inf,
7677
14
        { "OB Start info", "s7comm.ob.strt_info", FT_UINT8, BASE_HEX, NULL, 0x0,
7678
14
          "OB Start info (OB n has started)", HFILL }},
7679
14
        { &hf_s7comm_ob_flt_id,
7680
14
        { "OB Fault identification code", "s7comm.ob.flt_id", FT_UINT8, BASE_HEX, NULL, 0x0,
7681
14
          NULL, HFILL }},
7682
14
        { &hf_s7comm_ob_priority,
7683
14
        { "OB Priority", "s7comm.ob.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
7684
14
          "OB Priority (1 is lowest)", HFILL }},
7685
14
        { &hf_s7comm_ob_number,
7686
14
        { "OB Number", "s7comm.ob.number", FT_UINT8, BASE_DEC, NULL, 0x0,
7687
14
          NULL, HFILL }},
7688
14
        { &hf_s7comm_ob_reserved_1,
7689
14
        { "OB Reserved 1", "s7comm.ob.reserved_1", FT_UINT8, BASE_HEX, NULL, 0x0,
7690
14
          "OB Reserved 1 (Reserved for System)", HFILL }},
7691
14
        { &hf_s7comm_ob_reserved_2,
7692
14
        { "OB Reserved 2", "s7comm.ob.reserved_2", FT_UINT8, BASE_HEX, NULL, 0x0,
7693
14
          "OB Reserved 2 (Reserved for System)", HFILL }},
7694
14
        { &hf_s7comm_ob_reserved_3,
7695
14
        { "OB Reserved 3", "s7comm.ob.reserved_3", FT_UINT16, BASE_HEX, NULL, 0x0,
7696
14
          "OB Reserved 3 (Reserved for System)", HFILL }},
7697
14
        { &hf_s7comm_ob_reserved_4,
7698
14
        { "OB Reserved 4", "s7comm.ob.reserved_4", FT_UINT16, BASE_HEX, NULL, 0x0,
7699
14
          "OB Reserved 4 (Reserved for System)", HFILL }},
7700
14
        { &hf_s7comm_ob_reserved_4_dw,
7701
14
        { "OB Reserved 4", "s7comm.ob.reserved_4_dw", FT_UINT32, BASE_HEX, NULL, 0x0,
7702
14
          "OB Reserved 4 (Reserved for System)", HFILL }},
7703
14
        { &hf_s7comm_ob_prev_cycle,
7704
14
        { "OB Cycle time of previous OB scan (ms)", "s7comm.ob.prev_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
7705
14
          NULL, HFILL }},
7706
14
        { &hf_s7comm_ob_min_cycle,
7707
14
        { "OB Minimum cycle time of OB (ms)", "s7comm.ob.min_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
7708
14
          NULL, HFILL }},
7709
14
        { &hf_s7comm_ob_max_cycle,
7710
14
        { "OB Maximum cycle time of OB (ms)", "s7comm.ob.max_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
7711
14
          NULL, HFILL }},
7712
14
        { &hf_s7comm_ob_period_exe,
7713
14
        { "OB Period of execution", "s7comm.ob.period_exe", FT_UINT16, BASE_HEX, NULL, 0x0,
7714
14
          "OB Period of execution (once, per minute/hour/day/week/month/year)", HFILL }},
7715
14
        { &hf_s7comm_ob_sign,
7716
14
        { "OB Identifier input (SIGN) attached to SRT_DINT", "s7comm.ob.sign", FT_UINT16, BASE_HEX, NULL, 0x0,
7717
14
          NULL, HFILL }},
7718
14
        { &hf_s7comm_ob_dtime,
7719
14
        { "OB Delay time (DTIME) input to SRT_DINT instruction", "s7comm.ob.dtime", FT_UINT32, BASE_DEC, NULL, 0x0,
7720
14
          NULL, HFILL }},
7721
14
        { &hf_s7comm_ob_phase_offset,
7722
14
        { "OB Phase offset (ms)", "s7comm.ob.phase_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
7723
14
          NULL, HFILL }},
7724
14
        { &hf_s7comm_ob_exec_freq,
7725
14
        { "OB Frequency of execution (ms)", "s7comm.ob.exec_freq", FT_UINT16, BASE_DEC, NULL, 0x0,
7726
14
          NULL, HFILL }},
7727
14
        { &hf_s7comm_ob_io_flag,
7728
14
        { "OB IO flags", "s7comm.ob.io_flag", FT_UINT8, BASE_DEC, NULL, 0x0,
7729
14
          "OB IO flags (0x54=input module, 0x55=output module)", HFILL }},
7730
14
        { &hf_s7comm_ob_mdl_addr,
7731
14
        { "OB Base address of module initiating interrupt", "s7comm.ob.mdl_addr", FT_UINT16, BASE_HEX, NULL, 0x0,
7732
14
          NULL, HFILL }},
7733
14
        { &hf_s7comm_ob_point_addr,
7734
14
        { "OB Address of interrupt point on module", "s7comm.ob.point_addr", FT_UINT32, BASE_HEX, NULL, 0x0,
7735
14
          NULL, HFILL }},
7736
14
        { &hf_s7comm_ob_inf_len,
7737
14
        { "OB Length of information", "s7comm.ob.inf_len", FT_UINT8, BASE_DEC, NULL, 0x0,
7738
14
          NULL, HFILL }},
7739
14
        { &hf_s7comm_ob_alarm_type,
7740
14
        { "OB Type of alarm", "s7comm.ob.alarm_type", FT_UINT8, BASE_DEC, NULL, 0x0,
7741
14
          NULL, HFILL }},
7742
14
        { &hf_s7comm_ob_alarm_slot,
7743
14
        { "OB Slot", "s7comm.ob.alarm_slot", FT_UINT8, BASE_DEC, NULL, 0x0,
7744
14
          NULL, HFILL }},
7745
14
        { &hf_s7comm_ob_alarm_spec,
7746
14
        { "OB Specifier", "s7comm.ob.alarm_spec", FT_UINT8, BASE_DEC, NULL, 0x0,
7747
14
          NULL, HFILL }},
7748
14
        { &hf_s7comm_ob_error_info,
7749
14
        { "OB Error information on event", "s7comm.ob.error_info", FT_UINT16, BASE_HEX, NULL, 0x0,
7750
14
          NULL, HFILL }},
7751
14
        { &hf_s7comm_ob_err_ev_class,
7752
14
        { "OB Class of event causing error", "s7comm.ob.err_ev_class", FT_UINT8, BASE_DEC, NULL, 0x0,
7753
14
          NULL, HFILL }},
7754
14
        { &hf_s7comm_ob_err_ev_num,
7755
14
        { "OB Number of event causing error", "s7comm.ob.err_ev_num", FT_UINT8, BASE_DEC, NULL, 0x0,
7756
14
          NULL, HFILL }},
7757
14
        { &hf_s7comm_ob_err_ob_priority,
7758
14
        { "OB Priority of OB causing error", "s7comm.ob.err_ob_priority", FT_UINT8, BASE_DEC, NULL, 0x0,
7759
14
          NULL, HFILL }},
7760
14
        { &hf_s7comm_ob_err_ob_num,
7761
14
        { "OB Number of OB causing error", "s7comm.ob.err_ob_num", FT_UINT8, BASE_DEC, NULL, 0x0,
7762
14
          NULL, HFILL }},
7763
14
        { &hf_s7comm_ob_rack_cpu,
7764
14
        { "OB Rack / CPU number", "s7comm.ob.rack_cpu", FT_UINT16, BASE_HEX, NULL, 0x0,
7765
14
          NULL, HFILL }},
7766
14
        { &hf_s7comm_ob_8x_fault_flags,
7767
14
        { "OB 8x Fault flags", "s7comm.ob.8x_fault_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
7768
14
          NULL, HFILL }},
7769
14
        { &hf_s7comm_ob_mdl_type_b,
7770
14
        { "OB Type of module", "s7comm.ob.mdl_type_b", FT_UINT8, BASE_HEX, NULL, 0x0,
7771
14
          NULL, HFILL }},
7772
14
        { &hf_s7comm_ob_mdl_type_w,
7773
14
        { "OB Module type with point fault", "s7comm.ob.mdl_type_w", FT_UINT16, BASE_HEX, NULL, 0x0,
7774
14
          NULL, HFILL }},
7775
14
        { &hf_s7comm_ob_rack_num,
7776
14
        { "OB Number of rack that has module with point fault", "s7comm.ob.rack_num", FT_UINT16, BASE_DEC, NULL, 0x0,
7777
14
          NULL, HFILL }},
7778
14
        { &hf_s7comm_ob_racks_flt,
7779
14
        { "OB Racks in fault", "s7comm.ob.racks_flt", FT_UINT32, BASE_HEX, NULL, 0x0,
7780
14
          NULL, HFILL }},
7781
14
        { &hf_s7comm_ob_strtup,
7782
14
        { "OB Method of startup", "s7comm.ob.strtup", FT_UINT8, BASE_HEX, NULL, 0x0,
7783
14
          NULL, HFILL }},
7784
14
        { &hf_s7comm_ob_stop,
7785
14
        { "OB Event that caused CPU to stop", "s7comm.ob.stop", FT_UINT16, BASE_HEX, NULL, 0x0,
7786
14
          NULL, HFILL }},
7787
14
        { &hf_s7comm_ob_strt_info,
7788
14
        { "OB Information on how system started", "s7comm.ob.strt_info", FT_UINT32, BASE_HEX, NULL, 0x0,
7789
14
          NULL, HFILL }},
7790
14
        { &hf_s7comm_ob_sw_flt,
7791
14
        { "OB Software programming fault", "s7comm.ob.sw_flt", FT_UINT8, BASE_HEX, NULL, 0x0,
7792
14
          NULL, HFILL }},
7793
14
        { &hf_s7comm_ob_blk_type,
7794
14
        { "OB Type of block fault occurred in", "s7comm.ob.blk_type", FT_UINT8, BASE_HEX, NULL, 0x0,
7795
14
          NULL, HFILL }},
7796
14
        { &hf_s7comm_ob_flt_reg,
7797
14
        { "OB Specific register that caused fault", "s7comm.ob.flt_reg", FT_UINT16, BASE_HEX, NULL, 0x0,
7798
14
          NULL, HFILL }},
7799
14
        { &hf_s7comm_ob_flt_blk_num,
7800
14
        { "OB Number of block that programming fault occurred in", "s7comm.ob.flt_blk_num", FT_UINT16, BASE_DEC, NULL, 0x0,
7801
14
          NULL, HFILL }},
7802
14
        { &hf_s7comm_ob_prg_addr,
7803
14
        { "OB Address in block where programming fault occurred", "s7comm.ob.prg_addr", FT_UINT16, BASE_DEC, NULL, 0x0,
7804
14
          NULL, HFILL }},
7805
14
        { &hf_s7comm_ob_mem_area,
7806
14
        { "OB Memory area where access error occurred", "s7comm.ob.mem_area", FT_UINT8, BASE_HEX, NULL, 0x0,
7807
14
          NULL, HFILL }},
7808
14
        { &hf_s7comm_ob_mem_addr,
7809
14
        { "OB Memory address where access error occurred", "s7comm.ob.mem_addr", FT_UINT16, BASE_HEX, NULL, 0x0,
7810
14
          NULL, HFILL }},
7811
14
        { &hf_s7comm_diagdata_req_block_type,
7812
14
        { "Block type", "s7comm.diagdata.req.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7813
14
          NULL, HFILL }},
7814
14
        { &hf_s7comm_diagdata_req_block_num,
7815
14
        { "Block number", "s7comm.diagdata.req.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7816
14
          NULL, HFILL }},
7817
14
        { &hf_s7comm_diagdata_req_startaddr_awl,
7818
14
        { "Start address AWL", "s7comm.diagdata.req.startaddr_awl", FT_UINT16, BASE_DEC, NULL, 0x0,
7819
14
          NULL, HFILL }},
7820
14
        { &hf_s7comm_diagdata_req_saz,
7821
14
        { "Step address counter (SAZ)", "s7comm.diagdata.req.saz", FT_UINT16, BASE_DEC, NULL, 0x0,
7822
14
          NULL, HFILL }},
7823
7824
         /* Flags for requested registers in diagnostic data telegrams */
7825
14
        { &hf_s7comm_diagdata_registerflag,
7826
14
        { "Registers", "s7comm.diagdata.register", FT_UINT8, BASE_HEX, NULL, 0x00,
7827
14
          "Requested registers", HFILL }},
7828
14
        { &hf_s7comm_diagdata_registerflag_stw,
7829
14
        { "STW", "s7comm.diagdata.register.stw", FT_BOOLEAN, 8, NULL, 0x01,
7830
14
          "STW / Status word", HFILL }},
7831
14
        { &hf_s7comm_diagdata_registerflag_accu1,
7832
14
        { "ACCU1", "s7comm.diagdata.register.accu1", FT_BOOLEAN, 8, NULL, 0x02,
7833
14
          "ACCU1 / Accumulator 1", HFILL }},
7834
14
        { &hf_s7comm_diagdata_registerflag_accu2,
7835
14
        { "ACCU2", "s7comm.diagdata.register.accu2", FT_BOOLEAN, 8, NULL, 0x04,
7836
14
          "ACCU2 / Accumulator 2", HFILL }},
7837
14
        { &hf_s7comm_diagdata_registerflag_ar1,
7838
14
        { "AR1", "s7comm.diagdata.register.ar1", FT_BOOLEAN, 8, NULL, 0x08,
7839
14
          "AR1 / Addressregister 1", HFILL }},
7840
14
        { &hf_s7comm_diagdata_registerflag_ar2,
7841
14
        { "AR2", "s7comm.diagdata.register.ar2", FT_BOOLEAN, 8, NULL, 0x10,
7842
14
          "AR2 / Addressregister 2", HFILL }},
7843
14
        { &hf_s7comm_diagdata_registerflag_db1,
7844
14
        { "DB1", "s7comm.diagdata.register.db1", FT_BOOLEAN, 8, NULL, 0x20,
7845
14
          "DB1 (global)/ Datablock register 1", HFILL }},
7846
14
        { &hf_s7comm_diagdata_registerflag_db2,
7847
14
        { "DB2", "s7comm.diagdata.register.db2", FT_BOOLEAN, 8, NULL, 0x40,
7848
14
          "DB2 (instance) / Datablock register 2", HFILL }},
7849
7850
        /* timefunction: s7 timestamp */
7851
14
        { &hf_s7comm_data_ts,
7852
14
        { "S7 Timestamp", "s7comm.data.ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
7853
14
          "S7 Timestamp, BCD coded", HFILL }},
7854
14
        { &hf_s7comm_data_ts_reserved,
7855
14
        { "S7 Timestamp - Reserved", "s7comm.data.ts_reserved", FT_UINT8, BASE_HEX, NULL, 0x00,
7856
14
          "S7 Timestamp: Reserved byte", HFILL }},
7857
14
        { &hf_s7comm_data_ts_year1,
7858
14
        { "S7 Timestamp - Year 1", "s7comm.data.ts_year1", FT_UINT8, BASE_DEC, NULL, 0x00,
7859
14
          "S7 Timestamp: BCD coded year thousands/hundreds, should be ignored (19 or 20)", HFILL }},
7860
14
        { &hf_s7comm_data_ts_year2,
7861
14
        { "S7 Timestamp - Year 2", "s7comm.data.ts_year2", FT_UINT8, BASE_DEC, NULL, 0x00,
7862
14
          "S7 Timestamp: BCD coded year, if 00...89 then it's 2000...2089, else 1990...1999", HFILL }},
7863
14
        { &hf_s7comm_data_ts_month,
7864
14
        { "S7 Timestamp - Month", "s7comm.data.ts_month", FT_UINT8, BASE_DEC, NULL, 0x00,
7865
14
          "S7 Timestamp: BCD coded month", HFILL }},
7866
14
        { &hf_s7comm_data_ts_day,
7867
14
        { "S7 Timestamp - Day", "s7comm.data.ts_day", FT_UINT8, BASE_DEC, NULL, 0x00,
7868
14
          "S7 Timestamp: BCD coded day", HFILL }},
7869
14
        { &hf_s7comm_data_ts_hour,
7870
14
        { "S7 Timestamp - Hour", "s7comm.data.ts_hour", FT_UINT8, BASE_DEC, NULL, 0x00,
7871
14
          "S7 Timestamp: BCD coded hour", HFILL }},
7872
14
        { &hf_s7comm_data_ts_minute,
7873
14
        { "S7 Timestamp - Minute", "s7comm.data.ts_minute", FT_UINT8, BASE_DEC, NULL, 0x00,
7874
14
          "S7 Timestamp: BCD coded minute", HFILL }},
7875
14
        { &hf_s7comm_data_ts_second,
7876
14
        { "S7 Timestamp - Second", "s7comm.data.ts_second", FT_UINT8, BASE_DEC, NULL, 0x00,
7877
14
          "S7 Timestamp: BCD coded second", HFILL }},
7878
14
        { &hf_s7comm_data_ts_millisecond,
7879
14
        { "S7 Timestamp - Milliseconds", "s7comm.data.ts_millisecond", FT_UINT16, BASE_DEC, NULL, 0x00,
7880
14
          "S7 Timestamp: BCD coded milliseconds (left 3 nibbles)", HFILL }},
7881
14
        { &hf_s7comm_data_ts_weekday,
7882
14
        { "S7 Timestamp - Weekday", "s7comm.data.ts_weekday", FT_UINT16, BASE_DEC, VALS(weekdaynames), 0x000f,
7883
14
          "S7 Timestamp: Weekday number (right nibble, 1=Su,2=Mo,..)", HFILL }},
7884
7885
        /* Function 0x28 (PI service) and 0x29 */
7886
14
        { &hf_s7comm_piservice_unknown1,
7887
14
        { "Unknown bytes", "s7comm.param.pistart.unknown1", FT_BYTES, BASE_NONE, NULL, 0x0,
7888
14
          NULL, HFILL }},
7889
14
        { &hf_s7comm_piservice_parameterblock_len,
7890
14
        { "Parameter block length", "s7comm.param.pistart.parameterblock_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7891
14
          "Length of Parameter block in bytes", HFILL }},
7892
14
        { &hf_s7comm_piservice_parameterblock,
7893
14
        { "Parameter block", "s7comm.param.pistart.parameterblock", FT_NONE, BASE_NONE, NULL, 0x0,
7894
14
          NULL, HFILL }},
7895
14
        { &hf_s7comm_piservice_servicename,
7896
14
        { "PI (program invocation) Service", "s7comm.param.pistart.servicename", FT_STRING, BASE_NONE, NULL, 0x0,
7897
14
          NULL , HFILL }},
7898
7899
        /* PI Service parameters for NC services */
7900
14
        { &hf_s7comm_piservice_string_len,
7901
14
        { "String length", "s7comm.param.pi.n_x.string_len", FT_UINT8, BASE_DEC, NULL, 0x0,
7902
14
          "Length of the following string. If LengthByte + Stringlen is uneven, a fillbyte is added", HFILL }},
7903
14
        { &hf_s7comm_pi_n_x_addressident,
7904
14
        { "Addressidentification", "s7comm.param.pi.n_x.addressident", FT_STRING, BASE_NONE, NULL, 0x0,
7905
14
          "Addressidentification (RangeID / Index)", HFILL }},
7906
14
        { &hf_s7comm_pi_n_x_filename,
7907
14
        { "Filename", "s7comm.param.pi.n_x.filename", FT_STRING, BASE_NONE, NULL, 0x0,
7908
14
          "Name of the file or directory", HFILL }},
7909
14
        { &hf_s7comm_pi_n_x_editwindowname,
7910
14
        { "Editor Window Name", "s7comm.param.pi.n_x.editwindowname", FT_STRING, BASE_NONE, NULL, 0x0,
7911
14
          NULL, HFILL }},
7912
14
        { &hf_s7comm_pi_n_x_password,
7913
14
        { "Password", "s7comm.param.pi.n_x.password", FT_STRING, BASE_NONE, NULL, 0x0,
7914
14
          NULL, HFILL }},
7915
14
        { &hf_s7comm_pi_n_x_seekpointer,
7916
14
        { "Seek pointer", "s7comm.param.pi.n_x.seekpointer", FT_STRING, BASE_NONE, NULL, 0x0,
7917
14
          "SeekPointer string with exact 9 digit/character(s)", HFILL }},
7918
14
        { &hf_s7comm_pi_n_x_windowsize,
7919
14
        { "Window size", "s7comm.param.pi.n_x.windowsize", FT_STRING, BASE_NONE, NULL, 0x0,
7920
14
          NULL, HFILL }},
7921
14
        { &hf_s7comm_pi_n_x_comparestring,
7922
14
        { "Compare String", "s7comm.param.pi.n_x.comparestring", FT_STRING, BASE_NONE, NULL, 0x0,
7923
14
          NULL, HFILL }},
7924
14
        { &hf_s7comm_pi_n_x_skipcount,
7925
14
        { "Skip Count", "s7comm.param.pi.n_x.skipcount", FT_STRING, BASE_NONE, NULL, 0x0,
7926
14
          NULL, HFILL }},
7927
14
        { &hf_s7comm_pi_n_x_interruptnr,
7928
14
        { "Interrupt Number", "s7comm.param.pi.n_x.interruptnr", FT_STRING, BASE_NONE, NULL, 0x0,
7929
14
          "Interrupt Number: Interrupt number corresponds to the input number which caused the interrupt" , HFILL }},
7930
14
        { &hf_s7comm_pi_n_x_priority,
7931
14
        { "Priority", "s7comm.param.pi.n_x.priority", FT_STRING, BASE_NONE, NULL, 0x0,
7932
14
          NULL , HFILL }},
7933
14
        { &hf_s7comm_pi_n_x_liftfast,
7934
14
        { "Liftfast", "s7comm.param.pi.n_x.liftfast", FT_STRING, BASE_NONE, NULL, 0x0,
7935
14
          "Liftfast: Indicates whether an interrupt routine should simultaneously cause a fast lift-off motion" , HFILL }},
7936
14
        { &hf_s7comm_pi_n_x_blsync,
7937
14
        { "Blsync", "s7comm.param.pi.n_x.blsync", FT_STRING, BASE_NONE, NULL, 0x0,
7938
14
          "Blsync: Indicates whether the interrupt has to be synchronized to the next block end" , HFILL }},
7939
14
        { &hf_s7comm_pi_n_x_magnr,
7940
14
        { "Magnr", "s7comm.param.pi.n_x.magnr", FT_STRING, BASE_NONE, NULL, 0x0,
7941
14
          "Magnr: Magazine number" , HFILL }},
7942
14
        { &hf_s7comm_pi_n_x_dnr,
7943
14
        { "DNr", "s7comm.param.pi.n_x.dnr", FT_STRING, BASE_NONE, NULL, 0x0,
7944
14
          "DNr: D number" , HFILL }},
7945
14
        { &hf_s7comm_pi_n_x_spindlenumber,
7946
14
        { "Spindle Number", "s7comm.param.pi.n_x.spindlenumber", FT_STRING, BASE_NONE, NULL, 0x0,
7947
14
          NULL, HFILL }},
7948
14
        { &hf_s7comm_pi_n_x_wznr,
7949
14
        { "WZ-Nr", "s7comm.param.pi.n_x.wznr", FT_STRING, BASE_NONE, NULL, 0x0,
7950
14
          "WZ-Nr: Tool number" , HFILL }},
7951
14
        { &hf_s7comm_pi_n_x_class,
7952
14
        { "Class", "s7comm.param.pi.n_x.class", FT_STRING, BASE_NONE, NULL, 0x0,
7953
14
          "Class: Classify machine data" , HFILL }},
7954
14
        { &hf_s7comm_pi_n_x_tnr,
7955
14
        { "TNr", "s7comm.param.pi.n_x.tnr", FT_STRING, BASE_NONE, NULL, 0x0,
7956
14
          NULL , HFILL }},
7957
14
        { &hf_s7comm_pi_n_x_toolnumber,
7958
14
        { "Tool Number", "s7comm.param.pi.n_x.toolnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7959
14
          NULL , HFILL }},
7960
14
        { &hf_s7comm_pi_n_x_cenumber,
7961
14
        { "CE-Number", "s7comm.param.pi.n_x.cenumber", FT_STRING, BASE_NONE, NULL, 0x0,
7962
14
          NULL , HFILL }},
7963
14
        { &hf_s7comm_pi_n_x_datablocknumber,
7964
14
        { "Datablock Number", "s7comm.param.pi.n_x.datablocknumber", FT_STRING, BASE_NONE, NULL, 0x0,
7965
14
          NULL , HFILL }},
7966
14
        { &hf_s7comm_pi_n_x_firstcolumnnumber,
7967
14
        { "First Column Number", "s7comm.param.pi.n_x.firstcolumnnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7968
14
          NULL , HFILL }},
7969
14
        { &hf_s7comm_pi_n_x_lastcolumnnumber,
7970
14
        { "Last Column Number", "s7comm.param.pi.n_x.lastcolumnnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7971
14
          NULL , HFILL }},
7972
14
        { &hf_s7comm_pi_n_x_firstrownumber,
7973
14
        { "First Row Number", "s7comm.param.pi.n_x.firstrownnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7974
14
          NULL , HFILL }},
7975
14
        { &hf_s7comm_pi_n_x_lastrownumber,
7976
14
        { "Last Row Number", "s7comm.param.pi.n_x.lastrownnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7977
14
          NULL , HFILL }},
7978
14
        { &hf_s7comm_pi_n_x_direction,
7979
14
        { "Direction", "s7comm.param.pi.n_x.direction", FT_STRING, BASE_NONE, NULL, 0x0,
7980
14
          NULL , HFILL }},
7981
14
        { &hf_s7comm_pi_n_x_sourcefilename,
7982
14
        { "Source-Filename", "s7comm.param.pi.n_x.sourcefilename", FT_STRING, BASE_NONE, NULL, 0x0,
7983
14
          NULL , HFILL }},
7984
14
        { &hf_s7comm_pi_n_x_destinationfilename,
7985
14
        { "Destination-Filename", "s7comm.param.pi.n_x.destinationfilename", FT_STRING, BASE_NONE, NULL, 0x0,
7986
14
          NULL , HFILL }},
7987
14
        { &hf_s7comm_pi_n_x_channelnumber,
7988
14
        { "Channel Number", "s7comm.param.pi.n_x.channelnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7989
14
          NULL , HFILL }},
7990
14
        { &hf_s7comm_pi_n_x_protection,
7991
14
        { "Protection", "s7comm.param.pi.n_x.protection", FT_STRING, BASE_NONE, NULL, 0x0,
7992
14
          NULL , HFILL }},
7993
14
        { &hf_s7comm_pi_n_x_oldfilename,
7994
14
        { "Old Filename", "s7comm.param.pi.n_x.oldfilename", FT_STRING, BASE_NONE, NULL, 0x0,
7995
14
          NULL , HFILL }},
7996
14
        { &hf_s7comm_pi_n_x_newfilename,
7997
14
        { "New Filename", "s7comm.param.pi.n_x.newfilename", FT_STRING, BASE_NONE, NULL, 0x0,
7998
14
          NULL , HFILL }},
7999
14
        { &hf_s7comm_pi_n_x_findmode,
8000
14
        { "Findmode", "s7comm.param.pi.n_x.findmode", FT_STRING, BASE_NONE, NULL, 0x0,
8001
14
          NULL , HFILL }},
8002
14
        { &hf_s7comm_pi_n_x_switch,
8003
14
        { "Switch", "s7comm.param.pi.n_x.switch", FT_STRING, BASE_NONE, NULL, 0x0,
8004
14
          NULL , HFILL }},
8005
14
        { &hf_s7comm_pi_n_x_functionnumber,
8006
14
        { "Function Number", "s7comm.param.pi.n_x.functionnumber", FT_STRING, BASE_NONE, NULL, 0x0,
8007
14
          NULL , HFILL }},
8008
14
        { &hf_s7comm_pi_n_x_semaphorevalue,
8009
14
        { "Semaphore Value", "s7comm.param.pi.n_x.semaphorevalue", FT_STRING, BASE_NONE, NULL, 0x0,
8010
14
          NULL , HFILL }},
8011
14
        { &hf_s7comm_pi_n_x_onoff,
8012
14
        { "OnOff", "s7comm.param.pi.n_x.onoff", FT_STRING, BASE_NONE, NULL, 0x0,
8013
14
          NULL , HFILL }},
8014
14
        { &hf_s7comm_pi_n_x_mode,
8015
14
        { "Mode", "s7comm.param.pi.n_x.mode", FT_STRING, BASE_NONE, NULL, 0x0,
8016
14
          NULL , HFILL }},
8017
14
        { &hf_s7comm_pi_n_x_factor,
8018
14
        { "Factor", "s7comm.param.pi.n_x.factor", FT_STRING, BASE_NONE, NULL, 0x0,
8019
14
          NULL , HFILL }},
8020
14
        { &hf_s7comm_pi_n_x_passwordlevel,
8021
14
        { "Password Level", "s7comm.param.pi.n_x.passwordlevel", FT_STRING, BASE_NONE, NULL, 0x0,
8022
14
          NULL , HFILL }},
8023
14
        { &hf_s7comm_pi_n_x_linenumber,
8024
14
        { "Line Number", "s7comm.param.pi.n_x.linenumber", FT_STRING, BASE_NONE, NULL, 0x0,
8025
14
          NULL , HFILL }},
8026
14
        { &hf_s7comm_pi_n_x_weargroup,
8027
14
        { "Wear Group", "s7comm.param.pi.n_x.weargroup", FT_STRING, BASE_NONE, NULL, 0x0,
8028
14
          NULL , HFILL }},
8029
14
        { &hf_s7comm_pi_n_x_toolstatus,
8030
14
        { "Tool Status", "s7comm.param.pi.n_x.toolstatus", FT_STRING, BASE_NONE, NULL, 0x0,
8031
14
          NULL , HFILL }},
8032
14
        { &hf_s7comm_pi_n_x_wearsearchstrat,
8033
14
        { "Search Strategy", "s7comm.param.pi.n_x.wearsearchstrat", FT_STRING, BASE_NONE, NULL, 0x0,
8034
14
          NULL , HFILL }},
8035
14
        { &hf_s7comm_pi_n_x_toolid,
8036
14
        { "Tool ID", "s7comm.param.pi.n_x.toolid", FT_STRING, BASE_NONE, NULL, 0x0,
8037
14
          NULL , HFILL }},
8038
14
        { &hf_s7comm_pi_n_x_duplonumber,
8039
14
        { "Duplo Number", "s7comm.param.pi.n_x.duplonumber", FT_STRING, BASE_NONE, NULL, 0x0,
8040
14
          NULL , HFILL }},
8041
14
        { &hf_s7comm_pi_n_x_edgenumber,
8042
14
        { "Edge Number", "s7comm.param.pi.n_x.edgenumber", FT_STRING, BASE_NONE, NULL, 0x0,
8043
14
          NULL , HFILL }},
8044
14
        { &hf_s7comm_pi_n_x_placenr,
8045
14
        { "Place Number", "s7comm.param.pi.n_x.placenr", FT_STRING, BASE_NONE, NULL, 0x0,
8046
14
          NULL , HFILL }},
8047
14
        { &hf_s7comm_pi_n_x_placerefnr,
8048
14
        { "Place Reference Number", "s7comm.param.pi.n_x.placerefnr", FT_STRING, BASE_NONE, NULL, 0x0,
8049
14
          NULL , HFILL }},
8050
14
        { &hf_s7comm_pi_n_x_magrefnr,
8051
14
        { "Magazine Reference Number", "s7comm.param.pi.n_x.magrefnr", FT_STRING, BASE_NONE, NULL, 0x0,
8052
14
          NULL , HFILL }},
8053
14
        { &hf_s7comm_pi_n_x_placenrfrom,
8054
14
        { "Place Number from", "s7comm.param.pi.n_x.placenrfrom", FT_STRING, BASE_NONE, NULL, 0x0,
8055
14
          NULL , HFILL }},
8056
14
        { &hf_s7comm_pi_n_x_magnrfrom,
8057
14
        { "Magazine Number from", "s7comm.param.pi.n_x.magnrfrom", FT_STRING, BASE_NONE, NULL, 0x0,
8058
14
          NULL , HFILL }},
8059
14
        { &hf_s7comm_pi_n_x_placenrto,
8060
14
        { "Place Number to", "s7comm.param.pi.n_x.placenrto", FT_STRING, BASE_NONE, NULL, 0x0,
8061
14
          NULL , HFILL }},
8062
14
        { &hf_s7comm_pi_n_x_magnrto,
8063
14
        { "Magazine Number to", "s7comm.param.pi.n_x.magnrto", FT_STRING, BASE_NONE, NULL, 0x0,
8064
14
          NULL , HFILL }},
8065
14
        { &hf_s7comm_pi_n_x_halfplacesleft,
8066
14
        { "Half places left", "s7comm.param.pi.n_x.halfplacesleft", FT_STRING, BASE_NONE, NULL, 0x0,
8067
14
          NULL , HFILL }},
8068
14
        { &hf_s7comm_pi_n_x_halfplacesright,
8069
14
        { "Half places right", "s7comm.param.pi.n_x.halfplacesright", FT_STRING, BASE_NONE, NULL, 0x0,
8070
14
          NULL , HFILL }},
8071
14
        { &hf_s7comm_pi_n_x_halfplacesup,
8072
14
        { "Half places up", "s7comm.param.pi.n_x.halfplacesup", FT_STRING, BASE_NONE, NULL, 0x0,
8073
14
          NULL , HFILL }},
8074
14
        { &hf_s7comm_pi_n_x_halfplacesdown,
8075
14
        { "Half places down", "s7comm.param.pi.n_x.halfplacesdown", FT_STRING, BASE_NONE, NULL, 0x0,
8076
14
          NULL , HFILL }},
8077
14
        { &hf_s7comm_pi_n_x_placetype,
8078
14
        { "Place type index", "s7comm.param.pi.n_x.placetype", FT_STRING, BASE_NONE, NULL, 0x0,
8079
14
          NULL , HFILL }},
8080
14
        { &hf_s7comm_pi_n_x_searchdirection,
8081
14
        { "Search direction", "s7comm.param.pi.n_x.searchdirection", FT_STRING, BASE_NONE, NULL, 0x0,
8082
14
          NULL , HFILL }},
8083
14
        { &hf_s7comm_pi_n_x_toolname,
8084
14
        { "Tool Name", "s7comm.param.pi.n_x.toolname", FT_STRING, BASE_NONE, NULL, 0x0,
8085
14
          NULL , HFILL }},
8086
14
        { &hf_s7comm_pi_n_x_placenrsource,
8087
14
        { "Place Number Source", "s7comm.param.pi.n_x.placenrsource", FT_STRING, BASE_NONE, NULL, 0x0,
8088
14
          NULL , HFILL }},
8089
14
        { &hf_s7comm_pi_n_x_magnrsource,
8090
14
        { "Magazine Number Source", "s7comm.param.pi.n_x.magnrsource", FT_STRING, BASE_NONE, NULL, 0x0,
8091
14
          NULL , HFILL }},
8092
14
        { &hf_s7comm_pi_n_x_placenrdestination,
8093
14
        { "Place Number Destination", "s7comm.param.pi.n_x.placenrdestination", FT_STRING, BASE_NONE, NULL, 0x0,
8094
14
          NULL , HFILL }},
8095
14
        { &hf_s7comm_pi_n_x_magnrdestination,
8096
14
        { "Magazine Number Destination", "s7comm.param.pi.n_x.magnrdestination", FT_STRING, BASE_NONE, NULL, 0x0,
8097
14
          NULL , HFILL }},
8098
14
        { &hf_s7comm_pi_n_x_incrementnumber,
8099
14
        { "Increment Number", "s7comm.param.pi.n_x.incrementnumber", FT_STRING, BASE_NONE, NULL, 0x0,
8100
14
          NULL , HFILL }},
8101
14
        { &hf_s7comm_pi_n_x_monitoringmode,
8102
14
        { "Monitoring mode", "s7comm.param.pi.n_x.monitoringmode", FT_STRING, BASE_NONE, NULL, 0x0,
8103
14
          NULL , HFILL }},
8104
14
        { &hf_s7comm_pi_n_x_kindofsearch,
8105
14
        { "Kind of search", "s7comm.param.pi.n_x.kindofsearch", FT_STRING, BASE_NONE, NULL, 0x0,
8106
14
          NULL , HFILL }},
8107
8108
14
        { &hf_s7comm_data_pi_inse_unknown,
8109
14
        { "Unknown byte", "s7comm.param.pi.inse.unknown", FT_UINT8, BASE_HEX, NULL, 0x0,
8110
14
          NULL, HFILL }},
8111
8112
14
        { &hf_s7comm_data_plccontrol_argument,
8113
14
        { "Argument", "s7comm.param.pistart.argument", FT_STRING, BASE_NONE, NULL, 0x0,
8114
14
          NULL, HFILL }},
8115
14
        { &hf_s7comm_data_plccontrol_block_cnt,
8116
14
        { "Number of blocks", "s7comm.data.plccontrol.block_cnt", FT_UINT8, BASE_DEC, NULL, 0x0,
8117
14
          NULL, HFILL }},
8118
14
        { &hf_s7comm_data_plccontrol_part2_len,
8119
14
        { "Length part 2", "s7comm.data.plccontrol.part2_len", FT_UINT8, BASE_DEC, NULL, 0x0,
8120
14
          "Length of part 2 in bytes", HFILL }},
8121
8122
        /* block control functions */
8123
14
        { &hf_s7comm_data_blockcontrol_unknown1,
8124
14
        { "Unknown byte(s) in blockcontrol", "s7comm.data.blockcontrol.unknown1", FT_BYTES, BASE_NONE, NULL, 0x0,
8125
14
          NULL, HFILL }},
8126
14
        { &hf_s7comm_data_blockcontrol_errorcode,
8127
14
        { "Errorcode", "s7comm.data.blockcontrol.errorcode", FT_UINT16, BASE_HEX, NULL, 0x0,
8128
14
          "Errorcode, 0 on success", HFILL }},
8129
14
        { &hf_s7comm_data_blockcontrol_uploadid,
8130
14
        { "UploadID", "s7comm.data.blockcontrol.uploadid", FT_UINT32, BASE_HEX, NULL, 0x0,
8131
14
          NULL, HFILL }},
8132
14
        { &hf_s7comm_data_blockcontrol_file_ident,
8133
14
        { "File identifier", "s7comm.data.blockcontrol.file_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
8134
14
          "File identifier: '_'=complete module; '$'=Module header for up-loading", HFILL }},
8135
14
        { &hf_s7comm_data_blockcontrol_block_type,
8136
14
        { "Block type", "s7comm.data.blockcontrol.block_type", FT_STRING, BASE_NONE, NULL, 0x0,
8137
14
          NULL, HFILL }},
8138
14
        { &hf_s7comm_data_blockcontrol_block_num,
8139
14
        { "Block number", "s7comm.data.blockcontrol.block_number", FT_STRING, BASE_NONE, NULL, 0x0,
8140
14
          NULL, HFILL }},
8141
14
        { &hf_s7comm_data_blockcontrol_dest_filesys,
8142
14
        { "Destination filesystem", "s7comm.data.blockcontrol.dest_filesys", FT_STRING, BASE_NONE, NULL, 0x0,
8143
14
          NULL, HFILL }},
8144
14
        { &hf_s7comm_data_blockcontrol_part2_len,
8145
14
        { "Length part 2", "s7comm.data.blockcontrol.part2_len", FT_UINT8, BASE_DEC, NULL, 0x0,
8146
14
          "Length of part 2 in bytes", HFILL }},
8147
14
        { &hf_s7comm_data_blockcontrol_part2_unknown,
8148
14
        { "Unknown char before load mem", "s7comm.data.blockcontrol.part2_unknown", FT_STRING, BASE_NONE, NULL, 0x0,
8149
14
          NULL, HFILL }},
8150
14
        { &hf_s7comm_data_blockcontrol_loadmem_len,
8151
14
        { "Length of load memory", "s7comm.data.blockcontrol.loadmem_len", FT_STRING, BASE_NONE, NULL, 0x0,
8152
14
          "Length of load memory in bytes", HFILL }},
8153
14
        { &hf_s7comm_data_blockcontrol_mc7code_len,
8154
14
        { "Length of MC7 code", "s7comm.data.blockcontrol.mc7code_len", FT_STRING, BASE_NONE, NULL, 0x0,
8155
14
          "Length of MC7 code in bytes", HFILL }},
8156
8157
14
        { &hf_s7comm_data_blockcontrol_filename_len,
8158
14
        { "Filename Length", "s7comm.param.blockcontrol.filename_len", FT_UINT8, BASE_DEC, NULL, 0x0,
8159
14
          "Length following filename in bytes", HFILL }},
8160
14
        { &hf_s7comm_data_blockcontrol_filename,
8161
14
        { "Filename", "s7comm.param.blockcontrol.filename", FT_STRING, BASE_NONE, NULL, 0x0,
8162
14
          NULL, HFILL }},
8163
14
        { &hf_s7comm_data_blockcontrol_upl_lenstring_len,
8164
14
        { "Blocklengthstring Length", "s7comm.param.blockcontrol.upl_lenstring_len", FT_UINT8, BASE_DEC, NULL, 0x0,
8165
14
          "Length following blocklength string in bytes", HFILL }},
8166
14
        { &hf_s7comm_data_blockcontrol_upl_lenstring,
8167
14
        { "Blocklength", "s7comm.param.blockcontrol.upl_lenstring", FT_STRING, BASE_NONE, NULL, 0x0,
8168
14
          "Length of the complete uploadblock in bytes, may be split into many PDUs", HFILL }},
8169
14
        { &hf_s7comm_data_blockcontrol_functionstatus,
8170
14
        { "Function Status", "s7comm.param.blockcontrol.functionstatus", FT_UINT8, BASE_HEX, NULL, 0x0,
8171
14
          "0=no error, 1=more data, 2=error", HFILL }},
8172
14
        { &hf_s7comm_data_blockcontrol_functionstatus_more,
8173
14
        { "More data following", "s7comm.param.blockcontrol.functionstatus.more", FT_BOOLEAN, 8, NULL, 0x01,
8174
14
          "More data of the block/file can be retrieved with another request", HFILL }},
8175
14
        { &hf_s7comm_data_blockcontrol_functionstatus_error,
8176
14
        { "Error", "s7comm.param.blockcontrol.functionstatus.error", FT_BOOLEAN, 8, NULL, 0x02,
8177
14
          "An error occurred", HFILL }},
8178
8179
        /* NC programming functions */
8180
14
        { &hf_s7comm_data_ncprg_unackcount,
8181
14
        { "Number of telegrams sent without acknowledge", "s7comm.data.ncprg.unackcount", FT_UINT8, BASE_DEC, NULL, 0x0,
8182
14
          NULL, HFILL }},
8183
14
        { &hf_s7comm_data_ncprg_filelength,
8184
14
        { "NC file length", "s7comm.data.ncprg.filelength", FT_STRING, BASE_NONE, NULL, 0x0,
8185
14
          "NC file length: length of file date + file path", HFILL }},
8186
14
        { &hf_s7comm_data_ncprg_filetime,
8187
14
        { "NC file timestamp", "s7comm.data.ncprg.filetime", FT_STRING, BASE_NONE, NULL, 0x0,
8188
14
          NULL, HFILL }},
8189
14
        { &hf_s7comm_data_ncprg_filepath,
8190
14
        { "NC file path", "s7comm.data.ncprg.filepath", FT_STRING, BASE_NONE, NULL, 0x0,
8191
14
          NULL, HFILL }},
8192
14
        { &hf_s7comm_data_ncprg_filedata,
8193
14
        { "NC file data", "s7comm.data.ncprg.filedata", FT_BYTES, BASE_NONE, NULL, 0x0,
8194
14
          NULL, HFILL }},
8195
8196
        /* Data record routing to Profibus */
8197
14
        { &hf_s7comm_data_drr_data,
8198
14
        { "DRR Data", "s7comm.data.drr.data", FT_BYTES, BASE_NONE, NULL, 0x0,
8199
14
          NULL, HFILL }},
8200
8201
        /* Variable status */
8202
14
        { &hf_s7comm_varstat_unknown,
8203
14
        { "Unknown byte(s) varstat", "s7comm.varstat.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
8204
14
          NULL, HFILL }},
8205
14
        { &hf_s7comm_varstat_item_count,
8206
14
        { "Item count", "s7comm.varstat.item_count", FT_UINT16, BASE_DEC, NULL, 0x0,
8207
14
          NULL, HFILL }},
8208
14
        { &hf_s7comm_varstat_req_memory_area,
8209
14
        { "Memory area", "s7comm.varstat.req.memory_area", FT_UINT8, BASE_DEC, VALS(userdata_tis_varstat_area_names), 0x0,
8210
14
          NULL, HFILL }},
8211
14
        { &hf_s7comm_varstat_req_repetition_factor,
8212
14
        { "Repetition factor", "s7comm.varstat.req.repetition_factor", FT_UINT8, BASE_DEC, NULL, 0x0,
8213
14
          NULL, HFILL }},
8214
14
        { &hf_s7comm_varstat_req_db_number,
8215
14
        { "DB number", "s7comm.varstat.req.db_number", FT_UINT16, BASE_DEC, NULL, 0x0,
8216
14
          "DB number, when area is DB", HFILL }},
8217
14
        { &hf_s7comm_varstat_req_startaddress,
8218
14
        { "Startaddress", "s7comm.varstat.req.startaddress", FT_UINT16, BASE_DEC, NULL, 0x0,
8219
14
          "Startaddress / byteoffset", HFILL }},
8220
14
        { &hf_s7comm_varstat_req_bitpos,
8221
14
        { "Bitposition", "s7comm.varstat.req.bitpos", FT_UINT16, BASE_DEC, NULL, 0x0,
8222
14
          NULL, HFILL }},
8223
8224
        /* cyclic services */
8225
14
        { &hf_s7comm_cycl_interval_timebase,
8226
14
        { "Interval timebase", "s7comm.cyclic.interval_timebase", FT_UINT8, BASE_DEC, VALS(cycl_interval_timebase_names), 0x0,
8227
14
          NULL, HFILL }},
8228
14
        { &hf_s7comm_cycl_interval_time,
8229
14
        { "Interval time factor", "s7comm.cyclic.interval_time", FT_UINT8, BASE_DEC, NULL, 0x0,
8230
14
          NULL, HFILL }},
8231
14
        { &hf_s7comm_cycl_function,
8232
14
        { "Function", "s7comm.cyclic.function", FT_UINT8, BASE_DEC, NULL, 0x0,
8233
14
          NULL, HFILL }},
8234
14
        { &hf_s7comm_cycl_jobid,
8235
14
        { "Job-ID", "s7comm.cyclic.job_id", FT_UINT8, BASE_DEC, NULL, 0x0,
8236
14
          NULL, HFILL }},
8237
8238
        /* Read record */
8239
14
        { &hf_s7comm_rdrec_mlen,
8240
14
        { "Rdrec Mlen", "s7comm.readrec.mlen", FT_UINT16, BASE_DEC, NULL, 0x0,
8241
14
          "MLEN, Max. length in bytes of the data record data to be read", HFILL }},
8242
14
        { &hf_s7comm_rdrec_index,
8243
14
        { "Rdrec Index", "s7comm.readrec.index", FT_UINT16, BASE_HEX, NULL, 0x0,
8244
14
          "INDEX, Data record number", HFILL }},
8245
14
        { &hf_s7comm_rdrec_id,
8246
14
        { "Rdrec ID", "s7comm.readrec.id", FT_UINT24, BASE_DEC, NULL, 0x0,
8247
14
          "ID, Diagnostic address", HFILL }},
8248
14
        { &hf_s7comm_rdrec_statuslen,
8249
14
        { "Rdrec Status Len", "s7comm.readrec.statuslen", FT_UINT8, BASE_DEC, NULL, 0x0,
8250
14
          "STATUS LEN, Length of status data", HFILL }},
8251
14
        { &hf_s7comm_rdrec_statusdata,
8252
14
        { "Rdrec Status", "s7comm.readrec.status", FT_BYTES, BASE_NONE, NULL, 0x0,
8253
14
          "STATUS, Status data", HFILL }},
8254
14
        { &hf_s7comm_rdrec_recordlen,
8255
14
        { "Rdrec Len", "s7comm.readrec.len", FT_UINT16, BASE_DEC, NULL, 0x0,
8256
14
          "LEN, Length of data record data read", HFILL }},
8257
14
        { &hf_s7comm_rdrec_data,
8258
14
        { "Rdrec Data", "s7comm.readrec.data", FT_BYTES, BASE_NONE, NULL, 0x0,
8259
14
          "DATA, The read data record", HFILL }},
8260
14
        { &hf_s7comm_rdrec_reserved1,
8261
14
        { "Rdrec reserved", "s7comm.readrec.reserved1", FT_BYTES, BASE_NONE, NULL, 0x0,
8262
14
          NULL, HFILL }},
8263
8264
        /* PBC, Programmable Block Functions */
8265
14
        { &hf_s7comm_pbc_unknown,
8266
14
        { "PBC unknown", "s7comm.pbc.unknown", FT_UINT8, BASE_HEX, NULL, 0x0,
8267
14
          NULL, HFILL }},
8268
14
        { &hf_s7comm_pbc_bsend_r_id,
8269
14
        { "PBC BSEND R_ID", "s7comm.pbc.req.bsend.r_id", FT_UINT32, BASE_HEX, NULL, 0x0,
8270
14
          NULL, HFILL }},
8271
14
        { &hf_s7comm_pbc_bsend_len,
8272
14
        { "PBC BSEND LEN", "s7comm.pbc.req.bsend.len", FT_UINT32, BASE_DEC, NULL, 0x0,
8273
14
          NULL, HFILL }},
8274
14
        { &hf_s7comm_pbc_usend_unknown1,
8275
14
        { "PBC USEND unknown 1", "s7comm.pbc.usend.unknown1", FT_UINT8, BASE_HEX, NULL, 0x0,
8276
14
          NULL, HFILL }},
8277
14
        { &hf_s7comm_pbc_usend_r_id,
8278
14
        { "PBC USEND R_ID", "s7comm.pbc.usend.r_id", FT_UINT32, BASE_HEX, NULL, 0x0,
8279
14
          NULL, HFILL }},
8280
14
        { &hf_s7comm_pbc_usend_unknown2,
8281
14
        { "PBC USEND unknown 2", "s7comm.pbc.usend.unknown2", FT_UINT8, BASE_HEX, NULL, 0x0,
8282
14
          NULL, HFILL }},
8283
14
        { &hf_s7comm_pbc_arsend_ret,
8284
14
        { "PBC AR_SEND Returncode", "s7comm.pbc.arsend.ret", FT_UINT8, BASE_HEX, NULL, 0x0,
8285
14
          NULL, HFILL }},
8286
14
        { &hf_s7comm_pbc_arsend_unknown,
8287
14
        { "PBC AR_SEND unknown", "s7comm.pbc.arsend.unknown", FT_UINT8, BASE_HEX, NULL, 0x0,
8288
14
          NULL, HFILL }},
8289
14
        { &hf_s7comm_pbc_arsend_ar_id,
8290
14
        { "PBC AR_SEND AR_ID", "s7comm.pbc.arsend.ar_id", FT_UINT32, BASE_HEX, NULL, 0x0,
8291
14
          NULL, HFILL }},
8292
14
        { &hf_s7comm_pbc_arsend_len,
8293
14
        { "PBC AR_SEND LEN", "s7comm.pbc.arsend.len", FT_UINT32, BASE_DEC, NULL, 0x0,
8294
14
          NULL, HFILL }},
8295
8296
        /* CPU alarms */
8297
14
        { &hf_s7comm_cpu_alarm_message_item,
8298
14
        { "Alarm message", "s7comm.alarm.message", FT_NONE, BASE_NONE, NULL, 0x0,
8299
14
          NULL, HFILL }},
8300
14
        { &hf_s7comm_cpu_alarm_message_obj_item,
8301
14
        { "Message object", "s7comm.alarm.message_object", FT_NONE, BASE_NONE, NULL, 0x0,
8302
14
          NULL, HFILL }},
8303
14
        { &hf_s7comm_cpu_alarm_message_function,
8304
14
        { "Function identifier", "s7comm.alarm.function", FT_UINT8, BASE_HEX, NULL, 0x0,
8305
14
          NULL, HFILL }},
8306
14
        { &hf_s7comm_cpu_alarm_message_nr_objects,
8307
14
        { "Number of message objects", "s7comm.alarm.nr_objects", FT_UINT8, BASE_DEC, NULL, 0x0,
8308
14
          NULL, HFILL }},
8309
14
        { &hf_s7comm_cpu_alarm_message_nr_add_values,
8310
14
        { "Number of associated values", "s7comm.alarm.nr_add_values", FT_UINT8, BASE_DEC, NULL, 0x0,
8311
14
          NULL, HFILL }},
8312
14
        { &hf_s7comm_cpu_alarm_message_eventid,
8313
14
        { "EventID", "s7comm.alarm.event_id", FT_UINT32, BASE_HEX, NULL, 0x0,
8314
14
          NULL, HFILL }},
8315
14
        { &hf_s7comm_cpu_alarm_message_timestamp_coming,
8316
14
        { "Timestamp message coming", "s7comm.alarm.timestamp_coming", FT_NONE, BASE_NONE, NULL, 0x0,
8317
14
          NULL, HFILL }},
8318
14
        { &hf_s7comm_cpu_alarm_message_timestamp_going,
8319
14
        { "Timestamp message going", "s7comm.alarm.timestamp_going", FT_NONE, BASE_NONE, NULL, 0x0,
8320
14
          NULL, HFILL }},
8321
14
        { &hf_s7comm_cpu_alarm_message_associated_value,
8322
14
        { "Associated value(s)", "s7comm.alarm.associated_value", FT_NONE, BASE_NONE, NULL, 0x0,
8323
14
          NULL, HFILL }},
8324
14
        { &hf_s7comm_cpu_alarm_message_eventstate,
8325
14
        { "EventState", "s7comm.alarm.eventstate", FT_UINT8, BASE_HEX, NULL, 0x0,
8326
14
          NULL, HFILL }},
8327
14
        { &hf_s7comm_cpu_alarm_message_signal_sig1,
8328
14
        { "SIG_1", "s7comm.alarm.signal.sig1", FT_BOOLEAN, 8, NULL, 0x01,
8329
14
          "Current state of Signal SIG_1", HFILL }},
8330
14
        { &hf_s7comm_cpu_alarm_message_signal_sig2,
8331
14
        { "SIG_2", "s7comm.alarm.signal.sig2", FT_BOOLEAN, 8, NULL, 0x02,
8332
14
          "Current state of Signal SIG_2", HFILL }},
8333
14
        { &hf_s7comm_cpu_alarm_message_signal_sig3,
8334
14
        { "SIG_3", "s7comm.alarm.signal.sig3", FT_BOOLEAN, 8, NULL, 0x04,
8335
14
          "Current state of Signal SIG_3", HFILL }},
8336
14
        { &hf_s7comm_cpu_alarm_message_signal_sig4,
8337
14
        { "SIG_4", "s7comm.alarm.signal.sig4", FT_BOOLEAN, 8, NULL, 0x08,
8338
14
          "Current state of Signal SIG_4", HFILL }},
8339
14
        { &hf_s7comm_cpu_alarm_message_signal_sig5,
8340
14
        { "SIG_5", "s7comm.alarm.signal.sig5", FT_BOOLEAN, 8, NULL, 0x10,
8341
14
          "Current state of Signal SIG_5", HFILL }},
8342
14
        { &hf_s7comm_cpu_alarm_message_signal_sig6,
8343
14
        { "SIG_6", "s7comm.alarm.signal.sig6", FT_BOOLEAN, 8, NULL, 0x20,
8344
14
          "Current state of Signal SIG_6", HFILL }},
8345
14
        { &hf_s7comm_cpu_alarm_message_signal_sig7,
8346
14
        { "SIG_7", "s7comm.alarm.signal.sig7", FT_BOOLEAN, 8, NULL, 0x40,
8347
14
          "Current state of Signal SIG_7", HFILL }},
8348
14
        { &hf_s7comm_cpu_alarm_message_signal_sig8,
8349
14
        { "SIG_8", "s7comm.alarm.signal.sig8", FT_BOOLEAN, 8, NULL, 0x80,
8350
14
          "Current state of Signal SIG_8", HFILL }},
8351
14
        { &hf_s7comm_cpu_alarm_message_state,
8352
14
        { "State", "s7comm.alarm.state", FT_UINT8, BASE_HEX, NULL, 0x0,
8353
14
          NULL, HFILL }},
8354
14
        { &hf_s7comm_cpu_alarm_message_ackstate_coming,
8355
14
        { "AckState coming", "s7comm.alarm.ack_state.coming", FT_UINT8, BASE_HEX, NULL, 0x0,
8356
14
          "Acknowledge state coming (1=Event acknowledged, 0=Event not acknowledged)", HFILL }},
8357
14
        { &hf_s7comm_cpu_alarm_message_ackstate_going,
8358
14
        { "AckState going", "s7comm.alarm.ack_state.going", FT_UINT8, BASE_HEX, NULL, 0x0,
8359
14
          "Acknowledge state going (1=Event acknowledged, 0=Event not acknowledged)", HFILL }},
8360
14
         { &hf_s7comm_cpu_alarm_message_event_coming,
8361
14
        { "Event coming", "s7comm.alarm.event.coming", FT_UINT8, BASE_HEX, NULL, 0x0,
8362
14
          NULL, HFILL }},
8363
14
        { &hf_s7comm_cpu_alarm_message_event_going,
8364
14
        { "Event going", "s7comm.alarm.event.going", FT_UINT8, BASE_HEX, NULL, 0x0,
8365
14
          NULL, HFILL }},
8366
14
        { &hf_s7comm_cpu_alarm_message_event_lastchanged,
8367
14
        { "Event last changed", "s7comm.alarm.event.lastchanged", FT_UINT8, BASE_HEX, NULL, 0x0,
8368
14
          NULL, HFILL }},
8369
14
        { &hf_s7comm_cpu_alarm_message_event_reserved,
8370
14
        { "Reserved", "s7comm.alarm.event.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
8371
14
          NULL, HFILL }},
8372
14
        { &hf_s7comm_cpu_alarm_message_scan_unknown1,
8373
14
        { "SCAN unknown 1", "s7comm.alarm.scan.unknown1", FT_UINT16, BASE_HEX, NULL, 0x0,
8374
14
          NULL, HFILL }},
8375
14
        { &hf_s7comm_cpu_alarm_message_scan_unknown2,
8376
14
        { "SCAN unknown 2", "s7comm.alarm.scan.unknown2", FT_UINT16, BASE_HEX, NULL, 0x0,
8377
14
          NULL, HFILL }},
8378
        /* Alarm message query */
8379
14
        { &hf_s7comm_cpu_alarm_query_unknown1,
8380
14
        { "Unknown/Reserved (1)", "s7comm.alarm.query.unknown1", FT_UINT8, BASE_HEX, NULL, 0x0,
8381
14
          NULL, HFILL }},
8382
14
        { &hf_s7comm_cpu_alarm_query_querytype,
8383
14
        { "Querytype", "s7comm.alarm.query.querytype", FT_UINT8, BASE_DEC, VALS(alarm_message_querytype_names), 0x0,
8384
14
          NULL, HFILL }},
8385
14
        { &hf_s7comm_cpu_alarm_query_unknown2,
8386
14
        { "Unknown/Reserved (2)", "s7comm.alarm.query.unknown2", FT_UINT8, BASE_HEX, NULL, 0x0,
8387
14
          NULL, HFILL }},
8388
14
        { &hf_s7comm_cpu_alarm_query_alarmtype,
8389
14
        { "Alarmtype", "s7comm.alarm.query.alarmtype", FT_UINT32, BASE_DEC, VALS(alarm_message_query_alarmtype_names), 0x0,
8390
14
          NULL, HFILL }},
8391
14
        { &hf_s7comm_cpu_alarm_query_completelen,
8392
14
        { "Complete data length", "s7comm.alarm.query.complete_length", FT_UINT32, BASE_DEC, NULL, 0x0,
8393
14
          "Complete data length (with ALARM_S this is 0xffff, as they might be split into many telegrams)", HFILL }},
8394
14
        { &hf_s7comm_cpu_alarm_query_datasetlen,
8395
14
        { "Length of dataset", "s7comm.alarm.query.dataset_length", FT_UINT8, BASE_DEC, NULL, 0x0,
8396
14
          NULL, HFILL }},
8397
14
        { &hf_s7comm_cpu_alarm_query_resunknown1,
8398
14
        { "Unknown", "s7comm.alarm.query.resunknown1", FT_UINT16, BASE_HEX, NULL, 0x0,
8399
14
          NULL, HFILL }},
8400
        /* CPU diagnostic messages */
8401
14
        { &hf_s7comm_cpu_diag_msg_item,
8402
14
        { "CPU diagnostic message", "s7comm.cpu.diag_msg", FT_NONE, BASE_NONE, NULL, 0x0,
8403
14
          NULL, HFILL }},
8404
14
        { &hf_s7comm_cpu_diag_msg_eventid,
8405
14
        { "Event ID", "s7comm.cpu.diag_msg.eventid", FT_UINT16, BASE_HEX, NULL, 0x0,
8406
14
          NULL, HFILL }},
8407
14
        { &hf_s7comm_cpu_diag_msg_eventid_class,
8408
14
        { "Event class", "s7comm.cpu.diag_msg.eventid.class", FT_UINT16, BASE_HEX, VALS(cpu_diag_msg_eventid_class_names), 0xf000,
8409
14
          NULL, HFILL }},
8410
14
        { &hf_s7comm_cpu_diag_msg_eventid_ident_entleave,
8411
14
        { "Event entering state", "s7comm.cpu.diag_msg.eventid.ident.entleave", FT_BOOLEAN, 16, TFS(&tfs_s7comm_cpu_diag_msg_eventid_ident_entleave), 0x0100,
8412
14
          "Event identifier: 0=Event leaving state,1=Event entering state", HFILL }},
8413
14
        { &hf_s7comm_cpu_diag_msg_eventid_ident_diagbuf,
8414
14
        { "Entry in diagnostic buffer", "s7comm.cpu.diag_msg.eventid.ident.diagbuf", FT_BOOLEAN, 16, NULL, 0x0200,
8415
14
          "Event identifier: Entry in diagnostic buffer", HFILL }},
8416
14
        { &hf_s7comm_cpu_diag_msg_eventid_ident_interr,
8417
14
        { "Internal error", "s7comm.cpu.diag_msg.eventid.ident.interr", FT_BOOLEAN, 16, NULL, 0x0400,
8418
14
          "Event identifier: Internal error", HFILL }},
8419
14
        { &hf_s7comm_cpu_diag_msg_eventid_ident_exterr,
8420
14
        { "External error", "s7comm.cpu.diag_msg.eventid.ident.exterr", FT_BOOLEAN, 16, NULL, 0x0800,
8421
14
          "Event identifier: External error", HFILL }},
8422
14
        { &hf_s7comm_cpu_diag_msg_eventid_nr,
8423
14
        { "Event number", "s7comm.cpu.diag_msg.eventid.nr", FT_UINT16, BASE_HEX, NULL, 0x00ff,
8424
14
          NULL, HFILL }},
8425
14
        { &hf_s7comm_cpu_diag_msg_prioclass,
8426
14
        { "Priority class", "s7comm.cpu.diag_msg.prioclass", FT_UINT8, BASE_DEC, NULL, 0x0,
8427
14
          NULL, HFILL }},
8428
14
        { &hf_s7comm_cpu_diag_msg_obnumber,
8429
14
        { "OB number", "s7comm.cpu.diag_msg.obnumber", FT_UINT8, BASE_DEC, NULL, 0x0,
8430
14
          NULL, HFILL }},
8431
14
        { &hf_s7comm_cpu_diag_msg_datid,
8432
14
        { "DatID", "s7comm.cpu.diag_msg.datid", FT_UINT16, BASE_HEX, NULL, 0x0,
8433
14
          NULL, HFILL }},
8434
14
        { &hf_s7comm_cpu_diag_msg_info1,
8435
14
        { "INFO1 Additional information 1", "s7comm.cpu.diag_msg.info1", FT_UINT16, BASE_HEX, NULL, 0x0,
8436
14
          NULL, HFILL }},
8437
14
        { &hf_s7comm_cpu_diag_msg_info2,
8438
14
        { "INFO2 Additional information 2", "s7comm.cpu.diag_msg.info2", FT_UINT32, BASE_HEX, NULL, 0x0,
8439
14
          NULL, HFILL }},
8440
        /* CPU message service */
8441
14
        { &hf_s7comm_cpu_msgservice_subscribe_events,
8442
14
        { "Subscribed events", "s7comm.cpu.msg.events", FT_UINT8, BASE_HEX, NULL, 0x0,
8443
14
          NULL, HFILL }},
8444
14
        { &hf_s7comm_cpu_msgservice_subscribe_events_modetrans,
8445
14
        { "Mode-transition", "s7comm.cpu.msg.events.modetrans", FT_BOOLEAN, 8, NULL, 0x01,
8446
14
          "MODE: Register for mode-transition events via func-group=0 and subfunction=state", HFILL }},
8447
14
        { &hf_s7comm_cpu_msgservice_subscribe_events_system,
8448
14
        { "System-diagnostics", "s7comm.cpu.msg.events.system", FT_BOOLEAN, 8, NULL, 0x02,
8449
14
          "SYS: Register for system diagnostic events", HFILL }},
8450
14
        { &hf_s7comm_cpu_msgservice_subscribe_events_userdefined,
8451
14
        { "Userdefined", "s7comm.cpu.msg.events.userdefined", FT_BOOLEAN, 8, NULL, 0x04,
8452
14
          "USR: Register system user-defined diagnostic messages", HFILL }},
8453
14
        { &hf_s7comm_cpu_msgservice_subscribe_events_alarms,
8454
14
        { "Alarms", "s7comm.cpu.msg.events.alarms", FT_BOOLEAN, 8, NULL, 0x80,
8455
14
          "ALM: Register alarm events (ALARM, SCAN, ALARM_S) type of event defined in additional field", HFILL }},
8456
14
        { &hf_s7comm_cpu_msgservice_req_reserved1,
8457
14
        { "Reserved/Unknown", "s7comm.cpu.msg.req_reserved1", FT_UINT8, BASE_HEX, NULL, 0x0,
8458
14
          NULL, HFILL }},
8459
14
        { &hf_s7comm_cpu_msgservice_username,
8460
14
        { "Username", "s7comm.cpu.msg.username", FT_STRING, BASE_NONE, NULL, 0x0,
8461
14
          NULL, HFILL }},
8462
14
        { &hf_s7comm_cpu_msgservice_almtype,
8463
14
        { "Alarm type", "s7comm.cpu.msg.almtype", FT_UINT8, BASE_DEC, VALS(cpu_msgservice_almtype_names), 0x0,
8464
14
          NULL, HFILL }},
8465
14
        { &hf_s7comm_cpu_msgservice_req_reserved2,
8466
14
        { "Reserved/Unknown", "s7comm.cpu.msg.req_reserved2", FT_UINT8, BASE_HEX, NULL, 0x0,
8467
14
          NULL, HFILL }},
8468
14
        { &hf_s7comm_cpu_msgservice_res_result,
8469
14
        { "Result", "s7comm.cpu.msg.res_result", FT_UINT8, BASE_HEX, NULL, 0x0,
8470
14
          NULL, HFILL }},
8471
14
        { &hf_s7comm_cpu_msgservice_res_reserved1,
8472
14
        { "Reserved/Unknown", "s7comm.cpu.msg.res_reserved1", FT_UINT8, BASE_HEX, NULL, 0x0,
8473
14
          NULL, HFILL }},
8474
14
        { &hf_s7comm_cpu_msgservice_res_reserved2,
8475
14
        { "Reserved/Unknown", "s7comm.cpu.msg.res_reserved2", FT_UINT8, BASE_HEX, NULL, 0x0,
8476
14
          NULL, HFILL }},
8477
14
        { &hf_s7comm_cpu_msgservice_res_reserved3,
8478
14
        { "Reserved/Unknown", "s7comm.cpu.msg.res_reserved3", FT_UINT8, BASE_HEX, NULL, 0x0,
8479
14
          NULL, HFILL }},
8480
14
        { &hf_s7comm_modetrans_param_unknown1,
8481
14
        { "Reserved/Unknown", "s7comm.param.modetrans.unknown1", FT_UINT32, BASE_HEX, NULL, 0x0,
8482
14
          NULL, HFILL }},
8483
14
        { &hf_s7comm_modetrans_param_mode,
8484
14
        { "Current mode", "s7comm.param.modetrans.mode", FT_UINT8, BASE_DEC, VALS(modetrans_param_mode_names), 0x0,
8485
14
          NULL, HFILL }},
8486
14
        { &hf_s7comm_modetrans_param_unknown2,
8487
14
        { "Reserved/Unknown", "s7comm.param.modetrans.unknown2", FT_UINT8, BASE_HEX, NULL, 0x0,
8488
14
          NULL, HFILL }},
8489
8490
        /* TIA Portal stuff */
8491
14
        { &hf_s7comm_tia1200_item_reserved1,
8492
14
        { "1200 sym Reserved", "s7comm.tiap.item.reserved1", FT_UINT8, BASE_HEX, NULL, 0x0,
8493
14
          NULL, HFILL }},
8494
14
        { &hf_s7comm_tia1200_item_area1,
8495
14
        { "1200 sym root area 1", "s7comm.tiap.item.area1", FT_UINT16, BASE_HEX, VALS(tia1200_var_item_area1_names), 0x0,
8496
14
          "Area from where to read: DB or Inputs, Outputs, etc.", HFILL }},
8497
14
        { &hf_s7comm_tia1200_item_area2,
8498
14
        { "1200 sym root area 2", "s7comm.tiap.item.area2", FT_UINT16, BASE_HEX, VALS(tia1200_var_item_area2_names), 0x0,
8499
14
          "Specifies the area from where to read", HFILL }},
8500
14
        { &hf_s7comm_tia1200_item_area2unknown,
8501
14
        { "1200 sym root area 2 unknown", "s7comm.tiap.item.area2unknown", FT_UINT16, BASE_HEX, NULL, 0x0,
8502
14
          "For current unknown areas", HFILL }},
8503
14
        { &hf_s7comm_tia1200_item_dbnumber,
8504
14
        { "1200 sym root DB number", "s7comm.tiap.item.dbnumber", FT_UINT16, BASE_DEC, NULL, 0x0,
8505
14
          NULL, HFILL }},
8506
14
        { &hf_s7comm_tia1200_item_crc,
8507
14
        { "1200 sym CRC", "s7comm.tiap.item.crc", FT_UINT32, BASE_HEX, NULL, 0x0,
8508
14
          "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 }},
8509
14
        { &hf_s7comm_tia1200_var_lid_flags,
8510
14
        { "LID flags", "s7comm.tiap.item.lid_flags", FT_UINT8, BASE_DEC, VALS(tia1200_var_lid_flag_names), 0xf0,
8511
14
          NULL, HFILL }},
8512
14
        { &hf_s7comm_tia1200_substructure_item,
8513
14
        { "Substructure", "s7comm.tiap.item.substructure", FT_NONE, BASE_NONE, NULL, 0x0,
8514
14
          NULL, HFILL }},
8515
14
        { &hf_s7comm_tia1200_item_value,
8516
14
        { "Value", "s7comm.tiap.item.value", FT_UINT32, BASE_DEC, NULL, 0x0fffffff,
8517
14
          NULL, HFILL }},
8518
8519
        /* Fragment fields */
8520
14
        { &hf_s7comm_fragment_overlap,
8521
14
        { "Fragment overlap", "s7comm.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
8522
14
          "Fragment overlaps with other fragments", HFILL }},
8523
14
        { &hf_s7comm_fragment_overlap_conflict,
8524
14
        { "Conflicting data in fragment overlap", "s7comm.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
8525
14
          "Overlapping fragments contained conflicting data", HFILL }},
8526
14
        { &hf_s7comm_fragment_multiple_tails,
8527
14
        { "Multiple tail fragments found", "s7comm.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
8528
14
          "Several tails were found when defragmenting the packet", HFILL }},
8529
14
        { &hf_s7comm_fragment_too_long_fragment,
8530
14
        { "Fragment too long", "s7comm.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
8531
14
          "Fragment contained data past end of packet", HFILL }},
8532
14
        { &hf_s7comm_fragment_error,
8533
14
        { "Defragmentation error", "s7comm.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
8534
14
          "Defragmentation error due to illegal fragments", HFILL }},
8535
14
        { &hf_s7comm_fragment_count,
8536
14
        { "Fragment count", "s7comm.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
8537
14
          NULL, HFILL }},
8538
14
        { &hf_s7comm_reassembled_in,
8539
14
        { "Reassembled in", "s7comm.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
8540
14
          "S7COMM fragments are reassembled in the given packet", HFILL }},
8541
14
        { &hf_s7comm_reassembled_length,
8542
14
        { "Reassembled S7COMM length", "s7comm.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
8543
14
          "The total length of the reassembled payload", HFILL }},
8544
14
        { &hf_s7comm_fragment,
8545
14
        { "S7COMM Fragment", "s7comm.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
8546
14
          NULL, HFILL }},
8547
14
        { &hf_s7comm_fragments,
8548
14
        { "S7COMM Fragments", "s7comm.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
8549
14
          NULL, HFILL }},
8550
14
    };
8551
8552
14
    static ei_register_info ei[] = {
8553
14
        { &ei_s7comm_data_blockcontrol_block_num_invalid, { "s7comm.data.blockcontrol.block_number.invalid", PI_MALFORMED, PI_ERROR,
8554
14
            "Block number must be a string containing an integer", EXPFILL }},
8555
14
        { &ei_s7comm_ud_blockinfo_block_num_ascii_invalid, { "s7comm.data.blockinfo.block_number.invalid", PI_MALFORMED, PI_ERROR,
8556
14
            "Block info must be a string containing an integer", EXPFILL }}
8557
14
    };
8558
8559
14
    static int *ett[] = {
8560
14
        &ett_s7comm,
8561
14
        &ett_s7comm_header,
8562
14
        &ett_s7comm_param,
8563
14
        &ett_s7comm_param_item,
8564
14
        &ett_s7comm_param_subitem,
8565
14
        &ett_s7comm_data,
8566
14
        &ett_s7comm_data_item,
8567
14
        &ett_s7comm_item_address,
8568
14
        &ett_s7comm_diagdata_registerflag,
8569
14
        &ett_s7comm_userdata_blockinfo_flags,
8570
14
        &ett_s7comm_cpu_alarm_message,
8571
14
        &ett_s7comm_cpu_alarm_message_object,
8572
14
        &ett_s7comm_cpu_alarm_message_signal,
8573
14
        &ett_s7comm_cpu_alarm_message_timestamp,
8574
14
        &ett_s7comm_cpu_alarm_message_associated_value,
8575
14
        &ett_s7comm_cpu_diag_msg,
8576
14
        &ett_s7comm_cpu_diag_msg_eventid,
8577
14
        &ett_s7comm_cpu_msgservice_subscribe_events,
8578
14
        &ett_s7comm_piservice_parameterblock,
8579
14
        &ett_s7comm_data_blockcontrol_status,
8580
14
        &ett_s7comm_plcfilename,
8581
14
        &ett_s7comm_prog_parameter,
8582
14
        &ett_s7comm_prog_data,
8583
14
        &ett_s7comm_fragments,
8584
14
        &ett_s7comm_fragment,
8585
14
    };
8586
8587
14
    proto_s7comm = proto_register_protocol ("S7 Communication", "S7COMM", "s7comm");
8588
8589
14
    proto_register_field_array(proto_s7comm, hf, array_length (hf));
8590
8591
14
    s7comm_register_szl_types(proto_s7comm);
8592
8593
14
    proto_register_subtree_array(ett, array_length (ett));
8594
8595
14
    expert_s7comm = expert_register_protocol(proto_s7comm);
8596
14
    expert_register_field_array(expert_s7comm, ei, array_length(ei));
8597
8598
14
    register_init_routine(s7comm_defragment_init);
8599
14
    s7comm_heur_subdissector_list_bsend = register_heur_dissector_list_with_description("s7comm-bsend", "S7COMM BSEND/BRECV", proto_s7comm);
8600
14
    s7comm_heur_subdissector_list_block_data = register_heur_dissector_list_with_description("s7comm-blk-data", "S7COMM block data", proto_s7comm);
8601
14
}
8602
8603
/* Register this protocol */
8604
void
8605
proto_reg_handoff_s7comm(void)
8606
14
{
8607
    /* register ourself as an heuristic cotp (ISO 8073) payload dissector */
8608
14
    heur_dissector_add("cotp", dissect_s7comm, "S7 Communication over COTP", "s7comm_cotp", proto_s7comm, HEURISTIC_ENABLE);
8609
14
    heur_dissector_add("cotp_is", dissect_s7comm, "S7 Communication over COTP (inactive subset)", "s7comm_cotp_is", proto_s7comm, HEURISTIC_ENABLE);
8610
14
}
8611
8612
/*
8613
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
8614
 *
8615
 * Local variables:
8616
 * c-basic-offset: 4
8617
 * tab-width: 8
8618
 * indent-tabs-mode: nil
8619
 * End:
8620
 *
8621
 * vi: set shiftwidth=4 tabstop=8 expandtab:
8622
 * :indentSize=4:tabSize=8:noTabs=true:
8623
 */