/src/wireshark/epan/dissectors/packet-ecmp.c
Line | Count | Source |
1 | | /* packet-ecmp.c |
2 | | * |
3 | | * Copyright 2014, James Lynch <lynch007@gmail.com>, Control Techniques |
4 | | * Copyright 2015, Luke Orehawa <lukeorehawa@gmail.com>, Control Techniques |
5 | | * |
6 | | * Revisions: |
7 | | * - James Lynch 2014-07-22 |
8 | | * - Initial plugin development |
9 | | * - Luke Orehawa 2015-11-26 |
10 | | * - Removed commands not yet in released specification |
11 | | * - All commands implemented are as V0.26 of ECMP Specification |
12 | | * - Modifications of code to meet Wireshark coding style and current APIs |
13 | | * |
14 | | * Wireshark - Network traffic analyzer |
15 | | * By Gerald Combs <gerald@wireshark.org> |
16 | | * Copyright 1998 Gerald Combs |
17 | | * |
18 | | * SPDX-License-Identifier: GPL-2.0-or-later |
19 | | */ |
20 | | |
21 | | #include "config.h" |
22 | | #include <epan/packet.h> |
23 | | #include <epan/expert.h> |
24 | | #include <epan/tfs.h> |
25 | | #include <epan/unit_strings.h> |
26 | | #include "packet-mbtcp.h" |
27 | | |
28 | 28 | #define ECMP_TCP_PORT 6160 |
29 | | |
30 | | void proto_reg_handoff_ecmp(void); |
31 | | void proto_register_ecmp (void); |
32 | | |
33 | | static dissector_handle_t ecmp_tcp_handle, ecmp_udp_handle; |
34 | | |
35 | | /* Wireshark ID of the ECMP protocol */ |
36 | | static int proto_ecmp; |
37 | | |
38 | | /* Used to set Modbus protocol data */ |
39 | | static int proto_modbus; |
40 | | |
41 | | /* These are the handles of our subdissectors */ |
42 | | static dissector_handle_t modbus_handle; |
43 | | |
44 | | /*smallest size of a packet, number of bytes*/ |
45 | | static const int ecmp_min_packet_size = 6; |
46 | | |
47 | | /* ECMP request codes */ |
48 | 42 | #define ECMP_COMMAND_IDENTIFY 0x00 |
49 | 6 | #define ECMP_COMMAND_INFO 0x01 |
50 | 10 | #define ECMP_COMMAND_INTERROGATE 0x02 |
51 | 21 | #define ECMP_COMMAND_READ 0x10 |
52 | 1.02k | #define ECMP_COMMAND_READWITHTYPE 0x11 |
53 | 2.82k | #define ECMP_COMMAND_WRITE 0x12 |
54 | 1.25k | #define ECMP_COMMAND_OBJECTINFO 0x13 |
55 | 1.77k | #define ECMP_COMMAND_GETNEXTOBJECTS 0x14 |
56 | 2 | #define ECMP_COMMAND_FILEOPEN 0x20 |
57 | 0 | #define ECMP_COMMAND_FILEREAD 0x21 |
58 | 0 | #define ECMP_COMMAND_FILEWRITE 0x22 |
59 | 1 | #define ECMP_COMMAND_FILECLOSE 0x23 |
60 | 19 | #define ECMP_COMMAND_FILEINFO 0x24 |
61 | 1 | #define ECMP_COMMAND_FILEDELETE 0x25 |
62 | 3 | #define ECMP_COMMAND_FILESTATE 0x26 |
63 | 1 | #define ECMP_COMMAND_FILEPOS 0x27 |
64 | 5 | #define ECMP_COMMAND_FILELIST 0x28 |
65 | 0 | #define ECMP_COMMAND_FILEEXISTS 0x2a |
66 | 108 | #define ECMP_COMMAND_CYCLICLINK 0x31 |
67 | 1 | #define ECMP_COMMAND_PROGRAMCONTROL 0x60 |
68 | 2 | #define ECMP_COMMAND_PROGRAMSTATUS 0x61 |
69 | 1 | #define ECMP_COMMAND_CYCLICFRAME 0x70 |
70 | 1 | #define ECMP_COMMAND_TUNNELFRAME 0x73 |
71 | 2 | #define ECMP_COMMAND_MODBUSPDU 0x74 |
72 | | |
73 | | /* cyclic display formats */ |
74 | | static const uint8_t cyclic_display_byte_format; |
75 | | static const uint8_t cyclic_display_word_format = 1; |
76 | | static const uint8_t cyclic_display_long_format = 2; |
77 | | |
78 | | /* Addressing scheme Structure */ |
79 | | static const value_string address_scheme [] = { |
80 | | { 0, "No Route" }, |
81 | | { 1, "Intercept" }, |
82 | | { 2, "Default Route" }, |
83 | | { 3, "Diagnostics" }, |
84 | | { 4, "Named" }, |
85 | | { 0, NULL } |
86 | | /*other commands to be added */ |
87 | | }; |
88 | | |
89 | | /* Address Structure */ |
90 | | static const value_string diagnostic [] = { |
91 | | { 0, "Status" }, |
92 | | { 1, "Alarm" }, |
93 | | { 2, "Network" }, |
94 | | { 3, "Application" }, |
95 | | { 0, NULL } |
96 | | /*other commands to be added*/ |
97 | | }; |
98 | | |
99 | | /* Command Structure*/ |
100 | | static const value_string command_vals [] = { |
101 | | { 0x00, "Identify"}, |
102 | | { 0x01, "Info"}, |
103 | | { 0x02, "Interrogate"}, |
104 | | { 0x10, "Read"}, |
105 | | { 0x11, "ReadWithType"}, |
106 | | { 0x12, "Write"}, |
107 | | { 0x13, "ObjectInfo"}, |
108 | | { 0x14, "GetNextObjects"}, |
109 | | { 0x20, "FileOpen"}, |
110 | | { 0x21, "FileRead"}, |
111 | | { 0x22, "FileWrite"}, |
112 | | { 0x23, "FileClose"}, |
113 | | { 0x24, "FileInfo"}, |
114 | | { 0x25, "FileDelete"}, |
115 | | { 0x26, "FileState"}, |
116 | | { 0x27, "FilePos"}, |
117 | | { 0x28, "FileList"}, |
118 | | { 0x2A, "FileExists"}, |
119 | | { 0x31, "CyclicSetup"}, |
120 | | { 0x60, "ProgramControl"}, |
121 | | { 0x61, "ProgramStatus"}, |
122 | | { 0x70, "CyclicFrame"}, |
123 | | { 0x73, "TunnelFrame"}, |
124 | | { 0x74, "ModbusPDU"}, |
125 | | { 0, NULL } |
126 | | /*other commands to be added*/ |
127 | | }; |
128 | | |
129 | | /* Option Code structure*/ |
130 | | static const value_string option_code [] = { |
131 | | { 0, "End of Options"}, |
132 | | { 1, "Dummy" }, |
133 | | { 2, "Process At" }, |
134 | | { 3, "Route to Custom Target"}, |
135 | | { 0, NULL } |
136 | | /* other - "Unknown" */ |
137 | | }; |
138 | | |
139 | | /* Attribute type Structure */ |
140 | | static const value_string attribute [] = { |
141 | | { 0, "Manufacturer Name" }, |
142 | | { 1, "Product Family" }, |
143 | | { 2, "Product Model" }, |
144 | | { 3, "Serial Number" }, |
145 | | { 4, "Order Number" }, |
146 | | { 5, "Date Code" }, |
147 | | { 6, "Device Name" }, |
148 | | { 7, "Version Summary" }, |
149 | | { 8, "Colour Codes" }, |
150 | | { 0, NULL } |
151 | | /* other - Unknown*/ |
152 | | }; |
153 | | |
154 | | /* Status type Structure */ |
155 | | static const value_string status [] = { |
156 | | { 0, "OK (no errors detected in request)" }, |
157 | | { 1, "OK, chunks follow" }, |
158 | | { 2, "Processing Request" }, |
159 | | { -1, "Error - Slave not ready" }, |
160 | | { -2, "Error - Request Too Long" }, |
161 | | { -3, "Error - Chunking Error" }, |
162 | | { 0, NULL } |
163 | | /* other - Unknown*/ |
164 | | }; |
165 | | |
166 | | /* Category (device) structure*/ |
167 | | static const value_string category [] = { |
168 | | { 0, "Drive" }, |
169 | | { 1, "Option Module" }, |
170 | | { 0, NULL } |
171 | | }; |
172 | | |
173 | | /* Cyclic data alignment */ |
174 | | static const value_string cyclic_align [] = { |
175 | | { 0, "8bit" }, |
176 | | { 1, "8bit" }, /* TODO: is this correct? */ |
177 | | { 2, "16bit" }, |
178 | | { 4, "32bit" }, |
179 | | { 8, "64bit" }, |
180 | | { 0, NULL } |
181 | | }; |
182 | | |
183 | | /* Cyclic data scheme */ |
184 | | static const value_string cyclic_scheme [] = { |
185 | | { 0, "Standard" }, |
186 | | { 1, "Synchronised" }, |
187 | | { 0, NULL } |
188 | | }; |
189 | | |
190 | | /* Parameter addressing scheme */ |
191 | | static const value_string parameter_address_scheme [] = { |
192 | | { 0, "Standard" }, |
193 | | { 1, "Slot Specific" }, |
194 | | { 3, "Variable" }, |
195 | | { 0, NULL } |
196 | | }; |
197 | | |
198 | | #if 0 |
199 | | static const value_string route_address_scheme [] = { |
200 | | { 1, "Intercept" }, |
201 | | { 2, "DefaultRoute" }, |
202 | | { 0, NULL } |
203 | | }; |
204 | | #endif |
205 | | |
206 | | /* Parameter access status */ |
207 | | static const value_string parameter_access_status [] = { |
208 | | { 0, "OK" }, |
209 | | { 1, "OK - Converted"}, |
210 | | { 2, "OK - Clamped"}, |
211 | | { -1, "ERROR - Address Type"}, |
212 | | { -2, "ERROR - Timeout"}, |
213 | | { -3, "ERROR - Access Denied"}, |
214 | | { -4, "ERROR - Does not exist"}, |
215 | | { -5, "ERROR - Data Type"}, |
216 | | { -6, "ERROR - Failed Read"}, |
217 | | { -7, "ERROR - Failed Write"}, |
218 | | { -8, "ERROR - Not Readable"}, |
219 | | { -9, "ERROR - Not Writeable"}, |
220 | | { -10, "ERROR - Over Range"}, |
221 | | { -11, "ERROR - Request Invalid"}, |
222 | | { -12, "ERROR - Response Too Big"}, |
223 | | { -13, "ERROR - Decimal Place"}, |
224 | | { 0, NULL} |
225 | | }; |
226 | | |
227 | | /* Parameter data types */ |
228 | | static const value_string parameter_data_types [] = { |
229 | | { 0, "Boolean"}, |
230 | | { 1, "INT8"}, |
231 | | { 2, "UINT8"}, |
232 | | { 3, "INT16"}, |
233 | | { 4, "UINT16"}, |
234 | | { 5, "INT32"}, |
235 | | { 6, "UINT32"}, |
236 | | { 7, "INT64"}, |
237 | | { 8, "UINT64"}, |
238 | | { 9, "INT128"}, |
239 | | { 10, "UINT128"}, |
240 | | { 20, "SINGLE"}, |
241 | | { 21, "DOUBLE"}, |
242 | | { 30, "String ID"}, |
243 | | { 31, "String"}, |
244 | | { 0, NULL} |
245 | | }; |
246 | | |
247 | | /* Info types */ |
248 | | static const value_string info_type [] = { |
249 | | { 0, "No Information"}, |
250 | | { 1, "Lowest Numbered Parameter in Menu"}, |
251 | | { 2, "Highest Numbered Parameter in Menu"}, |
252 | | { 3, "Parameter Format"}, |
253 | | { 4, "Minimum Value allowed for Parameter"}, |
254 | | { 5, "Maximum Value allowed for Parameter"}, |
255 | | { 6, "Object Unit Information"}, |
256 | | { 7, "Data Type of Parameter"}, |
257 | | { 0, NULL } |
258 | | }; |
259 | | |
260 | | /* Display formats */ |
261 | | static const value_string display_format [] = { |
262 | | { 0, "Standard format"}, |
263 | | { 1, "Date format (xx,yy,zz)"}, |
264 | | { 2, "Time with seconds format (xx.yy.zz)"}, |
265 | | { 3, "Character format"}, |
266 | | { 4, "Binary format"}, |
267 | | { 5, "IP address format (www.xxx.yyy.zzz)"}, |
268 | | { 6, "MAC address format (AA:BB:CC:DD:EE:FF)"}, |
269 | | { 7, "Version number (ww.xx.yy.zz)"}, |
270 | | { 8, "Slot menu parameter format (x,yy,zzz)"}, |
271 | | { 0, NULL} |
272 | | }; |
273 | | |
274 | | /* Format units */ |
275 | | static const value_string format_units [] = { |
276 | | { 0, "No units"}, |
277 | | { 1, "Custom units"}, |
278 | | { 2, "Millimetres (mm)"}, |
279 | | { 3, "Metres (m)"}, |
280 | | { 4, "User units (UU)"}, |
281 | | { 5, "Revolutions (revs)"}, |
282 | | { 6, "Degrees (')"}, |
283 | | /* { 7, ""}, */ |
284 | | { 8, "General position unit"}, |
285 | | { 9, "Millimetres per second (mm/s)"}, |
286 | | { 10, "User units per millisecond (UU/ms)"}, |
287 | | { 11, "Revolutions per minute (Rpm)"}, |
288 | | { 12, "Hertz (Hz)"}, |
289 | | { 13, "Kilohertz (kHz)"}, |
290 | | { 14, "Megahertz (MHz)"}, |
291 | | { 15, "General speed unit (Hz, rpm, mm/s)"}, |
292 | | { 16, "Closed loop speed unit (rpm, mm/s)"}, |
293 | | { 17, "Seconds per one thousand millimetres per seconds (s/m/s)"}, |
294 | | { 18, "User units per millimetre per second (UU/mm/s)"}, |
295 | | { 19, "Seconds per one thousand revolution per minute (s/1000rpm)"}, |
296 | | { 20, "Seconds per one hundred hertz (s/100Hz)"}, |
297 | | { 21, "General acceleration unit"}, |
298 | | { 22, "Closed loop acceleration unit"}, |
299 | | { 23, "Seconds squared per one thousand millimetres per second (s^2/1000ms/s)"}, |
300 | | { 24, "Seconds squared per user units per millisecond (s^2/UU/ms"}, |
301 | | { 25, "Seconds squared per one thousand revolutions per minute (s^2/1000rpm)"}, |
302 | | { 26, "Seconds squared per one hundred hertz (s^2/100Hz)"}, |
303 | | { 27, "General jerk unit"}, |
304 | | { 28, "Closed loop jerk unit"}, |
305 | | { 29, "Messages per second (Msg/s)"}, |
306 | | { 30, "Hours (Hours)"}, |
307 | | { 31, "Minutes (Mins)"}, |
308 | | { 32, "Seconds (s)"}, |
309 | | { 33, "Milliseconds (ms)"}, |
310 | | { 34, "Microseconds (us)"}, |
311 | | { 35, "Nanoseconds (ns)"}, |
312 | | { 36, "Volts (V)"}, |
313 | | { 37, "Amperes (A)"}, |
314 | | { 38, "Ohms (Ohms)"}, |
315 | | { 39, "Millihenrys (mH)"}, |
316 | | { 40, "Kilowatts (kW)"}, |
317 | | { 41, "Kilo-Volt-Amps-Reactive (kVAr)"}, |
318 | | { 42, "Megawatt hours (MWh)"}, |
319 | | { 43, "Kilowatt hours (kWh)"}, |
320 | | { 44, "Degrees Celsius ('C)"}, |
321 | | { 45, "Reciprocal of degrees Celsius (/'C)"}, |
322 | | { 46, "Kilogram-metres squared (kgm^2)"}, |
323 | | { 47, "Newton metres (Nm)"}, |
324 | | { 48, "Newton metres per ampere (Nm/A)"}, |
325 | | { 49, "open-circuit volts per 1000rpm (V/1000rpm)"}, |
326 | | { 50, "Bits (Bits)"}, |
327 | | { 51, "Bytes (Bytes)"}, |
328 | | { 52, "Kilobytes (kB)"}, |
329 | | { 53, "Megabytes (MB)"}, |
330 | | { 54, "Bits per second (Bit/s)"}, |
331 | | { 55, "Baud (Baud)"}, |
332 | | { 56, "Kilobaud (kBaud)"}, |
333 | | { 57, "Megabaud (MBaud)"}, |
334 | | { 58, "Poles (Poles)"}, |
335 | | { 59, "Percent (%)"}, |
336 | | { 60, "Volts per millisecond (V/ms)"}, |
337 | | { 0, NULL} |
338 | | }; |
339 | | |
340 | | /* File status */ |
341 | | static const value_string file_status [] = { |
342 | | { 0, "Processing"}, |
343 | | { 1, "OK"}, |
344 | | { 2, "OK - More Data"}, |
345 | | { 3, "OK - EOF"}, |
346 | | { -1, "ERROR - File Handle"}, |
347 | | { -2, "ERROR - Blocked"}, |
348 | | { -3, "ERROR - Blocking Mode"}, |
349 | | { -4, "ERROR - Not in Progress"}, |
350 | | { -5, "ERROR - Not Found"}, |
351 | | { -6, "ERROR - Read Only"}, |
352 | | { -7, "ERROR - Write Only"}, |
353 | | { -8, "ERROR - Not Created"}, |
354 | | { -9, "ERROR - No Data"}, |
355 | | { -10, "ERROR - Wrong Mode"}, |
356 | | { -11, "ERROR - Too Big"}, |
357 | | { -12, "ERROR - Protected"}, |
358 | | { -13, "ERROR - CRC"}, |
359 | | { -14, "ERROR - Length"}, |
360 | | { -15, "ERROR - Too Many Open"}, |
361 | | { -16, "ERROR - Invalid File"}, |
362 | | { -17, "ERROR - Invalid Request"}, |
363 | | { -18, "ERROR - No Append"}, |
364 | | { -19, "ERROR - Invalid State"}, |
365 | | { -20, "ERROR - Incompatible"}, |
366 | | { -21, "ERROR - Uninitialized"}, |
367 | | { 0, NULL} |
368 | | }; |
369 | | |
370 | | /* File status mode */ |
371 | | static const value_string file_status_mode [] = { |
372 | | { 0, "Information"}, |
373 | | { 1, "Read"}, |
374 | | { 2, "Create"}, |
375 | | { 3, "Append"}, |
376 | | { 4, "New Directory"}, |
377 | | { 0, NULL} |
378 | | }; |
379 | | |
380 | | /* File attributes */ |
381 | | static const value_string file_attributes [] = { |
382 | | { 0, "File Length"}, |
383 | | { 1, "File Integrity"}, |
384 | | { 2, "Calculate CRC32"}, |
385 | | { 3, "File Attributes"}, |
386 | | { 4, "Creation Date and Time"}, |
387 | | { 5, "Modification Date and Time"}, |
388 | | { 0, NULL} |
389 | | }; |
390 | | |
391 | | /* File reference position */ |
392 | | static const value_string file_ref_point [] = { |
393 | | { 0, "SoF - Start of file"}, |
394 | | { 1, "EoF - End of file"}, |
395 | | { 2, "Current - Use current file pointer"}, |
396 | | { 0, NULL} |
397 | | }; |
398 | | |
399 | | static const value_string cyclic_setup_mode [] = { |
400 | | { 0, "Create"}, |
401 | | { 1, "Edit"}, |
402 | | { 2, "Finalise"}, |
403 | | { 3, "Delete"}, |
404 | | { 4, "Exist"}, |
405 | | { 5, "List"}, |
406 | | { 6, "Info"}, |
407 | | { 10, "Set"}, |
408 | | { 11, "Get"}, |
409 | | { 12, "Get mappings"}, |
410 | | { 0, NULL} |
411 | | }; |
412 | | |
413 | | static const value_string cyclic_attributes [] = { |
414 | | { 0, "State"}, |
415 | | { 1, "Rx/Tx"}, |
416 | | { 2, "Synchronised"}, |
417 | | { 3, "MEC Offset"}, |
418 | | { 4, "Sample Period"}, |
419 | | { 5, "MEC Delay"}, |
420 | | { 6, "Data Change"}, |
421 | | { 7, "Rx Timeout Handler"}, |
422 | | { 8, "Rx Data Late Handler"}, |
423 | | { 9, "Transport Address"}, |
424 | | { 10, "Max Mappings"}, |
425 | | { 11, "Number Of Mappings"}, |
426 | | { 12, "Mapping Item"}, |
427 | | { 13, "Saveable"}, |
428 | | { 128, "Max RX Links"}, |
429 | | { 129, "Max TX Links"}, |
430 | | { 130, "Max Mappings Per Link"}, |
431 | | { 131, "Max Sync RX Links"}, |
432 | | { 132, "Max Sync TX Links"}, |
433 | | { 133, "Max Mappings Per Sync Link"}, |
434 | | { 134, "'Process At' Queue Depth"}, |
435 | | { 135, "MEC Period"}, |
436 | | { 0, NULL} |
437 | | }; |
438 | | |
439 | | static const value_string cyclic_setup_link_dir [] = { |
440 | | { 0, "Rx"}, |
441 | | { 1, "Tx"}, |
442 | | { 0, NULL} |
443 | | }; |
444 | | |
445 | | static const value_string cyclic_setup_link_exists [] = { |
446 | | { 0, "Does not exist"}, |
447 | | { 1, "Exists"}, |
448 | | { 0, NULL} |
449 | | }; |
450 | | |
451 | | static const value_string additional_scheme_vals [] = { |
452 | | { 0, "None"}, |
453 | | { 1, "Generic"}, |
454 | | { 0, NULL} |
455 | | }; |
456 | | |
457 | | /* Program Control - command codes */ |
458 | | static const value_string command_code_list [] = { |
459 | | { 0, "Stop"}, |
460 | | { 1, "Start"}, |
461 | | { 2, "Reset"}, |
462 | | { 0, NULL } |
463 | | /*other commands to be added*/ |
464 | | }; |
465 | | |
466 | | /* Program Control - sub command codes */ |
467 | | static const value_string sub_command_code_list [] = { |
468 | | { 0, "Default"}, |
469 | | { 1, "User1"}, |
470 | | { 2, "User2"}, |
471 | | { 0, NULL } |
472 | | /*other sub commands to be added*/ |
473 | | }; |
474 | | |
475 | | /* Program Control - status codes */ |
476 | | static const value_string status_list [] = { |
477 | | { 0, "OK"}, |
478 | | { -1, "Error"}, |
479 | | { 0, NULL } |
480 | | /*other status to be added*/ |
481 | | }; |
482 | | |
483 | | /* Program Status - running state codes */ |
484 | | static const value_string running_state_list [] = { |
485 | | { 0, "Stopped"}, |
486 | | { 1, "Running"}, |
487 | | { 2, "Exception"}, |
488 | | { 3, "None (no program found in device)"}, |
489 | | { 0, NULL } |
490 | | /*other status to be added*/ |
491 | | }; |
492 | | |
493 | | /* Interrogate - command support states */ |
494 | | static const value_string Interrogate_support_state [] = { |
495 | | { 0, "Not Supported"}, |
496 | | { 1, "Supported"}, |
497 | | { 0, NULL } |
498 | | /*other status to be added*/ |
499 | | }; |
500 | | |
501 | | /* Interrogate - command / option states */ |
502 | | static const value_string Interrogate_command_option_state [] = { |
503 | | { 0, "Command"}, |
504 | | { 1, "Option"}, |
505 | | { 0, NULL } |
506 | | /*other status to be added*/ |
507 | | }; |
508 | | |
509 | | static const value_string item_type_vals[] = { |
510 | | { 0, "File"}, |
511 | | { 1, "Directory"}, |
512 | | { 0, NULL } |
513 | | }; |
514 | | |
515 | | |
516 | | /* The following hf_* variables are used to hold the Wireshark IDs of |
517 | | * our header fields; they are filled out when we call |
518 | | * proto_register_field_array() in proto_register_ecmp() |
519 | | */ |
520 | | static int hf_ecmp_command; |
521 | | static int hf_ecmp_destination_address; |
522 | | static int hf_ecmp_source_address; |
523 | | static int hf_ecmp_diagnostic; |
524 | | static int hf_ecmp_type_rr; |
525 | | static int hf_ecmp_chunking; |
526 | | static int hf_ecmp_max_response_size; |
527 | | static int hf_ecmp_category; |
528 | | static int hf_ecmp_option; |
529 | | static int hf_ecmp_attribute; |
530 | | static int hf_ecmp_no_of_attributes; |
531 | | static int hf_ecmp_chunk_id; |
532 | | static int hf_ecmp_transaction_id; |
533 | | static int hf_ecmp_status; |
534 | | static int hf_ecmp_drive_type; |
535 | | static int hf_ecmp_drive_derivative; |
536 | | static int hf_ecmp_drive_factory_fit_category_id; |
537 | | static int hf_ecmp_category_id; |
538 | | static int hf_ecmp_attribute_string; |
539 | | static int hf_ecmp_file_name; |
540 | | static int hf_ecmp_info_command; |
541 | | static int hf_ecmp_directory; |
542 | | static int hf_ecmp_names_scheme; |
543 | | static int hf_ecmp_variable_name; |
544 | | static int hf_ecmp_unit_id_string; |
545 | | static int hf_ecmp_ecmp_string; |
546 | | static int hf_ecmp_process_time; |
547 | | static int hf_ecmp_cyclic_frame_time; |
548 | | static int hf_ecmp_grandmaster; |
549 | | static int hf_ecmp_data; |
550 | | static int hf_ecmp_response_data; |
551 | | |
552 | | static int hf_ecmp_cyclic_link_num; |
553 | | static int hf_ecmp_cyclic_align; |
554 | | static int hf_ecmp_cyclic_scheme; |
555 | | static int hf_ecmp_cyclic_link_number_display; |
556 | | |
557 | | /* Cyclic setup */ |
558 | | static int hf_ecmp_cyclic_setup_mode; |
559 | | static int hf_ecmp_cyclic_setup_linkno; |
560 | | static int hf_ecmp_cyclic_setup_dir; |
561 | | static int hf_ecmp_cyclic_setup_attrib_count; |
562 | | static int hf_ecmp_cyclic_setup_rsp_status; |
563 | | static int hf_ecmp_cyclic_setup_rsp_err_idx; |
564 | | static int hf_ecmp_cyclic_setup_attrib; |
565 | | static int hf_ecmp_cyclic_setup_link_exists; |
566 | | static int hf_ecmp_cyclic_link_req_resp; |
567 | | |
568 | | /*for info command */ |
569 | | static int hf_ecmp_buffer_size; |
570 | | static int hf_ecmp_max_response; |
571 | | static int hf_ecmp_max_handle; |
572 | | static int hf_ecmp_info_address; |
573 | | |
574 | | /*for parameter access commands*/ |
575 | | static int hf_ecmp_parameter_address; |
576 | | static int hf_ecmp_number_of_parameter_definitions; |
577 | | static int hf_ecmp_number_of_parameter_responses; |
578 | | static int hf_ecmp_parameter_status; |
579 | | static int hf_ecmp_data_type; |
580 | | static int hf_ecmp_info_type; |
581 | | |
582 | | /* for file access commands */ |
583 | | static int hf_ecmp_file_status; |
584 | | static int hf_ecmp_file_handle; |
585 | | static int hf_ecmp_file_attributes; |
586 | | static int hf_ecmp_file_ref_point; |
587 | | |
588 | | |
589 | | /* for tunnel frame command */ |
590 | 14 | #define TUNNEL_START_FLAG 0x01 |
591 | 14 | #define TUNNEL_END_FLAG 0x02 |
592 | 14 | #define TUNNEL_CHECK_OUTPUT_FLAG 0x04 |
593 | | |
594 | | static int hf_ecmp_tunnel_control; |
595 | | static int hf_ecmp_tunnel_start_flag; |
596 | | static int hf_ecmp_tunnel_end_flag; |
597 | | static int hf_ecmp_tunnel_check_output_flag; |
598 | | static int hf_ecmp_tunnel_size; |
599 | | |
600 | | /* Generated from convert_proto_tree_add_text.pl */ |
601 | | static int hf_ecmp_physical_address; |
602 | | static int hf_ecmp_logical_address; |
603 | | static int hf_ecmp_primary_colour; |
604 | | static int hf_ecmp_secondary_colour; |
605 | | static int hf_ecmp_number_of_subsequent_object_requests; |
606 | | static int hf_ecmp_number_of_decimal_places; |
607 | | static int hf_ecmp_no_information_available; |
608 | | static int hf_ecmp_param_format_bit_default_unipolar; |
609 | | static int hf_ecmp_param_format_write_allowed; |
610 | | static int hf_ecmp_param_format_read_not_allowed; |
611 | | static int hf_ecmp_param_format_protected_from_destinations; |
612 | | static int hf_ecmp_param_format_parameter_not_visible; |
613 | | static int hf_ecmp_param_format_not_clonable; |
614 | | static int hf_ecmp_param_format_voltage_or_current_rating_dependent; |
615 | | static int hf_ecmp_param_format_parameter_has_no_default; |
616 | | static int hf_ecmp_param_format_number_of_decimal_places; |
617 | | static int hf_ecmp_param_format_variable_maximum_and_minimum; |
618 | | static int hf_ecmp_param_format_string_parameter; |
619 | | static int hf_ecmp_param_format_destination_set_up_parameter; |
620 | | static int hf_ecmp_param_format_filtered_when_displayed; |
621 | | static int hf_ecmp_param_format_pseudo_read_only; |
622 | | static int hf_ecmp_param_format_display_format; |
623 | | static int hf_ecmp_param_format_floating_point_value; |
624 | | static int hf_ecmp_param_format_units; |
625 | | static int hf_ecmp_string_id; |
626 | | static int hf_ecmp_address_scheme_menu; |
627 | | static int hf_ecmp_address_scheme_parameter; |
628 | | static int hf_ecmp_address_scheme_slot; |
629 | | static int hf_ecmp_address_scheme_null_byte_size; |
630 | | static int hf_ecmp_display_unit_id; |
631 | | static int hf_ecmp_data_boolean; |
632 | | static int hf_ecmp_data_int8; |
633 | | static int hf_ecmp_data_uint8; |
634 | | static int hf_ecmp_data_int16; |
635 | | static int hf_ecmp_data_uint16; |
636 | | static int hf_ecmp_data_int32; |
637 | | static int hf_ecmp_data_uint32; |
638 | | static int hf_ecmp_data_int64; |
639 | | static int hf_ecmp_data_uint64; |
640 | | static int hf_ecmp_data_float; |
641 | | static int hf_ecmp_data_double; |
642 | | static int hf_ecmp_access_mode; |
643 | | static int hf_ecmp_open_in_non_blocking_mode; |
644 | | static int hf_ecmp_open_file_relative_to_specified_directory_handle; |
645 | | static int hf_ecmp_file_access_mode; |
646 | | static int hf_ecmp_additional_scheme; |
647 | | static int hf_ecmp_scheme_data_length; |
648 | | static int hf_ecmp_number_of_requested_bytes; |
649 | | static int hf_ecmp_number_of_bytes_transferred; |
650 | | static int hf_ecmp_crc; |
651 | | static int hf_ecmp_ref_offset; |
652 | | static int hf_ecmp_number_of_files_to_list; |
653 | | static int hf_ecmp_file_hash; |
654 | | static int hf_ecmp_item_type; |
655 | | static int hf_ecmp_file_integrity; |
656 | | static int hf_ecmp_display_attr_read_only; |
657 | | static int hf_ecmp_display_attr_hidden; |
658 | | static int hf_ecmp_display_attr_system; |
659 | | static int hf_ecmp_display_attr_volume_label; |
660 | | static int hf_ecmp_display_attr_subdirectory; |
661 | | static int hf_ecmp_display_attr_archive; |
662 | | static int hf_ecmp_display_creation; |
663 | | static int hf_ecmp_display_modification; |
664 | | static int hf_ecmp_interrogate_item_type; |
665 | | static int hf_ecmp_interrogate_count; |
666 | | static int hf_ecmp_modbus_pdu_size; |
667 | | /* static int hf_ecmp_destination_scheme; */ |
668 | | static int hf_ecmp_program_control_target; |
669 | | static int hf_ecmp_program_control_command; |
670 | | static int hf_ecmp_program_control_sub_command; |
671 | | static int hf_ecmp_program_control_status; |
672 | | static int hf_ecmp_program_status_target; |
673 | | static int hf_ecmp_program_status_status; |
674 | | static int hf_ecmp_program_status_additional_items; |
675 | | static int hf_ecmp_cyclic_setup_max_mappings; |
676 | | static int hf_ecmp_cyclic_setup_start_offset; |
677 | | static int hf_ecmp_cyclic_setup_tx_count; |
678 | | static int hf_ecmp_cyclic_setup_rx_count; |
679 | | static int hf_ecmp_udp_alignment; |
680 | | static int hf_ecmp_udp_scheme; |
681 | | static int hf_ecmp_cyclic_data; |
682 | | static int hf_ecmp_version_summary; |
683 | | static int hf_ecmp_min_param_menu; |
684 | | static int hf_ecmp_max_param_menu; |
685 | | static int hf_ecmp_file_length; |
686 | | static int hf_ecmp_mec_offset; |
687 | | static int hf_ecmp_sample_period; |
688 | | static int hf_ecmp_rx_timeout; |
689 | | static int hf_ecmp_rx_action; |
690 | | static int hf_ecmp_rx_event_destination; |
691 | | static int hf_ecmp_rx_event; |
692 | | static int hf_ecmp_rx_late_handler_action; |
693 | | static int hf_ecmp_rx_late_handler_event_destination; |
694 | | static int hf_ecmp_rx_late_handler_event; |
695 | | static int hf_ecmp_transport_addr_scheme; |
696 | | static int hf_ecmp_transport_addr; |
697 | | static int hf_ecmp_mapping_item_offset; |
698 | | static int hf_ecmp_mapping_item_scheme; |
699 | | static int hf_ecmp_setup_attribute; |
700 | | static int hf_ecmp_mec_period; |
701 | | static int hf_ecmp_interrogate_command; |
702 | | /************************************************************/ |
703 | | |
704 | | /* These are the ids of the subtrees that we may be creating */ |
705 | | |
706 | | static int ett_ecmp; |
707 | | static int ett_ecmp_address; |
708 | | static int ett_ecmp_response_size; |
709 | | static int ett_ecmp_command; |
710 | | static int ett_ecmp_category; |
711 | | static int ett_ecmp_option; |
712 | | static int ett_ecmp_option_data; |
713 | | static int ett_ecmp_attribute; |
714 | | static int ett_ecmp_attribute_data; |
715 | | static int ett_ecmp_cyclic_scheme; |
716 | | static int ett_ecmp_info_type; |
717 | | static int ett_ecmp_info_count; |
718 | | static int ett_ecmp_interrogate_message; |
719 | | static int ett_ecmp_param_address; |
720 | | static int ett_ecmp_access_mode; |
721 | | static int ett_ecmp_access_file; |
722 | | static int ett_ecmp_file_read; |
723 | | static int ett_ecmp_file_write; |
724 | | static int ett_ecmp_file_info; |
725 | | static int ett_ecmp_file_info_att; |
726 | | static int ett_ecmp_file_position; |
727 | | static int ett_ecmp_file_list_no; |
728 | | static int ett_ecmp_file_list; |
729 | | static int ett_ecmp_tunnel_3s_goodframe; |
730 | | static int ett_ecmp_tunnel_3s_size; |
731 | | static int ett_ecmp_tunnel_3s_service; |
732 | | static int ett_cyclic_setup_attribs; |
733 | | static int ett_cyclic_setup_attrib_item; |
734 | | static int ett_cyclic_setup_transport_addr; |
735 | | static int ett_ecmp_cyclic_data_32_bit_display; |
736 | | static int ett_ecmp_cyclic_data_16_bit_display; |
737 | | static int ett_ecmp_cyclic_data_8_bit_display; |
738 | | static int ett_ecmp_modbus_pdu_message; |
739 | | static int ett_ecmp_program_control_message; |
740 | | static int ett_ecmp_program_status_message; |
741 | | static expert_field ei_ecmp_unknown_command; |
742 | | static expert_field ei_ecmp_color; |
743 | | static expert_field ei_ecmp_option; |
744 | | static expert_field ei_ecmp_item_type; |
745 | | static expert_field ei_ecmp_options_not_implemented; |
746 | | static expert_field ei_ecmp_info_type; |
747 | | static expert_field ei_ecmp_attribute_type; |
748 | | static expert_field ei_ecmp_parameter_addressing_scheme; |
749 | | static expert_field ei_ecmp_data_type; |
750 | | |
751 | | |
752 | | /*--------------------------------------------------------------------*/ |
753 | | /* General Commands and Framing Dissectors */ |
754 | | /*--------------------------------------------------------------------*/ |
755 | | /*a function to add the initial information about the transport layer (the first bits)*/ |
756 | | static int add_transport_layer_frame(unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree, int addr_type) |
757 | 656 | { |
758 | 656 | proto_item *ecmp_address_item = NULL; |
759 | 656 | proto_tree *ecmp_address_tree = NULL; |
760 | 656 | uint8_t byte_test; |
761 | | |
762 | 656 | ecmp_address_item = proto_tree_add_item(ecmp_tree, addr_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
763 | | |
764 | 656 | byte_test = tvb_get_uint8(tvb, offset); |
765 | 656 | if ((byte_test != 0) && (byte_test != 1)) { |
766 | | /* tree to display the data in the address*/ |
767 | 548 | ecmp_address_tree = proto_item_add_subtree(ecmp_address_item, ett_ecmp_address); |
768 | | |
769 | 548 | switch (byte_test) |
770 | 548 | { |
771 | 19 | case 2: /* default route scheme*/ |
772 | 19 | offset++; |
773 | | |
774 | | /* displays the values of the addresses*/ |
775 | 19 | proto_tree_add_item(ecmp_address_tree, hf_ecmp_physical_address, tvb, offset, 1, ENC_NA); |
776 | 19 | proto_tree_add_item(ecmp_address_tree, hf_ecmp_logical_address, tvb, offset, 1, ENC_NA); |
777 | 19 | break; |
778 | | |
779 | 35 | case 3:/* diagnostic scheme*/ |
780 | 35 | proto_tree_add_item(ecmp_address_tree, hf_ecmp_diagnostic, tvb, offset, 1, ENC_BIG_ENDIAN); |
781 | 35 | offset++; |
782 | 35 | break; |
783 | 1 | case 4: /* Names scheme */ |
784 | | /* Calls a function to display the UTF-8 string data*/ |
785 | 1 | proto_tree_add_item(ecmp_address_tree, hf_ecmp_names_scheme, tvb, offset, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
786 | 1 | offset += (tvb_get_ntohs(tvb, offset) + 2); |
787 | 1 | break; |
788 | 548 | } |
789 | 548 | } |
790 | 656 | offset++; |
791 | | |
792 | 656 | return offset; |
793 | 656 | } |
794 | | |
795 | | |
796 | | /* a function to display option codes */ |
797 | | static int add_option_codes(unsigned offset, packet_info *pinfo, tvbuff_t *tvb, proto_tree* ecmp_tree) |
798 | 323 | { |
799 | 323 | proto_item* ecmp_option_number_item = NULL; |
800 | 323 | proto_item* ecmp_option_item; |
801 | 323 | proto_tree* ecmp_option_tree; |
802 | 323 | proto_tree* ecmp_option_data_tree = NULL; |
803 | 323 | uint8_t option_code_display = 0; |
804 | 323 | uint16_t count = 0; /* number of times the loop iterates*/ |
805 | 323 | int start_offset; |
806 | 323 | bool more_options = true; |
807 | | |
808 | 323 | offset++; |
809 | | |
810 | 323 | start_offset = offset; |
811 | 323 | ecmp_option_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 1, ett_ecmp_option, &ecmp_option_number_item, "Options" ); |
812 | | |
813 | | /* Loop to display all options */ |
814 | 4.67k | while(more_options) /* loops until option code is 0*/ |
815 | 4.35k | { |
816 | 4.35k | option_code_display = tvb_get_uint8(tvb, offset); |
817 | 4.35k | ecmp_option_item = proto_tree_add_item(ecmp_option_tree, hf_ecmp_option, tvb, offset, 1, ENC_BIG_ENDIAN); |
818 | 4.35k | offset++; |
819 | 4.35k | switch(option_code_display) |
820 | 4.35k | { |
821 | 320 | case 0:/* end of options*/ |
822 | 320 | proto_item_append_text(ecmp_option_number_item, ": %d", count); |
823 | 320 | proto_item_set_len(ecmp_option_number_item, offset-start_offset); |
824 | 320 | more_options = false; |
825 | 320 | break; |
826 | 163 | case 1:/* dummy - 0 bytes of data */ |
827 | 163 | break; |
828 | 44 | case 2:/* process at - 8 bytes of data */ |
829 | 44 | ecmp_option_data_tree = proto_item_add_subtree(ecmp_option_item, ett_ecmp_option_data); |
830 | | |
831 | 44 | proto_tree_add_item(ecmp_option_data_tree, hf_ecmp_process_time, tvb, offset, 8, ENC_BIG_ENDIAN); |
832 | 44 | offset += 8; |
833 | 44 | break; |
834 | 3.82k | default: /* Option that is not recognised*/ |
835 | 3.82k | proto_item_append_text(ecmp_option_number_item, "%d ", count); |
836 | 3.82k | expert_add_info(pinfo, ecmp_option_number_item, &ei_ecmp_option); |
837 | 3.82k | break; |
838 | 4.35k | } |
839 | 4.35k | count++; |
840 | 4.35k | } |
841 | 320 | return offset; |
842 | 323 | } |
843 | | |
844 | | |
845 | | /* a function to display attributes */ |
846 | | static void add_attributes(packet_info* pinfo, unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree, bool request) |
847 | 42 | { |
848 | 42 | proto_item* ecmp_attribute_number_item = NULL; |
849 | 42 | proto_item* ecmp_attribute_item = NULL, *color_item; |
850 | 42 | proto_tree* ecmp_attribute_tree = NULL; |
851 | 42 | proto_tree* ecmp_attribute_data_tree = NULL; |
852 | 42 | uint8_t no_of_attributes = 0; |
853 | 42 | uint8_t a = 0; /*values used for looping*/ |
854 | 42 | uint8_t b = 0; |
855 | 42 | uint8_t c = 0; |
856 | 42 | uint8_t check = 0; |
857 | 42 | uint16_t att_length = 0; |
858 | 42 | uint32_t color; |
859 | 42 | wmem_strbuf_t* pStr = NULL; /*char array for version string output*/ |
860 | 42 | int start_offset = offset; |
861 | | |
862 | | /*display the number of attributes*/ |
863 | 42 | ecmp_attribute_number_item = proto_tree_add_item(ecmp_tree, hf_ecmp_no_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN); |
864 | 42 | ecmp_attribute_tree = proto_item_add_subtree(ecmp_attribute_number_item, ett_ecmp_attribute); |
865 | | |
866 | 42 | no_of_attributes = tvb_get_uint8(tvb, offset); |
867 | 42 | offset++; |
868 | | |
869 | 733 | for (a = 0; a < no_of_attributes; a++, offset++) { |
870 | | /*attribute header*/ |
871 | 712 | ecmp_attribute_item = proto_tree_add_item(ecmp_attribute_tree, hf_ecmp_attribute, tvb, offset, 1, ENC_BIG_ENDIAN ); |
872 | 712 | ecmp_attribute_data_tree = proto_item_add_subtree(ecmp_attribute_item, ett_ecmp_attribute_data); |
873 | | |
874 | 712 | if (!request) { |
875 | | /*code for dissecting the colour codes attribute*/ |
876 | 24 | switch(tvb_get_uint8(tvb, offset)) |
877 | 24 | { |
878 | 0 | case 8: |
879 | 0 | offset+= 1; |
880 | | /*get length of attribute for error checking*/ |
881 | 0 | offset+= 2; |
882 | | |
883 | | /*output primary colour codes- the two bytes representing each colour are output as integers*/ |
884 | 0 | color = tvb_get_ntohl(tvb, offset); |
885 | 0 | color_item = proto_tree_add_uint_format_value(ecmp_attribute_data_tree, hf_ecmp_primary_colour, tvb, offset, 4, color, "(red) %d (green) %d (blue) %d", tvb_get_uint8(tvb, offset+1), tvb_get_uint8(tvb, offset+2), tvb_get_uint8(tvb, offset+3)); |
886 | 0 | if ((color & 0xFF000000) != 0) { |
887 | | /*error check for correct colour code format */ |
888 | 0 | expert_add_info(pinfo, color_item, &ei_ecmp_color); |
889 | 0 | } |
890 | 0 | offset+= 4; |
891 | | |
892 | | /*output secondary colour codes- the two bytes representing each colour are output as integers*/ |
893 | 0 | color = tvb_get_ntohl(tvb, offset); |
894 | 0 | color_item = proto_tree_add_uint_format_value(ecmp_attribute_data_tree, hf_ecmp_secondary_colour, tvb, offset, 4, color, "(red) %d (green) %d (blue) %d", tvb_get_uint8(tvb, offset+1), tvb_get_uint8(tvb, offset+2), tvb_get_uint8(tvb, offset+3)); |
895 | 0 | if ((color & 0xFF000000) != 0) { |
896 | | /*error check for correct colour code format */ |
897 | 0 | expert_add_info(pinfo, color_item, &ei_ecmp_color); |
898 | 0 | } |
899 | 0 | offset+= 4; |
900 | 0 | break; |
901 | | /*code for dissecting the version summary attribute*/ |
902 | 18 | case 7: |
903 | 18 | offset++; |
904 | 18 | att_length = tvb_get_ntohs(tvb, offset); |
905 | 18 | pStr = wmem_strbuf_create(pinfo->pool); |
906 | 18 | offset+= 2; |
907 | 18 | if (pStr != NULL) { |
908 | 4.74k | for (c = 0; c < att_length; c++, offset++) { |
909 | 4.72k | check = tvb_get_uint8(tvb,offset); |
910 | 4.72k | if (check == 'V' || check == '#' || check == '@') { |
911 | 42 | wmem_strbuf_append_c(pStr, ' '); |
912 | 4.68k | } else if (check == ';') { |
913 | | /*display version summary parameter, e.g 'FW', 'BL', 'HW'*/ |
914 | 19 | proto_tree_add_string(ecmp_attribute_data_tree, hf_ecmp_version_summary, tvb, offset-b, b, wmem_strbuf_get_str(pStr)); |
915 | 19 | wmem_strbuf_truncate(pStr, 0); |
916 | 4.66k | } else if (check <= 0x7f) { |
917 | 3.18k | wmem_strbuf_append_c(pStr, check); |
918 | 3.18k | } |
919 | 1.47k | else { |
920 | 1.47k | wmem_strbuf_append_hex(pStr, check); |
921 | 1.47k | } |
922 | 4.72k | } |
923 | | /*display last version summary parameter, e.g 'FW', 'BL', 'HW' as no delimiter to check for, just prints out rest of version string*/ |
924 | 18 | proto_tree_add_string(ecmp_attribute_data_tree, hf_ecmp_version_summary, tvb, offset-b, b, wmem_strbuf_get_str(pStr)); |
925 | 18 | offset-= 1; |
926 | 18 | } |
927 | 18 | break; |
928 | 6 | default: |
929 | | /* displays the data inside the attribute*/ |
930 | 6 | proto_tree_add_item(ecmp_attribute_data_tree, hf_ecmp_attribute_string, tvb, offset+1, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
931 | 6 | offset += (tvb_get_ntohs(tvb, offset+1) + 2); |
932 | 6 | break; |
933 | 24 | } |
934 | 24 | } |
935 | 712 | } |
936 | | |
937 | 21 | proto_item_set_len(ecmp_attribute_number_item, offset-start_offset); |
938 | 21 | } |
939 | | |
940 | | |
941 | | /* a function to display the category codes */ |
942 | | static int add_category_codes(unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree) |
943 | 21 | { |
944 | 21 | proto_item *ecmp_category_item = NULL; |
945 | 21 | proto_tree *ecmp_category_tree = NULL; |
946 | 21 | uint8_t category_size = 0; |
947 | 21 | int start_offset = offset; |
948 | 21 | uint8_t category_value = tvb_get_uint8(tvb, offset); |
949 | | |
950 | | /* displays the category and creates a tree to display further data*/ |
951 | 21 | ecmp_category_item = proto_tree_add_item(ecmp_tree, hf_ecmp_category, tvb, offset, 1, ENC_BIG_ENDIAN); |
952 | 21 | ecmp_category_tree = proto_item_add_subtree(ecmp_category_item, ett_ecmp_category); |
953 | 21 | offset++; |
954 | | |
955 | 21 | category_size = tvb_get_uint8(tvb, offset); |
956 | 21 | offset++; |
957 | | |
958 | 21 | if(category_size==2 && category_value == 1) { |
959 | | /*display "option module" and its ID*/ |
960 | 0 | proto_tree_add_item(ecmp_category_tree, hf_ecmp_category_id, tvb, offset, 2, ENC_BIG_ENDIAN); |
961 | 0 | offset+=category_size; |
962 | 21 | } else if(category_size == 4 && category_value == 0) { |
963 | | /*display "drive" and its data (product type, drive derivative and ID*/ |
964 | 0 | proto_tree_add_item(ecmp_category_tree, hf_ecmp_drive_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
965 | 0 | proto_tree_add_item(ecmp_category_tree, hf_ecmp_drive_derivative, tvb, offset+1, 1, ENC_BIG_ENDIAN); |
966 | 0 | proto_tree_add_item(ecmp_category_tree, hf_ecmp_drive_factory_fit_category_id, tvb, offset+2, 2, ENC_BIG_ENDIAN); |
967 | 0 | offset+=category_size; |
968 | |
|
969 | 21 | } else { |
970 | | /* Display unknown and its hex data */ |
971 | 21 | proto_tree_add_item(ecmp_category_tree, hf_ecmp_data, tvb, offset, category_size, ENC_NA); |
972 | 21 | offset += category_size; |
973 | 21 | } |
974 | | |
975 | 21 | proto_item_set_len(ecmp_category_item, offset-start_offset); |
976 | 21 | return offset; |
977 | 21 | } |
978 | | |
979 | | |
980 | | /* a function to display response size data */ |
981 | | static int get_response_size(unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree) |
982 | 212 | { |
983 | 212 | proto_item* ecmp_max_response_item = NULL; |
984 | 212 | proto_tree* ecmp_response_size_tree = NULL; |
985 | 212 | uint8_t chunks = 0; |
986 | 212 | uint16_t max_response_size = 0; |
987 | | |
988 | | /*get values for number of chunks and max response size*/ |
989 | 212 | chunks = tvb_get_uint8(tvb, offset)>>4&0x0F; |
990 | 212 | max_response_size = tvb_get_ntohs(tvb, offset) & 0x0FFF; |
991 | | |
992 | | /*display response subtree */ |
993 | 212 | ecmp_response_size_tree = proto_tree_add_subtree_format(ecmp_tree, tvb, offset, 2, ett_ecmp_response_size, &ecmp_max_response_item, "Response Size: %X, %X (%d)", chunks, max_response_size, max_response_size); |
994 | | |
995 | | /*display chunks and max response size in response subtree*/ |
996 | 212 | proto_tree_add_item(ecmp_response_size_tree, hf_ecmp_chunking, tvb, offset, 2, ENC_BIG_ENDIAN); |
997 | 212 | proto_tree_add_item(ecmp_response_size_tree, hf_ecmp_max_response_size, tvb, offset, 2, ENC_BIG_ENDIAN); |
998 | 212 | offset+= 2; |
999 | | |
1000 | 212 | return offset; |
1001 | 212 | } |
1002 | | |
1003 | | |
1004 | | /* a function to display the command code and type (request/response) */ |
1005 | | static int add_command_codes(packet_info* pinfo, unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree, uint8_t transaction_id_value, uint8_t* command_value) |
1006 | 325 | { |
1007 | 325 | proto_tree *ecmp_command_tree; |
1008 | 325 | const char* command_str; |
1009 | 325 | uint8_t command = tvb_get_uint8(tvb, offset); |
1010 | 325 | *command_value = command & 0x7F; |
1011 | 325 | command_str = val_to_str(pinfo->pool, *command_value, command_vals, "Unknown Type (0x%02x)"); |
1012 | | |
1013 | | /*display command subtree*/ |
1014 | 325 | ecmp_command_tree = proto_tree_add_subtree_format(ecmp_tree, tvb, offset, 1, ett_ecmp_command, NULL, "Request Response Code: %s", command_str); |
1015 | | |
1016 | | /* Displays the command */ |
1017 | 325 | proto_tree_add_item(ecmp_command_tree, hf_ecmp_command, tvb, offset, 1, ENC_BIG_ENDIAN); |
1018 | | /* Displays the type (request/response) */ |
1019 | 325 | proto_tree_add_item(ecmp_command_tree, hf_ecmp_type_rr, tvb, offset, 1, ENC_BIG_ENDIAN); |
1020 | | |
1021 | | /* Information displayed in the Info column*/ |
1022 | 325 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s, %s. Transaction ID: %d", |
1023 | 325 | command_str, tfs_get_string(((command & 0x80) >> 7), &tfs_response_request), |
1024 | 325 | transaction_id_value); |
1025 | | |
1026 | 325 | return offset; |
1027 | 325 | } |
1028 | | |
1029 | | |
1030 | | /* a function to add a cyclic frame query */ |
1031 | | static int add_cyclic_frame_query(unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree ) |
1032 | 0 | { |
1033 | | /* display the cyclic link number */ |
1034 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_link_num, tvb, offset++, 1, ENC_BIG_ENDIAN); |
1035 | 0 | return offset; |
1036 | 0 | } |
1037 | | |
1038 | | |
1039 | | /* a function to add a cyclic frame */ |
1040 | | static int add_cyclic_frame(unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree ) |
1041 | 1 | { |
1042 | 1 | uint32_t scheme; |
1043 | 1 | proto_item *ecmp_scheme_item = NULL; |
1044 | 1 | proto_tree *ecmp_scheme_tree = NULL; |
1045 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_link_num, tvb, offset++, 1, ENC_BIG_ENDIAN); |
1046 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_align, tvb, offset++, 1, ENC_BIG_ENDIAN); |
1047 | 1 | ecmp_scheme_item = proto_tree_add_item_ret_uint(ecmp_tree, hf_ecmp_cyclic_scheme, tvb, offset++, 1, ENC_BIG_ENDIAN, &scheme); |
1048 | | |
1049 | 1 | if (scheme == 1) { |
1050 | | /* Create a new sub tree spawning off the scheme byte for the synchronisation scheme data to be placed. */ |
1051 | 0 | ecmp_scheme_tree = proto_item_add_subtree(ecmp_scheme_item, ett_ecmp_cyclic_scheme); |
1052 | | |
1053 | | /* grandmaster */ |
1054 | 0 | proto_tree_add_item( ecmp_scheme_tree, hf_ecmp_grandmaster, tvb, offset, 8, ENC_BIG_ENDIAN); |
1055 | 0 | offset += 8; |
1056 | |
|
1057 | 0 | proto_tree_add_item(ecmp_scheme_tree, hf_ecmp_cyclic_frame_time, tvb, offset, 8, ENC_BIG_ENDIAN); |
1058 | 0 | offset += 8; |
1059 | 0 | } |
1060 | | |
1061 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_data, tvb, offset, -1, ENC_NA); |
1062 | | |
1063 | 1 | return tvb_reported_length(tvb); |
1064 | 1 | } |
1065 | | |
1066 | | |
1067 | | /* a function to display cyclic tvb data in byte (8-bit), word (16-bit), and long (32-bit) unsigned formats */ |
1068 | | static int display_raw_cyclic_data(uint8_t display, unsigned offset, uint16_t buffer_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree* ecmp_current_tree ) |
1069 | 21 | { |
1070 | | /****************************************************************************************/ |
1071 | | /* */ |
1072 | | /* display_raw_cyclic_data - display the cyclic data in various formats. */ |
1073 | | /* */ |
1074 | | /* Parameters: display = selects desired display format. */ |
1075 | | /* 0 = BYTE_FORMAT (8-bits 1F 20 37 BC ... */ |
1076 | | /* 1 = WORD_FORMAT (16-bits 1F20 37BC 77F1 ... */ |
1077 | | /* 2 = LONG_FORMAT (32-bits 1F2037BC 0013F5CD ... */ |
1078 | | /* */ |
1079 | | /* offset = offset within tvb buffer where this data starts. */ |
1080 | | /* */ |
1081 | | /* buffer_size = number of bytes to be converted and displayed. */ |
1082 | | /* */ |
1083 | | /* tvb = buffer structure within Wireshark holding this frame. */ |
1084 | | /* */ |
1085 | | /* pinfo = packet info for this frame. */ |
1086 | | /* */ |
1087 | | /* ecmp_current_tree = the tree where the data is to be displayed. */ |
1088 | | /* */ |
1089 | | /* */ |
1090 | | /* Notes: we only display so many elements on a line (before continuing on next line) */ |
1091 | | /* */ |
1092 | | /* 16 elements per line for byte (8-bit) and word (16-bit) */ |
1093 | | /* 8 elements per line for long (32-bit) */ |
1094 | | /* */ |
1095 | | /* Programmer: Jim Lynch */ |
1096 | | /****************************************************************************************/ |
1097 | | |
1098 | | /* bail out if the buffer size is zero */ |
1099 | 21 | if (buffer_size == 0) { |
1100 | 0 | proto_tree_add_bytes_format_value(ecmp_current_tree, hf_ecmp_cyclic_data, tvb, offset-1, 0, NULL, "No data"); |
1101 | 21 | } else { |
1102 | | /* define some variables */ |
1103 | 21 | wmem_strbuf_t* pdata = wmem_strbuf_create(pinfo->pool); /* formatted data string */ |
1104 | 21 | uint16_t num_elements_total = 0; /* contains total number of elements (byte/word/long) to be processed */ |
1105 | 21 | const uint16_t num_byte_elements_per_line = 16; /* number of byte (8-bit) elements per line e.g. "1B " (3 chars per element) */ |
1106 | 21 | const uint16_t num_word_elements_per_line = 16; /* number of word (16-bit) elements per line e.g. "A81B " (5 chars per element) */ |
1107 | 21 | const uint16_t num_long_elements_per_line = 8; /* number of long (32-bit) elements per line e.g. "01F4A81B " (9 chars per element) */ |
1108 | 21 | uint16_t num_elements_per_line = 8; /* counts the current number of elements per line */ |
1109 | 21 | uint16_t num_elements = 0; /* counts the number of elements in the format string */ |
1110 | 21 | uint16_t a = 0; /* value used for looping */ |
1111 | 21 | int start_offset, line_offset; |
1112 | | |
1113 | | /* calculate number of elements */ |
1114 | | /* */ |
1115 | 21 | if (display == cyclic_display_byte_format) { |
1116 | 4 | num_elements_per_line = num_byte_elements_per_line; /* num_elements_per_line = 16 */ |
1117 | 4 | num_elements_total = buffer_size; |
1118 | 17 | } else if (display == cyclic_display_word_format) { |
1119 | 4 | num_elements_per_line = num_word_elements_per_line; /* num_elements_per_line = 16 */ |
1120 | 4 | num_elements_total = buffer_size >> 1; |
1121 | 13 | } else if (display == cyclic_display_long_format) { |
1122 | 13 | num_elements_per_line = num_long_elements_per_line; /* num_elements_per_line = 8 */ |
1123 | 13 | num_elements_total = buffer_size >> 2; |
1124 | 13 | } else { |
1125 | 0 | num_elements_per_line = num_byte_elements_per_line; /* num_elements_per_line = 16 */ |
1126 | 0 | num_elements_total = buffer_size; |
1127 | 0 | } |
1128 | | |
1129 | | /* OK, let's get started */ |
1130 | 21 | num_elements = 0; |
1131 | | |
1132 | 21 | line_offset = start_offset = offset; |
1133 | | /* work through the display elements, 1 byte\word\long at a time */ |
1134 | 709 | for (a = 0; a < num_elements_total; a++ ) { |
1135 | 688 | if (wmem_strbuf_get_len(pdata) > 0) { |
1136 | 597 | wmem_strbuf_append_c(pdata, ' '); |
1137 | 597 | } |
1138 | | |
1139 | | /* use Wireshark accessor function to get the next byte, word, or long data */ |
1140 | 688 | if (display == cyclic_display_byte_format) { |
1141 | 33 | uint8_t value8 = tvb_get_uint8(tvb, offset); |
1142 | 33 | wmem_strbuf_append_printf(pdata, "%02x", value8); |
1143 | 33 | offset++; |
1144 | 655 | } else if (display == cyclic_display_word_format) { |
1145 | 16 | uint16_t value16 = tvb_get_ntohs(tvb, offset); |
1146 | 16 | wmem_strbuf_append_printf(pdata, "%04x", value16); |
1147 | 16 | offset += 2; |
1148 | 639 | } else if (display == cyclic_display_long_format) { |
1149 | 639 | uint32_t value32 = tvb_get_ntohl(tvb, offset); |
1150 | 639 | wmem_strbuf_append_printf(pdata, "%08x", value32); |
1151 | 639 | offset += 4; |
1152 | 639 | } |
1153 | | |
1154 | | /* increment the num_elements we've done on the current line */ |
1155 | 688 | num_elements++; |
1156 | | |
1157 | | /* check if we hit the max number of byte elements per line */ |
1158 | 688 | if (num_elements >= num_elements_per_line) { |
1159 | | /* display the completed line in the sub-tree */ |
1160 | 79 | proto_tree_add_bytes_format(ecmp_current_tree, hf_ecmp_cyclic_data, tvb, offset, offset-line_offset, NULL, "%s", wmem_strbuf_get_str(pdata)); |
1161 | | |
1162 | | /* start the line over */ |
1163 | 79 | wmem_strbuf_truncate(pdata, 0); |
1164 | 79 | num_elements = 0; |
1165 | 79 | line_offset = offset; |
1166 | 79 | } |
1167 | 688 | } |
1168 | | |
1169 | | /* if we exited the loop, see if there's a partial line to display */ |
1170 | 21 | if (num_elements > 0) { |
1171 | | /* display the partial line in the sub-tree */ |
1172 | 12 | proto_tree_add_bytes_format(ecmp_current_tree, hf_ecmp_cyclic_data, tvb, start_offset, offset-start_offset, NULL, "%s", wmem_strbuf_get_str(pdata)); |
1173 | 12 | } |
1174 | 21 | } |
1175 | 21 | return offset; |
1176 | 21 | } |
1177 | | |
1178 | | |
1179 | | /* a function returning the information requested by the 'info' command */ |
1180 | | static void add_info_response(unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1181 | 4 | { |
1182 | 4 | proto_item* ecmp_info_address_item = NULL; |
1183 | 4 | proto_tree* ecmp_info_tree = NULL; |
1184 | 4 | proto_tree* ecmp_info_address_tree = NULL, *address_tree; |
1185 | 4 | uint16_t length = 0; |
1186 | 4 | uint8_t no_of_address = 0; |
1187 | 4 | uint8_t i = 0; /*for counting */ |
1188 | | |
1189 | 4 | length = tvb_reported_length(tvb); |
1190 | | |
1191 | | /*display info response tree */ |
1192 | 4 | ecmp_info_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 6, ett_ecmp_info_type, NULL, "Response Information"); |
1193 | | |
1194 | | /*display buffer size */ |
1195 | 4 | proto_tree_add_item(ecmp_info_tree, hf_ecmp_buffer_size, tvb, offset, 2, ENC_BIG_ENDIAN); |
1196 | 4 | offset+= 2; |
1197 | | |
1198 | | /*display max response time */ |
1199 | 4 | proto_tree_add_item(ecmp_info_tree, hf_ecmp_max_response, tvb, offset, 2, ENC_BIG_ENDIAN); |
1200 | 4 | offset+= 2; |
1201 | | |
1202 | | /*display max handle period */ |
1203 | 4 | proto_tree_add_item(ecmp_info_tree, hf_ecmp_max_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1204 | 4 | offset+= 2; |
1205 | | |
1206 | 4 | if (length > offset) { |
1207 | | /*display count of default server addresses */ |
1208 | 4 | ecmp_info_address_item = proto_tree_add_item(ecmp_tree, hf_ecmp_info_address, tvb, offset, 1, ENC_BIG_ENDIAN); |
1209 | 4 | ecmp_info_address_tree = proto_item_add_subtree(ecmp_info_address_item, ett_ecmp_info_count); |
1210 | 4 | no_of_address = tvb_get_uint8(tvb, offset); |
1211 | | |
1212 | 4 | if (no_of_address > 0) { |
1213 | | /*do code to display address data */ |
1214 | 86 | for (i = 0; i < no_of_address; i++) { |
1215 | 83 | address_tree = proto_tree_add_subtree_format(ecmp_info_address_tree, tvb, offset, 1, ett_ecmp_address, NULL, "Address %d", i+1); |
1216 | 83 | proto_tree_add_item(address_tree, hf_ecmp_physical_address, tvb, offset, 1, ENC_NA); |
1217 | 83 | proto_tree_add_item(address_tree, hf_ecmp_logical_address, tvb, offset, 1, ENC_NA); |
1218 | 83 | offset+= 1; |
1219 | 83 | } |
1220 | 3 | } |
1221 | 4 | } |
1222 | 4 | } |
1223 | | |
1224 | | |
1225 | | /*--------------------------------------------------------------------*/ |
1226 | | /* Parameter Access Commands */ |
1227 | | /*--------------------------------------------------------------------*/ |
1228 | | |
1229 | | /* a function to display data given data_type */ |
1230 | | static int get_data_type(packet_info* pinfo, unsigned offset, uint8_t data_type, tvbuff_t *tvb, proto_tree* ecmp_current_tree) |
1231 | 2.05k | { |
1232 | | /*switch to decide correct data_type dissection*/ |
1233 | 2.05k | switch(data_type) |
1234 | 2.05k | { |
1235 | 454 | case 0: /*display boolean*/ |
1236 | 454 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_boolean, tvb, offset, 1, ENC_NA); |
1237 | 454 | break; |
1238 | 76 | case 1: /*display INT8*/ |
1239 | 76 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_int8, tvb, offset, 1, ENC_NA); |
1240 | 76 | break; |
1241 | 49 | case 2: /*display UINT8*/ |
1242 | 49 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_uint8, tvb, offset, 1, ENC_NA); |
1243 | 49 | break; |
1244 | 82 | case 3: /*display INT16*/ |
1245 | 82 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_int16, tvb, offset, 2, ENC_BIG_ENDIAN); |
1246 | 82 | offset+= 1; |
1247 | 82 | break; |
1248 | 109 | case 4: /*display UINT16*/ |
1249 | 109 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_uint16, tvb, offset, 2, ENC_BIG_ENDIAN); |
1250 | 109 | offset+= 1; |
1251 | 109 | break; |
1252 | 29 | case 5: /*display INT32*/ |
1253 | 29 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_int32, tvb, offset, 4, ENC_BIG_ENDIAN); |
1254 | 29 | offset+= 3; |
1255 | 29 | break; |
1256 | 23 | case 6: /*display UINT32*/ |
1257 | 23 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_uint32, tvb, offset, 4, ENC_BIG_ENDIAN); |
1258 | 23 | offset+= 3; |
1259 | 23 | break; |
1260 | 16 | case 7: /*display INT64*/ |
1261 | 16 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_int64, tvb, offset, 8, ENC_BIG_ENDIAN); |
1262 | 16 | offset+= 7; |
1263 | 16 | break; |
1264 | 30 | case 8: /*display UINT64*/ |
1265 | 30 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_uint64, tvb, offset, 8, ENC_BIG_ENDIAN); |
1266 | 30 | offset+= 7; |
1267 | 30 | break; |
1268 | 21 | case 9: /*display INT128*/ |
1269 | 21 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data, tvb, offset, 16, ENC_NA); |
1270 | 21 | offset += 15; |
1271 | 21 | break; |
1272 | 18 | case 10: /*display UINT128*/ |
1273 | 18 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data, tvb, offset, 16, ENC_NA); |
1274 | 18 | offset += 15; |
1275 | 18 | break; |
1276 | 10 | case 20:/*display single float*/ |
1277 | 10 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_float, tvb, offset, 4, ENC_BIG_ENDIAN); |
1278 | 10 | offset+= 3; |
1279 | 10 | break; |
1280 | 9 | case 21: /*display double float*/ |
1281 | 9 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data_double, tvb, offset, 8, ENC_BIG_ENDIAN); |
1282 | 9 | offset+= 7; |
1283 | 9 | break; |
1284 | 14 | case 30: /*display string ID*/ |
1285 | 14 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_string_id, tvb, offset, 2, ENC_ASCII); |
1286 | 14 | offset++; |
1287 | 14 | break; |
1288 | 10 | case 32: /*display (ECMP) string*/ |
1289 | 10 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_ecmp_string, tvb, offset+1, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
1290 | 10 | offset += (tvb_get_ntohs(tvb, offset+1) + 2); |
1291 | 10 | break; |
1292 | 1.10k | default: /*display untyped size*/ |
1293 | 1.10k | if (data_type < 128) { |
1294 | 869 | proto_tree_add_expert_remaining(ecmp_current_tree, pinfo, &ei_ecmp_data_type, tvb, 0); |
1295 | 869 | } else { |
1296 | 233 | proto_tree_add_item(ecmp_current_tree, hf_ecmp_data, tvb, offset, (data_type- 127), ENC_NA); |
1297 | 233 | offset += (data_type- 128); |
1298 | 233 | } |
1299 | 1.10k | break; |
1300 | 2.05k | } |
1301 | 1.99k | return offset; |
1302 | 2.05k | } |
1303 | | |
1304 | | |
1305 | | /* a function to add the parameter address schemes for 'read' command */ |
1306 | | static int get_address_scheme(packet_info* pinfo, unsigned offset, uint8_t scheme, tvbuff_t *tvb, proto_tree* ecmp_parameter_tree) |
1307 | 1.61k | { |
1308 | | /*if address scheme is standard*/ |
1309 | 1.61k | switch (scheme) |
1310 | 1.61k | { |
1311 | 378 | case 0: |
1312 | | /*display Menu no. */ |
1313 | 378 | proto_tree_add_item(ecmp_parameter_tree, hf_ecmp_address_scheme_menu, tvb, offset, 2, ENC_BIG_ENDIAN); |
1314 | 378 | offset+= 2; |
1315 | | |
1316 | | /*display parameter no. */ |
1317 | 378 | proto_tree_add_item(ecmp_parameter_tree, hf_ecmp_address_scheme_parameter, tvb, offset, 2, ENC_BIG_ENDIAN); |
1318 | 378 | offset++; |
1319 | 378 | break; |
1320 | | |
1321 | 79 | case 1:/*if address scheme is slot specific*/ |
1322 | | /*display slot number*/ |
1323 | 79 | proto_tree_add_item(ecmp_parameter_tree, hf_ecmp_address_scheme_slot, tvb, offset, 1, ENC_NA); |
1324 | 79 | offset++; |
1325 | | |
1326 | | /*display Menu no. */ |
1327 | 79 | proto_tree_add_item(ecmp_parameter_tree, hf_ecmp_address_scheme_menu, tvb, offset, 2, ENC_BIG_ENDIAN); |
1328 | 79 | offset+= 2; |
1329 | | |
1330 | | /*display parameter no. */ |
1331 | 79 | proto_tree_add_item(ecmp_parameter_tree, hf_ecmp_address_scheme_parameter, tvb, offset, 2, ENC_BIG_ENDIAN); |
1332 | 79 | offset++; |
1333 | 79 | break; |
1334 | | |
1335 | 7 | case 3: /*if address scheme is variable*/ |
1336 | | /*display variable name */ |
1337 | 7 | offset--; |
1338 | 7 | proto_tree_add_item(ecmp_parameter_tree, hf_ecmp_variable_name, tvb, offset+1, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
1339 | 7 | offset += (tvb_get_ntohs(tvb, offset+1) + 2); |
1340 | 7 | break; |
1341 | | |
1342 | 69 | case 4: /*if address scheme is NULL*/ |
1343 | | /*null size*/ |
1344 | 69 | proto_tree_add_item(ecmp_parameter_tree, hf_ecmp_address_scheme_null_byte_size, tvb, offset, 1, ENC_NA); |
1345 | 69 | offset++; |
1346 | 69 | break; |
1347 | | |
1348 | 1.08k | default: |
1349 | 1.08k | proto_tree_add_expert(ecmp_parameter_tree, pinfo, &ei_ecmp_parameter_addressing_scheme, tvb, offset, 1); |
1350 | 1.61k | } |
1351 | 1.59k | return offset; |
1352 | 1.61k | } |
1353 | | |
1354 | | |
1355 | | /* a function to display an array of the read address schemes */ |
1356 | | static void get_parameter_definitions(packet_info* pinfo, unsigned offset, uint8_t command_value, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1357 | 53 | { |
1358 | 53 | proto_item* ecmp_parameter_item = NULL; |
1359 | 53 | proto_tree* ecmp_parameter_number_tree = NULL; |
1360 | 53 | proto_tree* ecmp_parameter_tree = NULL; |
1361 | 53 | uint8_t count = 0; |
1362 | 53 | uint8_t a = 0; |
1363 | 53 | uint8_t data_type = 0; |
1364 | 53 | int8_t dec = 0; |
1365 | 53 | uint8_t scheme = 0; |
1366 | 53 | uint16_t n = 0; |
1367 | | |
1368 | 53 | scheme = tvb_get_uint8(tvb, offset); |
1369 | | |
1370 | 53 | ecmp_parameter_item = proto_tree_add_item(ecmp_tree, hf_ecmp_parameter_address, tvb, offset, 1, ENC_BIG_ENDIAN); |
1371 | 53 | ecmp_parameter_tree = proto_item_add_subtree(ecmp_parameter_item, ett_ecmp_param_address); |
1372 | | |
1373 | 53 | offset++; |
1374 | | /* if "GetNextObjects" command */ |
1375 | 53 | if(command_value == ECMP_COMMAND_GETNEXTOBJECTS) |
1376 | 0 | { |
1377 | 0 | offset = get_address_scheme(pinfo, offset, scheme, tvb, ecmp_parameter_tree); |
1378 | 0 | offset++; |
1379 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_number_of_subsequent_object_requests, tvb, offset, 1, ENC_NA); |
1380 | 0 | }else |
1381 | 53 | { |
1382 | | /*display tree with count of definitions */ |
1383 | 53 | ecmp_parameter_item = proto_tree_add_item(ecmp_tree, hf_ecmp_number_of_parameter_definitions, tvb, offset, 1, ENC_BIG_ENDIAN); |
1384 | 53 | ecmp_parameter_number_tree = proto_item_add_subtree(ecmp_parameter_item, ett_ecmp_param_address); |
1385 | | |
1386 | 53 | count = tvb_get_uint8(tvb,offset); |
1387 | | |
1388 | 53 | offset++; |
1389 | | |
1390 | 53 | switch(scheme)/*sets n so that the tree highlights bytes in scheme specific data*/ |
1391 | 53 | { |
1392 | 15 | case 0: |
1393 | 15 | n = 4; |
1394 | 15 | break; |
1395 | 5 | case 1: |
1396 | 5 | n = 5; |
1397 | 5 | break; |
1398 | 0 | case 3: |
1399 | 0 | n = 1 + ((tvb_get_uint8(tvb, offset+1)<<8)|(tvb_get_uint8(tvb, offset+2))); |
1400 | 0 | break; |
1401 | 33 | default: |
1402 | 33 | n = 0; |
1403 | 33 | break; |
1404 | 53 | } |
1405 | | |
1406 | 53 | if (command_value == ECMP_COMMAND_OBJECTINFO) { |
1407 | 3 | n += 1; |
1408 | 3 | } |
1409 | | |
1410 | 1.22k | for (a = 0; a < count; a++) { |
1411 | 1.17k | ecmp_parameter_tree = proto_tree_add_subtree_format(ecmp_parameter_number_tree, tvb, offset, n, ett_ecmp_param_address, NULL, "Parameter Definition %d:", (a+1)); |
1412 | | |
1413 | 1.17k | if (command_value == ECMP_COMMAND_OBJECTINFO) { |
1414 | 73 | proto_tree_add_item(ecmp_parameter_tree, hf_ecmp_info_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
1415 | 73 | offset++; |
1416 | 73 | offset = get_address_scheme(pinfo, offset, scheme, tvb, ecmp_parameter_tree); |
1417 | 73 | offset++; |
1418 | 1.10k | } else { |
1419 | | /*output the address schemes of the parameter requests */ |
1420 | 1.10k | offset = get_address_scheme(pinfo, offset, scheme, tvb, ecmp_parameter_tree); |
1421 | 1.10k | offset++; |
1422 | 1.10k | if (command_value == ECMP_COMMAND_WRITE) { |
1423 | 934 | proto_tree_add_item_ret_uint8(ecmp_parameter_tree, hf_ecmp_data_type, tvb, offset, 1, ENC_BIG_ENDIAN, &data_type); |
1424 | 934 | offset++; |
1425 | 934 | dec = tvb_get_int8(tvb, offset); |
1426 | 934 | if (dec != -1) { |
1427 | 891 | proto_tree_add_int(ecmp_parameter_tree, hf_ecmp_number_of_decimal_places, tvb, offset, 1, dec); |
1428 | 891 | } else { |
1429 | 43 | proto_tree_add_int_format_value(ecmp_parameter_tree, hf_ecmp_number_of_decimal_places, tvb, offset, 1, dec, "0 (Invalid type)"); |
1430 | 43 | } |
1431 | 934 | offset++; |
1432 | 934 | offset = get_data_type(pinfo, offset, data_type, tvb, ecmp_parameter_tree); |
1433 | 934 | offset++; |
1434 | 934 | } |
1435 | 1.10k | } |
1436 | 1.17k | } |
1437 | 53 | } |
1438 | 53 | } |
1439 | | |
1440 | | |
1441 | | /* a function to show the "objectinfo" command response */ |
1442 | | static void get_object_info_response(packet_info* pinfo, unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1443 | 22 | { |
1444 | 22 | proto_item* ecmp_response_item = NULL; |
1445 | 22 | proto_tree* ecmp_parameter_number_tree = NULL; |
1446 | 22 | proto_tree* ecmp_parameter_response_tree = NULL; |
1447 | 22 | uint8_t count = 0; /* stores number of parameter read responses */ |
1448 | 22 | uint8_t a = 0; /* counting variables */ |
1449 | 22 | uint8_t n = 0; |
1450 | 22 | uint8_t info_type0 = 0; |
1451 | 22 | uint16_t length = 0; |
1452 | 22 | uint8_t data_type = 0; |
1453 | | |
1454 | 22 | length = tvb_reported_length(tvb); |
1455 | | |
1456 | 22 | ecmp_response_item = proto_tree_add_item(ecmp_tree, hf_ecmp_number_of_parameter_responses, tvb, offset, 1, ENC_BIG_ENDIAN); |
1457 | 22 | ecmp_parameter_number_tree = proto_item_add_subtree(ecmp_response_item, ett_ecmp_param_address); |
1458 | | |
1459 | 22 | count = tvb_get_uint8(tvb, offset); |
1460 | | |
1461 | 22 | if (count == 0) { |
1462 | 1 | offset++; |
1463 | 1 | proto_tree_add_item(ecmp_parameter_number_tree, hf_ecmp_parameter_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1464 | | |
1465 | 21 | } else { |
1466 | | /*display info data response */ |
1467 | 1.23k | for (a = 0; a < count; a++) { |
1468 | 1.23k | if (a==0) { |
1469 | 21 | n = (length-offset)/count; |
1470 | 21 | } |
1471 | 1.23k | offset++; |
1472 | | /*display response header */ |
1473 | 1.23k | proto_tree_add_subtree_format(ecmp_parameter_number_tree, tvb, offset, n, ett_ecmp_command, NULL, "Response %d:", (a+1)); |
1474 | | |
1475 | | /*display response status */ |
1476 | 1.23k | proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_parameter_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1477 | 1.23k | offset++; |
1478 | | |
1479 | | /*display response data */ |
1480 | 1.23k | proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_info_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
1481 | 1.23k | info_type0 = tvb_get_uint8(tvb, offset); |
1482 | | |
1483 | 1.23k | switch(info_type0) |
1484 | 1.23k | { |
1485 | 280 | case 0: |
1486 | | /*no information available */ |
1487 | 280 | proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_no_information_available, tvb, offset, 1, ENC_NA); |
1488 | 280 | break; |
1489 | 27 | case 1: |
1490 | | /*display min parameter in menu */ |
1491 | 27 | offset++; |
1492 | 27 | proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_min_param_menu, tvb, offset, 2, ENC_BIG_ENDIAN); |
1493 | 27 | offset++; |
1494 | 27 | break; |
1495 | 14 | case 2: |
1496 | | /*display max parameter in menu */ |
1497 | 14 | offset++; |
1498 | 14 | proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_max_param_menu, tvb, offset, 2, ENC_BIG_ENDIAN); |
1499 | 14 | offset++; |
1500 | 14 | break; |
1501 | 74 | case 3: |
1502 | 74 | { |
1503 | 74 | static int * const fields[] = { |
1504 | 74 | &hf_ecmp_param_format_bit_default_unipolar, |
1505 | 74 | &hf_ecmp_param_format_write_allowed, |
1506 | 74 | &hf_ecmp_param_format_read_not_allowed, |
1507 | 74 | &hf_ecmp_param_format_protected_from_destinations, |
1508 | 74 | &hf_ecmp_param_format_parameter_not_visible, |
1509 | 74 | &hf_ecmp_param_format_not_clonable, |
1510 | 74 | &hf_ecmp_param_format_voltage_or_current_rating_dependent, |
1511 | 74 | &hf_ecmp_param_format_parameter_has_no_default, |
1512 | 74 | &hf_ecmp_param_format_number_of_decimal_places, |
1513 | 74 | &hf_ecmp_param_format_variable_maximum_and_minimum, |
1514 | 74 | &hf_ecmp_param_format_string_parameter, |
1515 | 74 | &hf_ecmp_param_format_destination_set_up_parameter, |
1516 | 74 | &hf_ecmp_param_format_filtered_when_displayed, |
1517 | 74 | &hf_ecmp_param_format_pseudo_read_only, |
1518 | 74 | &hf_ecmp_param_format_display_format, |
1519 | 74 | &hf_ecmp_param_format_floating_point_value, |
1520 | 74 | &hf_ecmp_param_format_units, |
1521 | 74 | NULL |
1522 | 74 | }; |
1523 | | |
1524 | | /*display data for parameter format- UNITS and Display Format need dissecting? */ |
1525 | 74 | offset++; |
1526 | 74 | proto_tree_add_bitmask_list(ecmp_parameter_response_tree, tvb, offset, 4, fields, ENC_BIG_ENDIAN); |
1527 | 74 | offset+= 3; |
1528 | 74 | } |
1529 | 74 | break; |
1530 | 97 | case 4: |
1531 | | /*display minimum allowed value*/ |
1532 | 97 | offset++; |
1533 | 97 | ecmp_response_item = proto_tree_add_item_ret_uint8(ecmp_parameter_response_tree, hf_ecmp_data_type, tvb, offset, 1, ENC_BIG_ENDIAN, &data_type); |
1534 | 97 | offset++; |
1535 | 97 | offset = get_data_type(pinfo, offset, data_type, tvb, ecmp_parameter_response_tree); |
1536 | 97 | break; |
1537 | 29 | case 5: |
1538 | | /*display maximum allowed value*/ |
1539 | 29 | offset++; |
1540 | 29 | ecmp_response_item = proto_tree_add_item_ret_uint8(ecmp_parameter_response_tree, hf_ecmp_data_type, tvb, offset, 1, ENC_BIG_ENDIAN, &data_type); |
1541 | 29 | offset++; |
1542 | 29 | offset = get_data_type(pinfo, offset, data_type, tvb, ecmp_parameter_response_tree); |
1543 | 29 | break; |
1544 | 11 | case 6: |
1545 | | /*display Units- ID string */ |
1546 | 11 | offset++; |
1547 | 11 | proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_string_id, tvb, offset, 2, ENC_ASCII); |
1548 | 11 | offset++; |
1549 | 11 | break; |
1550 | 8 | case 7: |
1551 | | /*display data type */ |
1552 | 8 | offset++; |
1553 | 8 | ecmp_response_item = proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_data_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
1554 | 8 | break; |
1555 | 687 | default: |
1556 | 687 | expert_add_info(pinfo, ecmp_response_item, &ei_ecmp_info_type); |
1557 | 687 | break; |
1558 | 1.23k | } |
1559 | 1.23k | } |
1560 | 21 | } |
1561 | 22 | } |
1562 | | |
1563 | | |
1564 | | /* a function to display an array of the read responses */ |
1565 | | static int get_parameter_responses(packet_info* pinfo, unsigned offset, uint8_t command_value, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1566 | 36 | { |
1567 | 36 | proto_item* ecmp_response_item = NULL; |
1568 | 36 | proto_tree* ecmp_parameter_number_tree = NULL; |
1569 | 36 | proto_tree* ecmp_parameter_response_tree = NULL; |
1570 | 36 | uint8_t count = 0; /* stores number of parameter read responses */ |
1571 | 36 | uint8_t a = 0; /* counting variables */ |
1572 | 36 | uint8_t data_type = 0; |
1573 | 36 | uint8_t unit_id = 0; |
1574 | 36 | int8_t dec = 0; |
1575 | 36 | uint16_t n = 0; |
1576 | 36 | uint8_t st_error = 0; |
1577 | 36 | uint16_t length = 0; |
1578 | 36 | uint8_t scheme = 0; |
1579 | 36 | int start_offset; |
1580 | | |
1581 | 36 | scheme = tvb_get_uint8(tvb, offset); |
1582 | 36 | length = tvb_reported_length(tvb); |
1583 | | |
1584 | 36 | if (command_value == ECMP_COMMAND_GETNEXTOBJECTS) { |
1585 | | /*display addressing scheme*/ |
1586 | 3 | proto_tree_add_item(ecmp_tree, hf_ecmp_parameter_address, tvb, offset, 1, ENC_BIG_ENDIAN); |
1587 | 3 | offset++; |
1588 | 3 | } |
1589 | | |
1590 | | /*display number of responses*/ |
1591 | 36 | ecmp_response_item = proto_tree_add_item(ecmp_tree, hf_ecmp_number_of_parameter_responses, tvb, offset, 1, ENC_BIG_ENDIAN); |
1592 | 36 | ecmp_parameter_number_tree = proto_item_add_subtree(ecmp_response_item, ett_ecmp_param_address); |
1593 | | |
1594 | 36 | count = tvb_get_uint8(tvb, offset); |
1595 | | |
1596 | 36 | if (count == 0) { |
1597 | 1 | offset++; |
1598 | 1 | if (command_value != ECMP_COMMAND_GETNEXTOBJECTS) { |
1599 | | /*display parameter status*/ |
1600 | 1 | proto_tree_add_item(ecmp_parameter_number_tree, hf_ecmp_parameter_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1601 | 1 | } |
1602 | 35 | } else { |
1603 | | /*loop for outputting parameter data responses*/ |
1604 | 1.72k | for (a = 0; a < count; a++) { |
1605 | 1.68k | if (command_value == ECMP_COMMAND_WRITE) { |
1606 | 8 | if (a==0) { |
1607 | 1 | n = (length-offset)/count; /*set byte highlighting*/ |
1608 | 1 | } |
1609 | 8 | offset++; |
1610 | | /*display response: (a+1)*/ |
1611 | 8 | ecmp_parameter_response_tree = proto_tree_add_subtree_format(ecmp_parameter_number_tree, tvb, offset, n, ett_ecmp_command, NULL, "Response %d:", (a+1)); |
1612 | 8 | ecmp_response_item = proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_parameter_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1613 | | |
1614 | 1.67k | } else if (command_value == ECMP_COMMAND_GETNEXTOBJECTS) { |
1615 | 211 | if (a==0) { |
1616 | 3 | n = (length-offset)/count; |
1617 | 3 | } |
1618 | 211 | offset++; |
1619 | | /*display response: (a+1)*/ |
1620 | 211 | ecmp_parameter_response_tree = proto_tree_add_subtree_format(ecmp_parameter_number_tree, tvb, offset, n, ett_ecmp_command, NULL, "Response %d:", (a+1)); |
1621 | 211 | offset = get_address_scheme(pinfo, offset, scheme, tvb, ecmp_parameter_response_tree); |
1622 | 1.46k | } else { |
1623 | | /*if status is error */ |
1624 | 1.46k | if (tvb_get_int8(tvb, offset+1) < 0) { |
1625 | | /*output status*/ |
1626 | 464 | st_error = 1; |
1627 | 464 | offset++; |
1628 | 464 | ecmp_parameter_response_tree = proto_tree_add_subtree_format(ecmp_parameter_number_tree, tvb, offset, 1, ett_ecmp_command, NULL, "Response %d:", (a+1)); |
1629 | 464 | ecmp_response_item = proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_parameter_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1630 | 464 | if ((a+1) != count) { |
1631 | | /*loop to move to next data_type (skips bytes == 0)*/ |
1632 | 557 | while(1) { |
1633 | 557 | if(tvb_get_uint8(tvb, offset+1)==0) { |
1634 | 94 | offset++; |
1635 | 463 | } else { |
1636 | 463 | break; |
1637 | 463 | } |
1638 | 557 | } |
1639 | 463 | } |
1640 | 1.00k | } else { |
1641 | 1.00k | offset++; |
1642 | | /*display response data_byte*/ |
1643 | 1.00k | start_offset = offset; |
1644 | 1.00k | ecmp_parameter_response_tree = proto_tree_add_subtree_format(ecmp_parameter_number_tree, tvb, offset, 0, ett_ecmp_command, &ecmp_response_item, "Response %d:", (a+1)); |
1645 | 1.00k | proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_parameter_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1646 | 1.00k | offset++; |
1647 | 1.00k | proto_tree_add_item_ret_uint8(ecmp_parameter_response_tree, hf_ecmp_data_type, tvb, offset, 1, ENC_BIG_ENDIAN, &data_type); |
1648 | 1.00k | offset++; |
1649 | 1.00k | offset = get_data_type(pinfo, offset, data_type, tvb, ecmp_parameter_response_tree); |
1650 | | |
1651 | | /*if "ReadWithType" */ |
1652 | 1.00k | if ((command_value == ECMP_COMMAND_READWITHTYPE) && (st_error!= 1)) { |
1653 | 155 | offset++; |
1654 | | /*display decimal places*/ |
1655 | 155 | dec = tvb_get_int8(tvb, offset); |
1656 | 155 | if (dec != -1) { |
1657 | 152 | proto_tree_add_int(ecmp_parameter_response_tree, hf_ecmp_number_of_decimal_places, tvb, offset, 1, dec); |
1658 | 152 | } else { |
1659 | 3 | proto_tree_add_int_format_value(ecmp_parameter_response_tree, hf_ecmp_number_of_decimal_places, tvb, offset, 1, dec, "0 (Invalid type)"); |
1660 | 3 | } |
1661 | 155 | offset++; |
1662 | | /*display unit ID*/ |
1663 | 155 | proto_tree_add_item_ret_uint8(ecmp_parameter_response_tree, hf_ecmp_display_unit_id, tvb, offset, 1, ENC_NA, &unit_id); |
1664 | 155 | if (unit_id == 255) { |
1665 | 5 | offset++; |
1666 | 5 | proto_tree_add_item(ecmp_parameter_response_tree, hf_ecmp_unit_id_string, tvb, offset, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
1667 | 5 | offset += (tvb_get_ntohs(tvb, offset) + 2); |
1668 | 5 | } |
1669 | 155 | } |
1670 | | |
1671 | 1.00k | proto_item_set_len(ecmp_response_item, offset-start_offset); |
1672 | 1.00k | } |
1673 | | |
1674 | 1.46k | } |
1675 | 1.68k | } |
1676 | 35 | } |
1677 | 36 | return offset; |
1678 | 36 | } |
1679 | | |
1680 | | |
1681 | | /*--------------------------------------------------------------------*/ |
1682 | | /* File Access Commands */ |
1683 | | /*--------------------------------------------------------------------*/ |
1684 | | /* a function to dissect "FileOpen" command */ |
1685 | | static void file_open(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1686 | 2 | { |
1687 | 2 | proto_tree* ecmp_scheme_data_tree = NULL; |
1688 | 2 | uint8_t additional_scheme = 0; |
1689 | 2 | uint8_t relative = 0; |
1690 | | |
1691 | 2 | if (request) { |
1692 | 2 | static int * const fields[] = { |
1693 | 2 | &hf_ecmp_open_in_non_blocking_mode, |
1694 | 2 | &hf_ecmp_open_file_relative_to_specified_directory_handle, |
1695 | 2 | &hf_ecmp_file_access_mode, |
1696 | 2 | NULL |
1697 | 2 | }; |
1698 | | |
1699 | 2 | proto_tree_add_bitmask(ecmp_tree, tvb, offset, hf_ecmp_access_mode, ett_ecmp_access_mode, fields, ENC_BIG_ENDIAN); |
1700 | 2 | relative = (tvb_get_uint8(tvb, offset) & 0x40) ? 1 : 0; |
1701 | 2 | offset++; |
1702 | | |
1703 | | /*display additional scheme*/ |
1704 | 2 | proto_tree_add_item(ecmp_tree, hf_ecmp_additional_scheme, tvb, offset, 1, ENC_BIG_ENDIAN); |
1705 | 2 | additional_scheme= tvb_get_uint8(tvb, offset); |
1706 | | |
1707 | | /*display file name*/ |
1708 | 2 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_name, tvb, offset+1, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
1709 | 2 | offset += (tvb_get_ntohs(tvb, offset+1) + 2); |
1710 | | |
1711 | | /*only show file handle in relative mode*/ |
1712 | 2 | if (relative == 1) { |
1713 | 0 | offset++; |
1714 | | |
1715 | | /*display file handle*/ |
1716 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1717 | 0 | } |
1718 | | |
1719 | 2 | if (additional_scheme == 1) { |
1720 | | /*display additional data*/ |
1721 | 0 | offset+= 2; |
1722 | 0 | ecmp_scheme_data_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, -1, ett_ecmp_access_file, NULL, "Additional scheme data"); |
1723 | 0 | proto_tree_add_item(ecmp_scheme_data_tree, hf_ecmp_scheme_data_length, tvb, offset, 1, ENC_NA); |
1724 | 0 | offset++; |
1725 | 0 | proto_tree_add_item(ecmp_scheme_data_tree, hf_ecmp_data, tvb, offset, -1, ENC_NA); |
1726 | 0 | } |
1727 | 2 | } else { |
1728 | | /*display file status*/ |
1729 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1730 | |
|
1731 | 0 | if (tvb_get_int8(tvb, offset) >= 0) { |
1732 | 0 | offset++; |
1733 | | /*display file handle*/ |
1734 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1735 | 0 | } |
1736 | 0 | } |
1737 | 2 | } |
1738 | | |
1739 | | |
1740 | | /* a function to dissect "FileRead" command */ |
1741 | | static void file_read(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1742 | 0 | { |
1743 | 0 | uint16_t req_bytes = 0; |
1744 | |
|
1745 | 0 | if (request) { |
1746 | | /*display file handle*/ |
1747 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1748 | 0 | offset+=2; |
1749 | | |
1750 | | /*display requested bytes*/ |
1751 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_number_of_requested_bytes, tvb, offset, 2, ENC_BIG_ENDIAN); |
1752 | |
|
1753 | 0 | } else { |
1754 | | /*display file status*/ |
1755 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1756 | |
|
1757 | 0 | if (tvb_get_int8(tvb, offset)>= 0) { |
1758 | 0 | offset++; |
1759 | | |
1760 | | /*display bytes for reading*/ |
1761 | 0 | req_bytes = tvb_get_ntohs(tvb, offset); |
1762 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_response_data, tvb, offset, req_bytes+2, ENC_NA); |
1763 | | /*offset += (2+req_bytes);*/ |
1764 | 0 | } |
1765 | 0 | } |
1766 | 0 | } |
1767 | | |
1768 | | |
1769 | | /* a function to dissect "FileWrite" command */ |
1770 | | static void file_write(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1771 | 0 | { |
1772 | 0 | uint16_t req_bytes; |
1773 | |
|
1774 | 0 | if (request) { |
1775 | | /*display file handle*/ |
1776 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1777 | 0 | offset+=2; |
1778 | | |
1779 | | /*display bytes for writing*/ |
1780 | 0 | req_bytes = tvb_get_ntohs(tvb, offset); |
1781 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_data, tvb, offset+2, req_bytes, ENC_NA); |
1782 | | /*offset += (2+req_bytes);*/ |
1783 | |
|
1784 | 0 | } else { |
1785 | | /*display file status*/ |
1786 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1787 | | /*offset++;*/ |
1788 | 0 | } |
1789 | 0 | } |
1790 | | |
1791 | | |
1792 | | /*a function to dissect "FileClose" command*/ |
1793 | | static void file_close(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1794 | 1 | { |
1795 | 1 | if (request) { |
1796 | | /*display file handle*/ |
1797 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1798 | 1 | offset+=2; |
1799 | | |
1800 | | /*display number of data bytes transferred*/ |
1801 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_number_of_bytes_transferred, tvb, offset, 4, ENC_BIG_ENDIAN); |
1802 | 1 | offset+= 4; |
1803 | | |
1804 | | /*display CRC value*/ |
1805 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_crc, tvb, offset, 4, ENC_BIG_ENDIAN); |
1806 | 1 | } else { |
1807 | | /*display file status*/ |
1808 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1809 | 0 | offset++; |
1810 | 0 | } |
1811 | 1 | } |
1812 | | |
1813 | | |
1814 | | /*a function to display file attributes*/ |
1815 | | static int get_file_attribute(packet_info* pinfo, unsigned offset, tvbuff_t *tvb, proto_tree* ecmp_current_tree) |
1816 | 940 | { |
1817 | 940 | proto_item *ecmp_file_info_att_item; |
1818 | 940 | proto_tree *ecmp_file_info_att_tree; |
1819 | 940 | uint32_t attribute0; |
1820 | 940 | int start_offset = offset; |
1821 | | |
1822 | 940 | ecmp_file_info_att_item = proto_tree_add_item_ret_uint(ecmp_current_tree, |
1823 | 940 | hf_ecmp_file_attributes, tvb, offset, 1, ENC_BIG_ENDIAN, &attribute0); |
1824 | 940 | offset++; |
1825 | 940 | ecmp_file_info_att_tree = proto_item_add_subtree(ecmp_file_info_att_item, ett_ecmp_file_info_att); |
1826 | | |
1827 | 940 | switch(attribute0) |
1828 | 940 | { |
1829 | 141 | case 0: /*display length of file*/ |
1830 | 141 | proto_tree_add_item(ecmp_file_info_att_tree, hf_ecmp_file_length, tvb, offset, 4, ENC_BIG_ENDIAN); |
1831 | 141 | offset += 4; |
1832 | 141 | break; |
1833 | 87 | case 1: /*display integrity*/ |
1834 | 87 | proto_tree_add_item(ecmp_file_info_att_tree, hf_ecmp_file_integrity, tvb, offset, 1, ENC_BIG_ENDIAN); |
1835 | 87 | offset++; |
1836 | 87 | break; |
1837 | 55 | case 2: /*display CRC*/ |
1838 | 55 | proto_tree_add_item(ecmp_file_info_att_tree, hf_ecmp_crc, tvb, offset, 4, ENC_BIG_ENDIAN); |
1839 | 55 | offset += 4; |
1840 | 55 | break; |
1841 | 134 | case 3: /*display attrib*/ |
1842 | 134 | { |
1843 | 134 | static int * const fields[] = { |
1844 | 134 | &hf_ecmp_display_attr_read_only, |
1845 | 134 | &hf_ecmp_display_attr_hidden, |
1846 | 134 | &hf_ecmp_display_attr_system, |
1847 | 134 | &hf_ecmp_display_attr_volume_label, |
1848 | 134 | &hf_ecmp_display_attr_subdirectory, |
1849 | 134 | &hf_ecmp_display_attr_archive, |
1850 | 134 | NULL |
1851 | 134 | }; |
1852 | | |
1853 | 134 | proto_tree_add_bitmask_list(ecmp_file_info_att_tree, tvb, offset, 1, fields, ENC_BIG_ENDIAN); |
1854 | 134 | offset++; |
1855 | 134 | } |
1856 | 134 | break; |
1857 | 43 | case 4: /*display creation date*/ |
1858 | 43 | proto_tree_add_item(ecmp_file_info_att_tree, hf_ecmp_display_creation, tvb, offset, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN); |
1859 | 43 | offset += 4; |
1860 | 43 | break; |
1861 | 7 | case 5: /*display modification date*/ |
1862 | 7 | proto_tree_add_item(ecmp_file_info_att_tree, hf_ecmp_display_modification, tvb, offset, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN); |
1863 | 7 | offset += 4; |
1864 | 7 | break; |
1865 | 473 | default: /*display incorrect attribute type error*/ |
1866 | 473 | proto_tree_add_expert(ecmp_file_info_att_tree, pinfo, &ei_ecmp_attribute_type, tvb, offset, 1); |
1867 | 473 | offset++; |
1868 | 473 | break; |
1869 | 940 | } |
1870 | 928 | proto_item_set_len(ecmp_file_info_att_item, offset - start_offset); |
1871 | 928 | return offset; |
1872 | 940 | } |
1873 | | |
1874 | | |
1875 | | /*a function to dissect "FileInfo" command*/ |
1876 | | static void file_info(packet_info* pinfo, unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1877 | 19 | { |
1878 | 19 | proto_tree *ecmp_file_info_tree; |
1879 | 19 | uint32_t a, no_of_att; |
1880 | 19 | int start_offset; |
1881 | | |
1882 | 19 | if (request) { |
1883 | 4 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1884 | 4 | offset+=2; |
1885 | | |
1886 | 4 | start_offset = offset; |
1887 | 4 | ecmp_file_info_tree = proto_tree_add_subtree(ecmp_tree, |
1888 | 4 | tvb, offset, -1, ett_ecmp_file_info, NULL, "Requested Attributes"); |
1889 | 4 | proto_tree_add_item_ret_uint(ecmp_file_info_tree, |
1890 | 4 | hf_ecmp_no_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN, &no_of_att); |
1891 | 4 | offset++; |
1892 | | |
1893 | 161 | for (a = 0; a < no_of_att; a++) { |
1894 | 157 | proto_tree_add_item(ecmp_file_info_tree, |
1895 | 157 | hf_ecmp_file_attributes, tvb, offset, 1, ENC_BIG_ENDIAN); |
1896 | 157 | offset++; |
1897 | 157 | } |
1898 | 4 | proto_item_set_len(ecmp_file_info_tree, offset - start_offset); |
1899 | 15 | } else { |
1900 | 15 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1901 | 15 | offset++; |
1902 | | |
1903 | 15 | start_offset = offset; |
1904 | 15 | ecmp_file_info_tree = proto_tree_add_subtree(ecmp_tree, |
1905 | 15 | tvb, offset, -1, ett_ecmp_file_info, NULL, "Received Attributes"); |
1906 | | |
1907 | 15 | proto_tree_add_item_ret_uint(ecmp_file_info_tree, |
1908 | 15 | hf_ecmp_no_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN, &no_of_att); |
1909 | 15 | offset++; |
1910 | | |
1911 | | /*display attributes*/ |
1912 | 955 | for (a = 0; a < no_of_att; a++) { |
1913 | 940 | offset = get_file_attribute(pinfo, offset, tvb, ecmp_file_info_tree); |
1914 | 940 | } |
1915 | 15 | proto_item_set_len(ecmp_file_info_tree, offset-start_offset); |
1916 | 15 | } |
1917 | 19 | } |
1918 | | |
1919 | | |
1920 | | /*a function to dissect "FileStatus"/"FileDelete" commands*/ |
1921 | | static void file_state_delete(uint16_t offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1922 | 4 | { |
1923 | 4 | if (request) { |
1924 | | /*display file handle*/ |
1925 | 3 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1926 | | |
1927 | 3 | } else { |
1928 | | /*display file status*/ |
1929 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1930 | 1 | } |
1931 | 4 | } |
1932 | | |
1933 | | |
1934 | | /*a function to dissect "FilePos" command*/ |
1935 | | static void file_pos(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1936 | 1 | { |
1937 | 1 | proto_tree* ecmp_file_position_tree = NULL; |
1938 | | |
1939 | 1 | if (request) { |
1940 | | /*display file handle*/ |
1941 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1942 | 1 | offset+=2; |
1943 | | |
1944 | | /*display "position" header*/ |
1945 | 1 | ecmp_file_position_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 5, ett_ecmp_file_position, NULL, "Position"); |
1946 | | |
1947 | | /*display reference point*/ |
1948 | 1 | proto_tree_add_item(ecmp_file_position_tree, hf_ecmp_file_ref_point, tvb, offset, 1, ENC_BIG_ENDIAN); |
1949 | 1 | offset++; |
1950 | | |
1951 | | /*display offset from ref point*/ |
1952 | 1 | proto_tree_add_item(ecmp_file_position_tree, hf_ecmp_ref_offset, tvb, offset, 4, ENC_BIG_ENDIAN); |
1953 | | |
1954 | 1 | } else { |
1955 | | /*display file status*/ |
1956 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1957 | |
|
1958 | 0 | if(tvb_get_int8(tvb,offset) >= 0) { |
1959 | 0 | offset++; |
1960 | | |
1961 | | /*display offset from ref point*/ |
1962 | 0 | proto_tree_add_item(ecmp_file_position_tree, hf_ecmp_ref_offset, tvb, offset, 4, ENC_BIG_ENDIAN); |
1963 | 0 | } |
1964 | 0 | } |
1965 | 1 | } |
1966 | | |
1967 | | |
1968 | | /*a function to dissect "FileList" command*/ |
1969 | | static void file_list(packet_info* pinfo, unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
1970 | 5 | { |
1971 | 5 | proto_item* ecmp_file_list_item, *ecmp_file_list_item2, *item_type_item; |
1972 | 5 | proto_tree* ecmp_file_list_no_tree = NULL; |
1973 | 5 | proto_tree* ecmp_file_list_tree = NULL; |
1974 | 5 | uint8_t no_of_items = 0; |
1975 | 5 | uint8_t item_type = 0; |
1976 | 5 | uint8_t a = 0; |
1977 | 5 | uint16_t n = 0; |
1978 | 5 | int start_offset, start_offset2; |
1979 | | |
1980 | 5 | if (request) { |
1981 | | /*display file handle*/ |
1982 | 2 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_handle, tvb, offset, 2, ENC_BIG_ENDIAN); |
1983 | 2 | offset+= 2; |
1984 | | |
1985 | | /*display number of files to list*/ |
1986 | 2 | proto_tree_add_item(ecmp_tree, hf_ecmp_number_of_files_to_list, tvb, offset, 1, ENC_NA); |
1987 | 3 | } else { |
1988 | | /*display file status*/ |
1989 | 3 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
1990 | | |
1991 | 3 | if (tvb_get_int8(tvb,offset) >= 0) { |
1992 | 3 | offset++; |
1993 | | |
1994 | | /*display number of files to list*/ |
1995 | 3 | no_of_items = tvb_get_uint8(tvb, offset); |
1996 | 3 | proto_tree_add_item(ecmp_tree, hf_ecmp_number_of_files_to_list, tvb, offset, 1, ENC_NA); |
1997 | 3 | offset++; |
1998 | | |
1999 | | /*display hash value (dissection TBD)*/ |
2000 | 3 | ecmp_file_list_item = proto_tree_add_item(ecmp_tree, hf_ecmp_file_hash, tvb, offset, 2, ENC_BIG_ENDIAN); |
2001 | 3 | offset++; |
2002 | | |
2003 | | /*display subtree for files*/ |
2004 | 3 | start_offset = offset+1; |
2005 | 3 | ecmp_file_list_no_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset+1, no_of_items, ett_ecmp_file_list_no, &ecmp_file_list_item, "Files"); |
2006 | | |
2007 | | /*display list of file names*/ |
2008 | 11 | for (a = 0; a < no_of_items; a++) { |
2009 | 9 | start_offset2 = offset; |
2010 | 9 | offset++; |
2011 | 9 | item_type = tvb_get_uint8(tvb, offset); |
2012 | 9 | n = tvb_get_ntohs(tvb, offset+1); |
2013 | 9 | ecmp_file_list_tree = proto_tree_add_subtree_format(ecmp_file_list_no_tree, tvb, offset, n+2, ett_ecmp_file_list, &ecmp_file_list_item2, "File %d:", a+1); |
2014 | 9 | item_type_item = proto_tree_add_item(ecmp_file_list_tree, hf_ecmp_item_type, tvb, offset, 1, ENC_NA); |
2015 | | |
2016 | 9 | switch(item_type) |
2017 | 9 | { |
2018 | 5 | case 0: /*if item type is "file"*/ |
2019 | 5 | proto_tree_add_item(ecmp_file_list_tree, hf_ecmp_file_name, tvb, offset+1, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
2020 | 5 | break; |
2021 | | |
2022 | 0 | case 1: /*if item type is "directory"*/ |
2023 | 0 | proto_tree_add_item(ecmp_file_list_tree, hf_ecmp_directory, tvb, offset+1, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
2024 | 0 | break; |
2025 | | |
2026 | 3 | default: /*if item type is not "file" or "directory"*/ |
2027 | 3 | expert_add_info(pinfo, item_type_item, &ei_ecmp_item_type); |
2028 | 3 | break; |
2029 | 9 | } |
2030 | 8 | offset+= n; |
2031 | | |
2032 | 8 | proto_item_set_len(ecmp_file_list_item2, offset-start_offset2); |
2033 | 8 | } |
2034 | | |
2035 | 2 | proto_item_set_len(ecmp_file_list_item, (offset+1)-start_offset); |
2036 | 2 | } |
2037 | 3 | } |
2038 | 5 | } |
2039 | | |
2040 | | |
2041 | | /*a function to dissect "FileExists" command*/ |
2042 | | static void file_exists(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
2043 | 0 | { |
2044 | 0 | if (request) { |
2045 | | /*display filename*/ |
2046 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_name, tvb, offset, 2, ENC_BIG_ENDIAN|ENC_ASCII); |
2047 | 0 | } else { |
2048 | | /*display file status*/ |
2049 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_file_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
2050 | 0 | } |
2051 | 0 | } |
2052 | | |
2053 | | |
2054 | | static int add_cyclic_setup_attributes(packet_info* pinfo, unsigned offset, uint16_t length, tvbuff_t *tvb, proto_tree* ecmp_tree) |
2055 | 98 | { |
2056 | 98 | proto_item *cyclic_setup_attributes_root = NULL; |
2057 | 98 | proto_item *cyclic_setup_attributes = NULL; |
2058 | 98 | proto_item *cyclic_setup_attrib_item_root = NULL; |
2059 | 98 | proto_tree *cyclic_setup_attrib_item = NULL; |
2060 | 98 | uint8_t attrib; |
2061 | | |
2062 | | /* num attribs */ |
2063 | 98 | cyclic_setup_attributes_root = proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_attrib_count, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2064 | | |
2065 | | /* attrib list */ |
2066 | 98 | cyclic_setup_attributes = proto_item_add_subtree(cyclic_setup_attributes_root, ett_cyclic_setup_attribs); |
2067 | | |
2068 | 21.3k | while (offset < length) { |
2069 | 21.2k | cyclic_setup_attrib_item_root = proto_tree_add_item_ret_uint8(cyclic_setup_attributes, hf_ecmp_cyclic_setup_attrib, tvb, offset++, 1, ENC_BIG_ENDIAN, &attrib); |
2070 | | |
2071 | 21.2k | cyclic_setup_attrib_item = proto_item_add_subtree(cyclic_setup_attrib_item_root, ett_cyclic_setup_attrib_item); |
2072 | | |
2073 | 21.2k | switch (attrib) { |
2074 | 201 | case 3: /* mec offset */ |
2075 | 201 | { |
2076 | 201 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_mec_offset, tvb, offset, 4, ENC_BIG_ENDIAN); |
2077 | 201 | offset += 4; |
2078 | 201 | } |
2079 | 201 | break; |
2080 | | |
2081 | 138 | case 4: /* sample period */ |
2082 | 274 | case 5: /* mec delay */ |
2083 | 274 | { |
2084 | 274 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_sample_period, tvb, offset, 8, ENC_BIG_ENDIAN); |
2085 | 274 | offset += 8; |
2086 | 274 | } |
2087 | 274 | break; |
2088 | | |
2089 | 139 | case 7: /* rx timeout */ |
2090 | 139 | { |
2091 | | /* tout */ |
2092 | 139 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_rx_timeout, tvb, offset, 4, ENC_BIG_ENDIAN); |
2093 | 139 | offset += 4; |
2094 | | |
2095 | | /* action */ |
2096 | 139 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_rx_action, tvb, offset++, 1, ENC_NA); |
2097 | | |
2098 | | /* event dest */ |
2099 | 139 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_rx_event_destination, tvb, offset++, 1, ENC_NA); |
2100 | | |
2101 | | /* event */ |
2102 | 139 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_rx_event, tvb, offset++, 1, ENC_NA); |
2103 | | |
2104 | 139 | } |
2105 | 139 | break; |
2106 | | |
2107 | 168 | case 8: /* rx late handler */ |
2108 | 168 | { |
2109 | | /* action */ |
2110 | 168 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_rx_late_handler_action, tvb, offset++, 1, ENC_NA); |
2111 | | |
2112 | | /* event dest */ |
2113 | 168 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_rx_late_handler_event_destination, tvb, offset++, 1, ENC_NA); |
2114 | | |
2115 | | /* event */ |
2116 | 168 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_rx_late_handler_event, tvb, offset++, 1, ENC_NA); |
2117 | 168 | } |
2118 | 168 | break; |
2119 | | |
2120 | 77 | case 9: /* transport addr */ |
2121 | 77 | { |
2122 | | /* scheme */ |
2123 | 77 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_transport_addr_scheme, tvb, offset++, 1, ENC_NA); |
2124 | | |
2125 | | /* todo - make this check the scheme is actually 0! */ |
2126 | | |
2127 | 77 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_transport_addr, tvb, offset, 4, ENC_BIG_ENDIAN); |
2128 | 77 | offset += 4; |
2129 | 77 | } |
2130 | 77 | break; |
2131 | | |
2132 | 232 | case 12: /* mapping item */ |
2133 | 232 | { |
2134 | 232 | uint8_t addrScheme; |
2135 | | |
2136 | 232 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_mapping_item_offset, tvb, offset++, 1, ENC_NA); |
2137 | | |
2138 | 232 | addrScheme = tvb_get_uint8(tvb, offset); |
2139 | 232 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_mapping_item_scheme, tvb, offset++, 1, ENC_NA); |
2140 | | |
2141 | 232 | offset = get_address_scheme(pinfo, offset, addrScheme, tvb, cyclic_setup_attrib_item); |
2142 | | |
2143 | | /* todo - should this be done in the last function itself??? */ |
2144 | 232 | offset++; |
2145 | 232 | } |
2146 | 232 | break; |
2147 | | |
2148 | 3.37k | case 0: /* state */ |
2149 | 3.90k | case 1: /* rx/tx */ |
2150 | 4.45k | case 2: /* synchronised */ |
2151 | 4.75k | case 6: /* data change */ |
2152 | 4.96k | case 10: /* max mappings */ |
2153 | 5.05k | case 11: /* num mappings */ |
2154 | 5.29k | case 13: /* saveable */ |
2155 | 5.53k | case 128: /* max rx links */ |
2156 | 5.61k | case 129: /* max tx links */ |
2157 | 5.73k | case 130: /* max mappings per link */ |
2158 | 6.13k | case 131: /* max sync rx links */ |
2159 | 6.34k | case 132: /* max sync tx links */ |
2160 | 6.36k | case 133: /* max mappings per sync link */ |
2161 | 6.49k | case 134: /* process at queue depth */ |
2162 | 6.49k | { |
2163 | 6.49k | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_setup_attribute, tvb, offset++, 1, ENC_NA); |
2164 | 6.49k | } |
2165 | 6.49k | break; |
2166 | | |
2167 | 41 | case 135: /* mec period */ |
2168 | 41 | { |
2169 | 41 | proto_tree_add_item(cyclic_setup_attrib_item, hf_ecmp_mec_period, tvb, offset, 4, ENC_BIG_ENDIAN); |
2170 | 41 | offset += 4; |
2171 | 41 | } |
2172 | 41 | break; |
2173 | | |
2174 | 13.6k | default: |
2175 | 13.6k | break; |
2176 | | |
2177 | 21.2k | } /* attribute switch */ |
2178 | 21.2k | } /* loop through list */ |
2179 | | |
2180 | 42 | return offset; |
2181 | 98 | } |
2182 | | |
2183 | | |
2184 | | static void cyclic_setup(packet_info* pinfo, uint16_t offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
2185 | 108 | { |
2186 | 108 | uint16_t length = 0; |
2187 | 108 | proto_item* cyclic_setup_attributes_root = NULL; |
2188 | 108 | proto_item* cyclic_setup_attributes = NULL; |
2189 | 108 | uint8_t Mode; |
2190 | | |
2191 | 108 | length = tvb_reported_length(tvb); |
2192 | | |
2193 | | /* if a request add the check output flag */ |
2194 | 108 | if (request) { |
2195 | 107 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_linkno, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2196 | | |
2197 | 107 | Mode = tvb_get_uint8(tvb, offset); |
2198 | 107 | proto_tree_add_uint(ecmp_tree, hf_ecmp_cyclic_setup_mode, tvb, offset++, 1, Mode); |
2199 | | |
2200 | 107 | switch (Mode) { |
2201 | 76 | case 0: /* create */ |
2202 | 98 | case 10: /* set */ |
2203 | 98 | { |
2204 | | /* link direction */ |
2205 | 98 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_dir, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2206 | | |
2207 | | /* add the attributes as a tree */ |
2208 | 98 | add_cyclic_setup_attributes(pinfo, offset, length, tvb, ecmp_tree); |
2209 | 98 | } |
2210 | 98 | break; |
2211 | | |
2212 | 0 | case 1: /* edit */ |
2213 | 1 | case 2: /* finalise */ |
2214 | 1 | case 3: /* delete */ |
2215 | 2 | case 4: /* exist */ |
2216 | | /* link direction */ |
2217 | 2 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_dir, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2218 | 2 | break; |
2219 | | |
2220 | 0 | case 5: /* list */ |
2221 | | /* tx/rx bits */ |
2222 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); |
2223 | 0 | break; |
2224 | | |
2225 | 0 | case 11: /* get */ |
2226 | 4 | case 6: /* info */ |
2227 | 4 | { |
2228 | 4 | if (Mode == 11) { |
2229 | | /* link dir */ |
2230 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_dir, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2231 | 0 | } |
2232 | | |
2233 | | /* num attribs */ |
2234 | 4 | cyclic_setup_attributes_root = proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_attrib_count, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2235 | | |
2236 | | /* attrib list */ |
2237 | 4 | cyclic_setup_attributes = proto_item_add_subtree(cyclic_setup_attributes_root, ett_cyclic_setup_attribs); |
2238 | 1.54k | while (offset < length) { |
2239 | 1.54k | proto_tree_add_item(cyclic_setup_attributes, hf_ecmp_cyclic_setup_attrib, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2240 | 1.54k | } |
2241 | 4 | } |
2242 | 4 | break; |
2243 | | |
2244 | 1 | case 12: /* get mappings */ |
2245 | 1 | { |
2246 | | /* link dir */ |
2247 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_dir, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2248 | | |
2249 | | /* max mappings */ |
2250 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_max_mappings, tvb, offset++, 1, ENC_NA); |
2251 | | |
2252 | | /* start offset */ |
2253 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_start_offset, tvb, offset++, 1, ENC_NA); |
2254 | 1 | } |
2255 | 1 | break; |
2256 | | |
2257 | 2 | default: |
2258 | | /* display payload as hex bytes */ |
2259 | 2 | proto_tree_add_item(ecmp_tree, hf_ecmp_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); |
2260 | 2 | break; |
2261 | 107 | } |
2262 | 107 | } else { |
2263 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_rsp_status, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2264 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_rsp_err_idx, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2265 | | |
2266 | 1 | Mode = tvb_get_uint8(tvb, offset); |
2267 | 1 | proto_tree_add_uint(ecmp_tree, hf_ecmp_cyclic_setup_mode, tvb, offset++, 1, Mode); |
2268 | | |
2269 | 1 | switch (Mode) { |
2270 | 0 | case 0: /* create */ |
2271 | 0 | case 1: /* edit */ |
2272 | 0 | case 2: /* finalise */ |
2273 | 0 | case 3: /* delete */ |
2274 | | /* no mode specific data */ |
2275 | 0 | break; |
2276 | | |
2277 | 0 | case 4: /* exist */ |
2278 | 0 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_link_exists, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2279 | 0 | break; |
2280 | | |
2281 | 0 | case 5: /* list */ |
2282 | 0 | { |
2283 | 0 | uint8_t txCount, rxCount, linkno; |
2284 | | |
2285 | | /* num attribs */ |
2286 | 0 | txCount = tvb_get_uint8(tvb, offset); |
2287 | 0 | cyclic_setup_attributes_root = proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_tx_count, tvb, offset++, 1, ENC_NA); |
2288 | | |
2289 | | /* link list */ |
2290 | 0 | cyclic_setup_attributes = proto_item_add_subtree(cyclic_setup_attributes_root, ett_cyclic_setup_attribs); |
2291 | 0 | while (txCount > 0) { |
2292 | 0 | linkno = tvb_get_uint8(tvb, offset); |
2293 | 0 | proto_tree_add_uint(cyclic_setup_attributes, hf_ecmp_cyclic_setup_linkno, tvb, offset++, 1, linkno); |
2294 | 0 | txCount--; |
2295 | 0 | } |
2296 | |
|
2297 | 0 | rxCount = tvb_get_uint8(tvb, offset); |
2298 | 0 | cyclic_setup_attributes_root = proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_rx_count, tvb, offset++, 1, ENC_NA); |
2299 | | |
2300 | | /* link list */ |
2301 | 0 | cyclic_setup_attributes = proto_item_add_subtree(cyclic_setup_attributes_root, ett_cyclic_setup_attribs); |
2302 | 0 | while (rxCount > 0) { |
2303 | 0 | linkno = tvb_get_uint8(tvb, offset); |
2304 | 0 | proto_tree_add_uint(cyclic_setup_attributes, hf_ecmp_cyclic_setup_linkno, tvb, offset++, 1, linkno); |
2305 | 0 | rxCount--; |
2306 | 0 | } |
2307 | 0 | } |
2308 | 0 | break; |
2309 | | |
2310 | 0 | case 10: /* set */ |
2311 | 0 | { |
2312 | | /* num attribs */ |
2313 | 0 | cyclic_setup_attributes_root = proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_setup_attrib_count, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2314 | | |
2315 | | /* attrib list */ |
2316 | 0 | cyclic_setup_attributes = proto_item_add_subtree(cyclic_setup_attributes_root, ett_cyclic_setup_attribs); |
2317 | 0 | while (offset < length) { |
2318 | 0 | proto_tree_add_item(cyclic_setup_attributes, hf_ecmp_cyclic_setup_attrib, tvb, offset++, 1, ENC_BIG_ENDIAN); |
2319 | 0 | } |
2320 | 0 | } |
2321 | 0 | break; |
2322 | | |
2323 | 0 | case 11: /* get */ |
2324 | 0 | case 12: /* get mappings */ |
2325 | 0 | case 6: /* info */ |
2326 | | /* add the attributes as a tree */ |
2327 | 0 | add_cyclic_setup_attributes(pinfo, offset, length, tvb, ecmp_tree); |
2328 | 0 | break; |
2329 | | |
2330 | 1 | default: |
2331 | | /* display payload as hex bytes */ |
2332 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); |
2333 | 1 | break; |
2334 | 1 | } |
2335 | 1 | } |
2336 | 108 | } |
2337 | | |
2338 | | |
2339 | | /*a function to dissect "ProgramStatus" command */ |
2340 | | static void program_status(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
2341 | 2 | { |
2342 | | /* Description:function to dissect Program Status command */ |
2343 | | /* */ |
2344 | | /* Inputs: */ |
2345 | | /* offset - current offset of pointer within the ECMP frame */ |
2346 | | /* command_value - function code of ECMP message */ |
2347 | | /* request - (1 = query, 0 = response) */ |
2348 | | /* tvb - Wireshark protocol tree */ |
2349 | | /* ecmp_tree - Wireshark protocol tree */ |
2350 | | /* tree - Wireshark protocol tree */ |
2351 | | /* */ |
2352 | | /* Returns: nothing */ |
2353 | | /* */ |
2354 | | /* Notes: for queries, the "offset" points to the "target". */ |
2355 | | /* for responses, the "offset" points to the "status". */ |
2356 | | /* */ |
2357 | | /* sample ECMP Request Frame */ |
2358 | | /* 0x61 - request code (program control) */ |
2359 | | /* 0x00 - option terminator */ |
2360 | | /* 0x00 - target (0 = default program) <======== offset */ |
2361 | | /* */ |
2362 | | /* sample ECMP Response Frame */ |
2363 | | /* 0xE1 - response code (program control) */ |
2364 | | /* 0x00 - option terminator */ |
2365 | | /* 0x01 - running state (0=Stopped, 1=Running ... ) <======== offset */ |
2366 | | /* 0x00 - additional items */ |
2367 | | |
2368 | 2 | proto_item* ecmp_program_status_message_tree = NULL; |
2369 | | |
2370 | | /* differentiate between ECMP query and response */ |
2371 | 2 | if (request) { |
2372 | | /*display the program control details sub-tree */ |
2373 | 2 | ecmp_program_status_message_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 1, ett_ecmp_program_status_message, NULL, "Program Status: (Query)"); |
2374 | | |
2375 | | /* read the target */ |
2376 | 2 | proto_tree_add_item(ecmp_program_status_message_tree, hf_ecmp_program_status_target, tvb, offset, 1, ENC_NA); |
2377 | 2 | } else { |
2378 | | /*display the program status details sub-tree */ |
2379 | 0 | ecmp_program_status_message_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 2, ett_ecmp_program_status_message, NULL, "Program Status: (Response)"); |
2380 | | |
2381 | | /* read and display the Status */ |
2382 | 0 | proto_tree_add_item(ecmp_program_status_message_tree, hf_ecmp_program_status_status, tvb, offset, 1, ENC_NA); |
2383 | 0 | offset += 1; |
2384 | | |
2385 | | /* read and display the Additional Items */ |
2386 | 0 | proto_tree_add_item(ecmp_program_status_message_tree, hf_ecmp_program_status_additional_items, tvb, offset, 1, ENC_NA); |
2387 | 0 | } |
2388 | 2 | } |
2389 | | |
2390 | | |
2391 | | /*a function to dissect "ProgramControl" command */ |
2392 | | static void program_control(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
2393 | 1 | { |
2394 | | /* Description:function to dissect Program Control command */ |
2395 | | /* */ |
2396 | | /* Inputs: */ |
2397 | | /* offset - current offset of pointer within the ECMP frame */ |
2398 | | /* command_value - function code of ECMP message */ |
2399 | | /* request - (1 = query, 0 = response) */ |
2400 | | /* tvb - Wireshark protocol tree */ |
2401 | | /* ecmp_tree - Wireshark protocol tree */ |
2402 | | /* tree - Wireshark protocol tree */ |
2403 | | /* */ |
2404 | | /* Returns: nothing */ |
2405 | | /* */ |
2406 | | /* Notes: for queries, the "offset" points to the "target". */ |
2407 | | /* for responses, the "offset" points to the "status". */ |
2408 | | /* */ |
2409 | | /* sample ECMP Request Frame */ |
2410 | | /* 0x60 - request code (program control) */ |
2411 | | /* 0x00 - option terminator */ |
2412 | | /* 0x00 - target (0 = default program) <======== offset */ |
2413 | | /* 0x01 - command (1 = start the program) */ |
2414 | | /* 0x00 - sub command */ |
2415 | | /* */ |
2416 | | /* sample ECMP Response Frame */ |
2417 | | /* 0xE0 - response code (program control) */ |
2418 | | /* 0x00 - option terminator */ |
2419 | | /* 0x00 - status (0 = OK) <======== offset */ |
2420 | | /* */ |
2421 | | |
2422 | 1 | proto_item* ecmp_program_control_message_tree = NULL; |
2423 | | |
2424 | | /* differentiate between ECMP query and response */ |
2425 | 1 | if (request) { |
2426 | | /*display the program control details sub-tree */ |
2427 | 1 | ecmp_program_control_message_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 3, ett_ecmp_program_control_message, NULL, "Program Control: (Query)"); |
2428 | | |
2429 | | /* read the target */ |
2430 | 1 | proto_tree_add_item(ecmp_program_control_message_tree, hf_ecmp_program_control_target, tvb, offset, 1, ENC_NA); |
2431 | 1 | offset += 1; |
2432 | | |
2433 | | /* read the command */ |
2434 | 1 | proto_tree_add_item(ecmp_program_control_message_tree, hf_ecmp_program_control_command, tvb, offset, 1, ENC_NA); |
2435 | 1 | offset += 1; |
2436 | | |
2437 | | /* read the subcommand */ |
2438 | 1 | proto_tree_add_item(ecmp_program_control_message_tree, hf_ecmp_program_control_sub_command, tvb, offset, 1, ENC_NA); |
2439 | 1 | } else { |
2440 | | /*display the program control details sub-tree */ |
2441 | 0 | ecmp_program_control_message_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 1, ett_ecmp_program_control_message, NULL, "Program Control: (Response)"); |
2442 | | |
2443 | | /* read and display the Status */ |
2444 | 0 | proto_tree_add_item(ecmp_program_control_message_tree, hf_ecmp_program_control_status, tvb, offset, 1, ENC_NA); |
2445 | 0 | } |
2446 | 1 | } |
2447 | | |
2448 | | |
2449 | | /*a function to dissect "ModbusPDU" command */ |
2450 | | static void modbus_pdu(unsigned offset, bool request, tvbuff_t *tvb, packet_info* pinfo, proto_tree* ecmp_tree) |
2451 | 2 | { |
2452 | | /* Description:function to dissect Modbus PDU ECMP transactions */ |
2453 | | /* */ |
2454 | | /* Inputs: */ |
2455 | | /* offset - current offset of pointer within the ECMP frame */ |
2456 | | /* command_value - function code of ECMP message */ |
2457 | | /* request - (1 = query, 0 = response) */ |
2458 | | /* tvb - Wireshark protocol tree */ |
2459 | | /* ecmp-tree - Wireshark protocol tree */ |
2460 | | /* tree - Wireshark protocol tree */ |
2461 | | /* */ |
2462 | | /* Returns: nothing */ |
2463 | | /* */ |
2464 | | /* Notes: for queries, the "offset" points to the "size". */ |
2465 | | /* for responses, the "offset" points to the size. */ |
2466 | | /* */ |
2467 | | /* sample ECMP Request Frame (Read Holding Registers) */ |
2468 | | /* 0x74 - request code (ModbusMaster) */ |
2469 | | /* 0x00 - option terminator */ |
2470 | | /* 0x00 - size msb <======== offset */ |
2471 | | /* 0x05 - size lsb */ |
2472 | | /* 0x03 - function code - read hold reg */ |
2473 | | /* 0x07 - register address (#20.021) msb */ |
2474 | | /* 0xE4 - register address lsb */ |
2475 | | /* 0x00 - number registers msb */ |
2476 | | /* 0x03 - number registers lsb */ |
2477 | | /* */ |
2478 | | /* sample ECMP Response Frame */ |
2479 | | /* 0xF4 - response code (ModbusMaster) */ |
2480 | | /* 0x00 - option terminator */ |
2481 | | /* 0x00 - size msb <======== offset */ |
2482 | | /* 0x08 - size lsb */ |
2483 | | /* 0x03 - function code - read hold reg */ |
2484 | | /* 0x06 - byte count */ |
2485 | | /* 0x30 - register #2021 value 12345 msb */ |
2486 | | /* 0x39 - register #2021 value lsb */ |
2487 | | /* 0x03 - register #2022 value 787 msb */ |
2488 | | /* 0x13 - register #2022 value lsb */ |
2489 | | /* 0x00 - register #2023 value 100 msb */ |
2490 | | /* 0x64 - register #2023 value lsb */ |
2491 | | |
2492 | 2 | tvbuff_t* next_tvb; |
2493 | 2 | uint16_t size = 0; /* from Modbus TCP/IP spec: number of bytes that follow */ |
2494 | 2 | modbus_data_t modbus_data; |
2495 | | |
2496 | | /* differentiate between ECMP query and response */ |
2497 | 2 | if (request) { |
2498 | | /* read and display the Size */ |
2499 | 1 | proto_tree_add_item_ret_uint16(ecmp_tree, hf_ecmp_modbus_pdu_size, tvb, offset, 2, ENC_BIG_ENDIAN, &size); |
2500 | 1 | offset += 2; |
2501 | | |
2502 | | /* keep packet context */ |
2503 | 1 | modbus_data.packet_type = QUERY_PACKET; |
2504 | 1 | modbus_data.mbtcp_transid = 0; |
2505 | 1 | modbus_data.unit_id = 0; |
2506 | 1 | next_tvb = tvb_new_subset_length(tvb, offset, size); |
2507 | 1 | call_dissector_with_data(modbus_handle, next_tvb, pinfo, ecmp_tree, &modbus_data); |
2508 | | |
2509 | 1 | } else { |
2510 | | /* read and display the Size */ |
2511 | 1 | proto_tree_add_item_ret_uint16(ecmp_tree, hf_ecmp_modbus_pdu_size, tvb, offset, 2, ENC_BIG_ENDIAN, &size); |
2512 | 1 | offset += 2; |
2513 | | |
2514 | 1 | modbus_data.packet_type = RESPONSE_PACKET; |
2515 | 1 | modbus_data.mbtcp_transid = 0; |
2516 | 1 | modbus_data.unit_id = 0; |
2517 | 1 | next_tvb = tvb_new_subset_length(tvb, offset, size); |
2518 | 1 | call_dissector_with_data(modbus_handle, next_tvb, pinfo, ecmp_tree, &modbus_data); |
2519 | 1 | } |
2520 | 2 | } |
2521 | | |
2522 | | |
2523 | | /*a function to dissect "Interrogate" command */ |
2524 | | static void interrogate(packet_info* pinfo, unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
2525 | 10 | { |
2526 | | /* Description: function to dissect Interrogate command */ |
2527 | | /* */ |
2528 | | /* Inputs: */ |
2529 | | /* offset - current offset of pointer within the ECMP frame */ |
2530 | | /* request - (1 = query, 0 = response) */ |
2531 | | /* tvb - rather complex structure that has the frame data */ |
2532 | | /* ecmp-tree - Wireshark protocol tree */ |
2533 | | /* */ |
2534 | | /* Returns: nothing */ |
2535 | | /* */ |
2536 | | /* Notes: for queries, the "offset" points to the "item type". */ |
2537 | | /* for responses, the "offset" points to the "item type". */ |
2538 | | /* */ |
2539 | | /* sample ECMP Request Frame */ |
2540 | | /* 0x02 - request code (interrogate) */ |
2541 | | /* 0x00 - option terminator */ |
2542 | | /* 0x00 - item type (0=ECMP command, 1=ECMP option) <==== offset */ |
2543 | | /* 0x05 - count (number of commands/options to follow) */ |
2544 | | /* 0x10 - item code #1 ECMP Read command */ |
2545 | | /* 0x11 - item code #2 ECMP ReadWithType command */ |
2546 | | /* 0x12 - item code #3 ECMP Write command */ |
2547 | | /* 0x13 - item code #4 ECMP ObjectInfo command */ |
2548 | | /* 0x14 - item code #5 ECMP GetNextObject command */ |
2549 | | /* */ |
2550 | | /* sample ECMP Response Frame */ |
2551 | | /* 0x82 - response code (program control) */ |
2552 | | /* 0x00 - option terminator */ |
2553 | | /* 0x00 - item type (0=ECMP command, 1=ECMP option) <==== offset */ |
2554 | | /* 0x05 - count (number of commands/options to follow) */ |
2555 | | /* 0x10 - item code #1 */ |
2556 | | /* 0x01 - supported (ECMP Read command) */ |
2557 | | /* 0x11 - item code #2 */ |
2558 | | /* 0x01 - supported (ECMP ReadWithType command) */ |
2559 | | /* 0x12 - item code #3 */ |
2560 | | /* 0x01 - supported (ECMP Write command) */ |
2561 | | /* 0x13 - item code #4 */ |
2562 | | /* 0x01 - supported (ECMP ObjectInfo command) */ |
2563 | | /* 0x14 - item code #5 */ |
2564 | | /* 0x01 - supported (ECMP GetNextObject command) */ |
2565 | | /* */ |
2566 | | /* */ |
2567 | | /* Item Type: 0 = ECMP command */ |
2568 | | /* 1 = ECMP option (not currently implemented) */ |
2569 | | /* */ |
2570 | | /* Item Code: 0 .. 0x7F for commands */ |
2571 | | /* 0 .. 2 for options */ |
2572 | | /* */ |
2573 | | /* Item Support: 0 = not supported */ |
2574 | | /* 1 = supported */ |
2575 | | /* */ |
2576 | | |
2577 | | |
2578 | 10 | const uint8_t interrogate_type_command = 0; |
2579 | | |
2580 | 10 | proto_tree* ecmp_interrogate_message_tree = NULL, *ecmp_interrogate_tree; |
2581 | 10 | proto_item* ecmp_interrogate_message_item = NULL; |
2582 | 10 | uint8_t item_type = 0; /* 0=ECMP command, 1=ECMP option */ |
2583 | 10 | uint8_t command_req = 0; /* ECMP command */ |
2584 | 10 | uint8_t supported = 0; /* ECMP command support status: 1=supported, 0=not supported */ |
2585 | 10 | uint32_t count = 0; /* number of ECMP commands to be checked */ |
2586 | 10 | uint32_t j; /* loop counter */ |
2587 | | |
2588 | | |
2589 | | /* differentiate between ECMP query and response */ |
2590 | 10 | if (request) { |
2591 | | |
2592 | | /* identify the ECMP command we're dissecting */ |
2593 | 7 | ecmp_interrogate_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 2, ett_ecmp_interrogate_message, NULL, "Interrogate: (Query)"); |
2594 | | |
2595 | | /* read the item_type (command/option setting) */ |
2596 | 7 | proto_tree_add_item_ret_uint8(ecmp_interrogate_tree, hf_ecmp_interrogate_item_type, tvb, offset, 1, ENC_NA, &item_type); |
2597 | 7 | offset += 1; |
2598 | | |
2599 | | /* read the count */ |
2600 | 7 | proto_tree_add_item_ret_uint(ecmp_interrogate_tree, hf_ecmp_interrogate_count, tvb, offset, 1, ENC_NA, &count); |
2601 | 7 | offset += 1; |
2602 | | |
2603 | | /*create the interrogate details sub-tree */ |
2604 | 7 | ecmp_interrogate_message_tree = proto_tree_add_subtree(ecmp_interrogate_tree, tvb, offset, count, ett_ecmp_interrogate_message, &ecmp_interrogate_message_item, "ECMP Commands to be Checked"); |
2605 | | |
2606 | | /* display the item_codes (commands to be checked) */ |
2607 | 7 | if (item_type == interrogate_type_command) { |
2608 | | /* loop on the commands */ |
2609 | 181 | for (j = 0; j < count; j++) { |
2610 | | |
2611 | | /* display the commands to be checked */ |
2612 | 176 | proto_tree_add_item(ecmp_interrogate_message_tree, hf_ecmp_interrogate_command, tvb, offset, 1, ENC_NA); |
2613 | 176 | offset += 1; |
2614 | 176 | } |
2615 | 5 | proto_item_set_len(ecmp_interrogate_message_item, count); |
2616 | | |
2617 | 5 | } else { |
2618 | 2 | expert_add_info(pinfo, ecmp_interrogate_message_item, &ei_ecmp_options_not_implemented); |
2619 | 2 | } |
2620 | | |
2621 | 7 | } else { |
2622 | | /* identify the ECMP command we're dissecting */ |
2623 | 3 | ecmp_interrogate_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 2, ett_ecmp_interrogate_message, NULL, "Interrogate: (Response)"); |
2624 | | |
2625 | | /* read the item_type (command/option setting) */ |
2626 | 3 | item_type = tvb_get_uint8(tvb, offset); |
2627 | 3 | offset += 1; |
2628 | | |
2629 | | /* read the count */ |
2630 | 3 | count = tvb_get_uint8(tvb, offset); |
2631 | 3 | offset += 1; |
2632 | | |
2633 | | /* display the item_codes (commands to be checked) */ |
2634 | 3 | if (item_type == interrogate_type_command) { |
2635 | | |
2636 | | /*create the interrogate details sub-tree */ |
2637 | 2 | ecmp_interrogate_message_tree = proto_tree_add_subtree(ecmp_interrogate_tree, tvb, offset, 1, ett_ecmp_interrogate_message, &ecmp_interrogate_message_item, "ECMP Commands Supported"); |
2638 | | |
2639 | | /* loop on the commands */ |
2640 | 98 | for (j = 0; j < count; j++) { |
2641 | | /* get the command code */ |
2642 | 96 | command_req = tvb_get_uint8(tvb, offset); |
2643 | 96 | offset += 1; |
2644 | | |
2645 | | /* get the support status */ |
2646 | 96 | supported = tvb_get_uint8(tvb, offset); |
2647 | 96 | offset += 1; |
2648 | | |
2649 | | /* display if the command is supported */ |
2650 | 96 | proto_tree_add_uint_format(ecmp_interrogate_message_tree, hf_ecmp_interrogate_command, tvb, offset, 1, command_req, "%s: %s", |
2651 | 96 | try_val_to_str(command_req, command_vals), |
2652 | 96 | try_val_to_str(supported, Interrogate_support_state)); |
2653 | 96 | } |
2654 | | |
2655 | 2 | } else { |
2656 | | |
2657 | 1 | expert_add_info(pinfo, ecmp_interrogate_message_item, &ei_ecmp_options_not_implemented); |
2658 | 1 | } |
2659 | 3 | } |
2660 | 10 | } |
2661 | | |
2662 | | |
2663 | | static void tunnel_frame(unsigned offset, bool request, tvbuff_t *tvb, proto_tree* ecmp_tree) |
2664 | 1 | { |
2665 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_tunnel_control, tvb, offset, 1, ENC_BIG_ENDIAN); |
2666 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_tunnel_start_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
2667 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_tunnel_end_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
2668 | | |
2669 | | /* if a request add the check output flag */ |
2670 | 1 | if (request) { |
2671 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_tunnel_check_output_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
2672 | 1 | } |
2673 | | |
2674 | 1 | offset+= 1; |
2675 | | |
2676 | | /* Payload length */ |
2677 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_tunnel_size, tvb, offset, 2, ENC_BIG_ENDIAN); |
2678 | 1 | offset+= 2; |
2679 | | |
2680 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); |
2681 | | /*offset = tvb_reported_length(tvb);*/ |
2682 | 1 | } |
2683 | | |
2684 | | |
2685 | | /* dissect_ecmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
2686 | | * ----------------------------------------------------------------- |
2687 | | * |
2688 | | * Purpose: Wireshark dissector for Emerson Control Techniques ECMP protocol |
2689 | | * |
2690 | | * |
2691 | | * Inputs: tvbuff_t *tvb - complex buffer structure holding the packet's bytes |
2692 | | * packet_info *pinfo - structure holding information about the packet |
2693 | | * proto_tree *tree - pointer to top-level tree (print lines) |
2694 | | * |
2695 | | * Outputs: none |
2696 | | * |
2697 | | * |
2698 | | * Notes: if tree = NULL, packet capture is running and dissector will only write into the Summary Line (Info Field) |
2699 | | * |
2700 | | * if tree is non-NULL, packet capture has stopped because a packet has been selected (clicked) |
2701 | | * In this case, we will display quite a bit of additional information about the packet. |
2702 | | * |
2703 | | * |
2704 | | * To inspect the frame buffer (very difficult using the *tvb pointer), it's best to add this little debug |
2705 | | * code snippet at the top of the program to copy the frame buffer into an array that you can inspect. |
2706 | | * |
2707 | | * static uint8_t jimbuf[512]; // temp buffer for current frame data |
2708 | | * static int lenframe = 0; // num bytes in the frame |
2709 | | * static int j = 0; // loop counter |
2710 | | * static int16_t saved_offset = 0; // saves offset for later restoration |
2711 | | * |
2712 | | * lenframe = tvb_captured_length(tvb); // get the length of the frame |
2713 | | * saved_offset = offset; // temporarily save the "offset" |
2714 | | * |
2715 | | * for (j = 0; j < lenframe; j++) { // loop to copy the frame buffer |
2716 | | * jimbuf[j] = tvb_get_uint8(tvb, offset); // Wireshark function to read the frame buffer |
2717 | | * offset += 1; |
2718 | | * } |
2719 | | * offset = saved_offset; // restore the offset |
2720 | | * |
2721 | | * |
2722 | | * Authors: Sarah Bouremoum, Jim Lynch, Luke Orehawa, Others |
2723 | | */ |
2724 | | |
2725 | | static int dissect_ecmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
2726 | 334 | { |
2727 | | /* Initialize the items and trees*/ |
2728 | 334 | proto_item *ecmp_item = NULL; |
2729 | 334 | proto_item *ecmp_transaction_id_item = NULL; |
2730 | 334 | proto_item *ecmp_chunk_id_item = NULL; |
2731 | 334 | proto_tree *ecmp_tree = NULL; |
2732 | | |
2733 | | /*initialise the values to be used */ |
2734 | 334 | uint8_t command_value = 0; |
2735 | 334 | bool request; |
2736 | 334 | uint8_t transaction_id_value = 0; |
2737 | 334 | int offset = 0; /* index used to read data from the buffer*/ |
2738 | 334 | int framelen = 0; /* number of bytes in the frame */ |
2739 | | |
2740 | | /* note length of the UDP frame */ |
2741 | 334 | framelen = tvb_reported_length(tvb); |
2742 | | |
2743 | 334 | if (framelen < ecmp_min_packet_size) { |
2744 | 6 | return 0; |
2745 | 6 | } |
2746 | | |
2747 | | /* this code block processes ECMP TCP messages (most of them) */ |
2748 | 328 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ECMP"); |
2749 | 328 | col_clear(pinfo->cinfo,COL_INFO); |
2750 | | |
2751 | | |
2752 | | /*declaration of variables*/ |
2753 | 328 | offset = 4; |
2754 | | |
2755 | | /*display the first line of the tree (ECMP data)*/ |
2756 | 328 | ecmp_item = proto_tree_add_item(tree, proto_ecmp, tvb, 0, -1, ENC_NA); |
2757 | 328 | ecmp_tree = proto_item_add_subtree(ecmp_item, ett_ecmp); |
2758 | | |
2759 | | /* display the information for the destination address */ |
2760 | 328 | offset = add_transport_layer_frame(offset, tvb, ecmp_tree, hf_ecmp_destination_address); |
2761 | | |
2762 | | /* display the information for the source address */ |
2763 | 328 | offset = add_transport_layer_frame(offset, tvb, ecmp_tree, hf_ecmp_source_address); |
2764 | | |
2765 | | /*display the transaction ID*/ |
2766 | 328 | ecmp_transaction_id_item = proto_tree_add_item(ecmp_tree, hf_ecmp_transaction_id, tvb, offset, 1, ENC_BIG_ENDIAN ); |
2767 | 328 | transaction_id_value = tvb_get_uint8(tvb, offset); |
2768 | | |
2769 | 328 | if(transaction_id_value == 0) { |
2770 | 54 | proto_item_append_text(ecmp_transaction_id_item, "%s", " -> Not initiated by Request"); |
2771 | 54 | } |
2772 | 328 | offset++; |
2773 | | |
2774 | 328 | request = ((tvb_get_uint8(tvb, offset+2) & 0x80) == 0); |
2775 | 328 | if (request) { |
2776 | | /* Calls the function to display the Response size */ |
2777 | 212 | offset = get_response_size(offset, tvb, ecmp_tree); |
2778 | | |
2779 | | /* Calls the function to display the command and request/response */ |
2780 | 212 | offset = add_command_codes(pinfo, offset, tvb, ecmp_tree, transaction_id_value, &command_value); |
2781 | | |
2782 | | /* Calls the function to display the option codes and its data */ |
2783 | 212 | offset = add_option_codes(offset, pinfo, tvb, ecmp_tree); |
2784 | | |
2785 | | /* up til here all code for the request should be the same */ |
2786 | 212 | switch(command_value) |
2787 | 212 | { |
2788 | 21 | case ECMP_COMMAND_IDENTIFY: |
2789 | | /*Calls a method to display the attributes and its data */ |
2790 | 21 | add_attributes(pinfo, offset, tvb, ecmp_tree, request); |
2791 | 21 | break; |
2792 | 2 | case ECMP_COMMAND_INFO: |
2793 | | /* Info command is just the request code, nothing else to display */ |
2794 | 2 | proto_tree_add_item(ecmp_tree, hf_ecmp_info_command, tvb, 0, -1, ENC_NA); |
2795 | | /*do nothing, no more data is present */ |
2796 | 2 | break; |
2797 | 7 | case ECMP_COMMAND_INTERROGATE: |
2798 | 7 | interrogate(pinfo, offset, request, tvb, ecmp_tree); |
2799 | 7 | break; |
2800 | 9 | case ECMP_COMMAND_READ: |
2801 | 9 | get_parameter_definitions(pinfo, offset, command_value, tvb, ecmp_tree); |
2802 | 9 | break; |
2803 | 2 | case ECMP_COMMAND_READWITHTYPE: |
2804 | 2 | get_parameter_definitions(pinfo, offset, command_value, tvb, ecmp_tree); |
2805 | 2 | break; |
2806 | 39 | case ECMP_COMMAND_WRITE: |
2807 | 39 | get_parameter_definitions(pinfo, offset, command_value, tvb, ecmp_tree); |
2808 | 39 | break; |
2809 | 3 | case ECMP_COMMAND_OBJECTINFO: |
2810 | 3 | get_parameter_definitions(pinfo, offset, command_value, tvb, ecmp_tree); |
2811 | 3 | break; |
2812 | 0 | case ECMP_COMMAND_GETNEXTOBJECTS: |
2813 | 0 | get_parameter_definitions(pinfo, offset, command_value, tvb, ecmp_tree); |
2814 | 0 | break; |
2815 | 2 | case ECMP_COMMAND_FILEOPEN: |
2816 | 2 | file_open(offset, request, tvb, ecmp_tree); |
2817 | 2 | break; |
2818 | 0 | case ECMP_COMMAND_FILEREAD: |
2819 | 0 | file_read(offset, request, tvb, ecmp_tree); |
2820 | 0 | break; |
2821 | 0 | case ECMP_COMMAND_FILEWRITE: |
2822 | 0 | file_write(offset, request, tvb, ecmp_tree); |
2823 | 0 | break; |
2824 | 1 | case ECMP_COMMAND_FILECLOSE: |
2825 | 1 | file_close(offset, request, tvb, ecmp_tree); |
2826 | 1 | break; |
2827 | 4 | case ECMP_COMMAND_FILEINFO: |
2828 | 4 | file_info(pinfo, offset, request, tvb, ecmp_tree); |
2829 | 4 | break; |
2830 | 1 | case ECMP_COMMAND_FILEDELETE: |
2831 | 1 | file_state_delete(offset, request, tvb, ecmp_tree); |
2832 | 1 | break; |
2833 | 2 | case ECMP_COMMAND_FILESTATE: |
2834 | 2 | file_state_delete(offset, request, tvb, ecmp_tree); |
2835 | 2 | break; |
2836 | 1 | case ECMP_COMMAND_FILEPOS: |
2837 | 1 | file_pos(offset, request, tvb, ecmp_tree); |
2838 | 1 | break; |
2839 | 2 | case ECMP_COMMAND_FILELIST: |
2840 | 2 | file_list(pinfo, offset, request, tvb, ecmp_tree); |
2841 | 2 | break; |
2842 | 0 | case ECMP_COMMAND_FILEEXISTS: |
2843 | 0 | file_exists(offset, request, tvb, ecmp_tree); |
2844 | 0 | break; |
2845 | 107 | case ECMP_COMMAND_CYCLICLINK: |
2846 | 107 | cyclic_setup(pinfo, offset, request, tvb, ecmp_tree); |
2847 | 107 | break; |
2848 | 1 | case ECMP_COMMAND_PROGRAMCONTROL: |
2849 | 1 | program_control(offset, request, tvb, ecmp_tree); |
2850 | 1 | break; |
2851 | 2 | case ECMP_COMMAND_PROGRAMSTATUS: |
2852 | 2 | program_status(offset, request, tvb, ecmp_tree); |
2853 | 2 | break; |
2854 | 0 | case ECMP_COMMAND_CYCLICFRAME: |
2855 | 0 | add_cyclic_frame_query(offset, tvb, ecmp_tree); |
2856 | 0 | break; |
2857 | 1 | case ECMP_COMMAND_TUNNELFRAME: |
2858 | 1 | tunnel_frame(offset, command_value, tvb, ecmp_tree); |
2859 | 1 | break; |
2860 | 1 | case ECMP_COMMAND_MODBUSPDU: |
2861 | 1 | modbus_pdu(offset, request, tvb, pinfo, ecmp_tree); |
2862 | 1 | break; |
2863 | 2 | default: |
2864 | 2 | proto_tree_add_expert_remaining(ecmp_tree, pinfo, &ei_ecmp_unknown_command, tvb, 0); |
2865 | 2 | break; |
2866 | 212 | } |
2867 | | |
2868 | | /* END of code to be modified */ |
2869 | 212 | } else { |
2870 | 116 | uint8_t chunk_id_value = 0; |
2871 | 116 | int8_t status_value = 0; |
2872 | | |
2873 | 116 | status_value = tvb_get_int8(tvb, offset); /*stores a signed value for status */ |
2874 | | |
2875 | 116 | proto_tree_add_item(ecmp_tree, hf_ecmp_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
2876 | | |
2877 | | |
2878 | 116 | if (status_value >= 0) { |
2879 | 113 | offset++; |
2880 | 113 | chunk_id_value = tvb_get_uint8(tvb, offset); |
2881 | 113 | ecmp_chunk_id_item = proto_tree_add_item(ecmp_tree, hf_ecmp_chunk_id, tvb, offset, 1, ENC_BIG_ENDIAN); |
2882 | | |
2883 | 113 | if(chunk_id_value == 0) { |
2884 | 43 | proto_item_append_text(ecmp_chunk_id_item, "%s", " -> Response is NOT Chunked"); |
2885 | 43 | } |
2886 | | |
2887 | 113 | offset++; |
2888 | | |
2889 | | /* Calls the function to display the option codes */ |
2890 | 113 | offset = add_command_codes(pinfo, offset, tvb, ecmp_tree, transaction_id_value, &command_value); |
2891 | | |
2892 | 113 | if ((status_value == 0) || (status_value == 1)) { |
2893 | | /* Calls a method to display option codes */ |
2894 | 111 | offset = add_option_codes(offset, pinfo, tvb, ecmp_tree); |
2895 | | |
2896 | | /* up til here all code for the response should be the same */ |
2897 | 111 | switch(command_value) |
2898 | 111 | { |
2899 | 21 | case ECMP_COMMAND_IDENTIFY: |
2900 | | /*Call a method to add category data */ |
2901 | 21 | offset = add_category_codes(offset, tvb, ecmp_tree); |
2902 | | /*Call a method to add attributes */ |
2903 | 21 | add_attributes(pinfo, offset, tvb, ecmp_tree, request); |
2904 | 21 | break; |
2905 | 4 | case ECMP_COMMAND_INFO: |
2906 | 4 | add_info_response(offset, tvb, ecmp_tree); |
2907 | 4 | break; |
2908 | 3 | case ECMP_COMMAND_INTERROGATE: |
2909 | 3 | interrogate(pinfo, offset, request, tvb, ecmp_tree); |
2910 | 3 | break; |
2911 | 12 | case ECMP_COMMAND_READ: |
2912 | 12 | get_parameter_responses(pinfo, offset, command_value, tvb, ecmp_tree); |
2913 | 12 | break; |
2914 | 20 | case ECMP_COMMAND_READWITHTYPE: |
2915 | 20 | get_parameter_responses(pinfo, offset, command_value, tvb, ecmp_tree); |
2916 | 20 | break; |
2917 | 1 | case ECMP_COMMAND_WRITE: |
2918 | 1 | get_parameter_responses(pinfo, offset, command_value, tvb, ecmp_tree); |
2919 | 1 | break; |
2920 | 22 | case ECMP_COMMAND_OBJECTINFO: |
2921 | 22 | get_object_info_response(pinfo, offset, tvb, ecmp_tree); |
2922 | 22 | break; |
2923 | 3 | case ECMP_COMMAND_GETNEXTOBJECTS: |
2924 | 3 | get_parameter_responses(pinfo, offset, command_value, tvb, ecmp_tree); |
2925 | 3 | break; |
2926 | 0 | case ECMP_COMMAND_FILEOPEN: |
2927 | 0 | file_open(offset, request, tvb, ecmp_tree); |
2928 | 0 | break; |
2929 | 0 | case ECMP_COMMAND_FILEREAD: |
2930 | 0 | file_read(offset, request, tvb, ecmp_tree); |
2931 | 0 | break; |
2932 | 0 | case ECMP_COMMAND_FILEWRITE: |
2933 | 0 | file_write(offset, request, tvb, ecmp_tree); |
2934 | 0 | break; |
2935 | 0 | case ECMP_COMMAND_FILECLOSE: |
2936 | 0 | file_close(offset, request, tvb, ecmp_tree); |
2937 | 0 | break; |
2938 | 15 | case ECMP_COMMAND_FILEINFO: |
2939 | 15 | file_info(pinfo, offset, request, tvb, ecmp_tree); |
2940 | 15 | break; |
2941 | 0 | case ECMP_COMMAND_FILEDELETE: |
2942 | 0 | file_state_delete(offset, request, tvb, ecmp_tree); |
2943 | 0 | break; |
2944 | 1 | case ECMP_COMMAND_FILESTATE: |
2945 | 1 | file_state_delete(offset, request, tvb, ecmp_tree); |
2946 | 1 | break; |
2947 | 0 | case ECMP_COMMAND_FILEPOS: |
2948 | 0 | file_pos(offset, request, tvb, ecmp_tree); |
2949 | 0 | break; |
2950 | 3 | case ECMP_COMMAND_FILELIST: |
2951 | 3 | file_list(pinfo, offset, request, tvb, ecmp_tree); |
2952 | 3 | break; |
2953 | 0 | case ECMP_COMMAND_FILEEXISTS: |
2954 | 0 | file_exists(offset, request, tvb, ecmp_tree); |
2955 | 0 | break; |
2956 | 1 | case ECMP_COMMAND_CYCLICLINK: |
2957 | 1 | cyclic_setup(pinfo, offset, request, tvb, ecmp_tree); |
2958 | 1 | break; |
2959 | 0 | case ECMP_COMMAND_PROGRAMCONTROL: |
2960 | 0 | program_control(offset, request, tvb, ecmp_tree); |
2961 | 0 | break; |
2962 | 0 | case ECMP_COMMAND_PROGRAMSTATUS: |
2963 | 0 | program_status(offset, request, tvb, ecmp_tree); |
2964 | 0 | break; |
2965 | 1 | case ECMP_COMMAND_CYCLICFRAME: |
2966 | 1 | add_cyclic_frame(offset, tvb, ecmp_tree); |
2967 | 1 | break; |
2968 | 0 | case ECMP_COMMAND_TUNNELFRAME: |
2969 | 0 | tunnel_frame(offset, command_value, tvb, ecmp_tree); |
2970 | 0 | break; |
2971 | 1 | case ECMP_COMMAND_MODBUSPDU: |
2972 | 1 | modbus_pdu(offset, request, tvb, pinfo, ecmp_tree); |
2973 | 1 | break; |
2974 | 2 | default: |
2975 | 2 | proto_tree_add_expert_remaining(ecmp_tree, pinfo, &ei_ecmp_unknown_command, tvb, 0); |
2976 | 2 | break; |
2977 | 111 | } |
2978 | | /********************************* END of code to be modified ***********************************/ |
2979 | 111 | } |
2980 | 113 | } |
2981 | 116 | } |
2982 | | |
2983 | 128 | return framelen; |
2984 | 328 | } |
2985 | | |
2986 | | /* this code block processes ECMP UDP messages (cyclic data) */ |
2987 | | static int dissect_ecmp_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
2988 | 17 | { |
2989 | 17 | proto_item *ecmp_item = NULL; |
2990 | 17 | proto_tree *ecmp_tree = NULL; |
2991 | 17 | proto_tree *ecmp_cyclic_data_32_bit_display_tree = NULL; |
2992 | 17 | proto_tree *ecmp_cyclic_data_16_bit_display_tree = NULL; |
2993 | 17 | proto_tree *ecmp_cyclic_data_8_bit_display_tree = NULL; |
2994 | 17 | uint8_t command_value = 0; |
2995 | 17 | uint8_t type_value = 0; |
2996 | 17 | uint8_t transaction_id_value = 0; |
2997 | 17 | uint16_t offset = 0; /* index used to read data from the buffer*/ |
2998 | 17 | int framelen = 0; /* number of bytes in the frame */ |
2999 | 17 | uint8_t scheme = 0; /* 0=no scheme, 1=grandmaster setup */ |
3000 | | |
3001 | | /* note length of the UDP frame */ |
3002 | 17 | framelen = tvb_reported_length(tvb); |
3003 | | |
3004 | 17 | if (framelen < ecmp_min_packet_size) { |
3005 | 2 | return 0; |
3006 | 2 | } |
3007 | | |
3008 | | /* display the "ECMP" protocol indication in the PROTOCOL field */ |
3009 | 15 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ECMP"); |
3010 | | |
3011 | | /* Clear out stuff in the info column */ |
3012 | 15 | col_clear(pinfo->cinfo,COL_INFO); |
3013 | | |
3014 | | /* adjust offset to point at transaction ID */ |
3015 | 15 | offset += 2; |
3016 | | |
3017 | | /*getting the information from the buffer*/ |
3018 | 15 | transaction_id_value = tvb_get_uint8(tvb, offset); |
3019 | | |
3020 | | /* adjust offset to point at ECMP query/response code */ |
3021 | 15 | offset += 3; |
3022 | | |
3023 | | /* calculate if it's a query or response (type_r_r) */ |
3024 | 15 | type_value = tvb_get_uint8(tvb, offset); |
3025 | | |
3026 | | /* determine the ECMP command code */ |
3027 | 15 | command_value = type_value & 0x7f; |
3028 | | |
3029 | | /* update offset to point to cyclic link number */ |
3030 | 15 | offset += 2; |
3031 | | |
3032 | | /* Information displayed in the Info column*/ |
3033 | 15 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s, %s. Transaction ID: %d", |
3034 | 15 | val_to_str(pinfo->pool, command_value, command_vals, "Unknown Type:0x%02x"), |
3035 | 15 | tfs_get_string((type_value & 0x80) >> 7, &tfs_response_request), |
3036 | 15 | transaction_id_value); |
3037 | | |
3038 | | /*display the first line of the tree (ECMP data)*/ |
3039 | 15 | ecmp_item = proto_tree_add_item(tree, proto_ecmp, tvb, 0, -1, ENC_NA); /*item created*/ |
3040 | 15 | ecmp_tree = proto_item_add_subtree(ecmp_item, ett_ecmp); /*tree created*/ |
3041 | | |
3042 | | /* indicate cyclic link message */ |
3043 | 15 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_link_req_resp, tvb, offset, 1, ENC_BIG_ENDIAN); |
3044 | | |
3045 | | /* display the cyclic link number */ |
3046 | 15 | proto_tree_add_item(ecmp_tree, hf_ecmp_cyclic_link_number_display, tvb, offset, 1, ENC_BIG_ENDIAN); |
3047 | 15 | offset += 1; |
3048 | | |
3049 | 15 | if (type_value & 0x80) { |
3050 | | /* response data handled here */ |
3051 | | /* display the alignment */ |
3052 | 13 | proto_tree_add_item(ecmp_tree, hf_ecmp_udp_alignment, tvb, offset, 1, ENC_NA); |
3053 | 13 | offset += 1; |
3054 | | |
3055 | | /* display the scheme */ |
3056 | 13 | proto_tree_add_item_ret_uint8(ecmp_tree, hf_ecmp_udp_scheme, tvb, offset, 1, ENC_NA, &scheme); |
3057 | 13 | offset += 1; |
3058 | | |
3059 | | /* if the scheme is 1, there is grandmaster data to be printed */ |
3060 | 13 | if (scheme == 1) { |
3061 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_grandmaster, tvb, offset, 8, ENC_BIG_ENDIAN); |
3062 | 1 | offset += 8; |
3063 | | |
3064 | 1 | proto_tree_add_item(ecmp_tree, hf_ecmp_process_time, tvb, offset, 8, ENC_BIG_ENDIAN); |
3065 | 1 | offset += 8; |
3066 | 1 | } |
3067 | | |
3068 | | /* create the Cyclic Data Display (uint32_t format) sub-tree */ |
3069 | 13 | ecmp_cyclic_data_32_bit_display_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 2, ett_ecmp_cyclic_data_32_bit_display, NULL, |
3070 | 13 | "Cyclic Data (32-bit hex unsigned format): "); |
3071 | | |
3072 | | /* display the raw hex data for the cyclic data in a 32-bit format */ |
3073 | 13 | display_raw_cyclic_data(cyclic_display_long_format, offset, framelen - offset, tvb, pinfo, ecmp_cyclic_data_32_bit_display_tree); |
3074 | | |
3075 | | /* create the Cyclic Data Display (uint16_t format) sub-tree */ |
3076 | 13 | ecmp_cyclic_data_16_bit_display_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 2, ett_ecmp_cyclic_data_16_bit_display, NULL, |
3077 | 13 | "Cyclic Data (16-bit hex unsigned format): "); |
3078 | | |
3079 | | /* display the raw hex data for the cyclic data in a 16-bit format */ |
3080 | 13 | display_raw_cyclic_data(cyclic_display_word_format, offset, framelen - offset, tvb, pinfo, ecmp_cyclic_data_16_bit_display_tree); |
3081 | | |
3082 | | /* display the raw hex data for the cyclic data in a uint8_t format */ |
3083 | 13 | ecmp_cyclic_data_8_bit_display_tree = proto_tree_add_subtree(ecmp_tree, tvb, offset, 2, ett_ecmp_cyclic_data_8_bit_display, NULL, |
3084 | 13 | "Cyclic Data (8-bit hex unsigned format): "); |
3085 | | |
3086 | | /* display the raw hex data for the cyclic data in 8-bit format */ |
3087 | 13 | display_raw_cyclic_data(cyclic_display_byte_format, offset, framelen - offset, tvb, pinfo, ecmp_cyclic_data_8_bit_display_tree); |
3088 | 13 | } |
3089 | | |
3090 | 15 | return tvb_reported_length(tvb); |
3091 | 17 | } |
3092 | | |
3093 | | /* Function to register the protocol */ |
3094 | | /* Wireshark literally scans this file (packet-ecmp.c) to find this function */ |
3095 | | /* note: this function MUST start in column 1, due to the scanning mentioned above */ |
3096 | | void proto_register_ecmp (void) |
3097 | 14 | { |
3098 | | /* A header field is something you can search/filter on. |
3099 | | * |
3100 | | * We create a structure to register our fields. It consists of an |
3101 | | * array of hf_register_info structures, each of which are of the format |
3102 | | * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}. |
3103 | | */ |
3104 | | |
3105 | 14 | static hf_register_info hf[] = { |
3106 | | |
3107 | 14 | { &hf_ecmp_destination_address, |
3108 | 14 | { "Destination Address scheme", "ecmp.destination_address", FT_UINT8, BASE_DEC, VALS(address_scheme), 0, NULL, HFILL }}, |
3109 | | |
3110 | 14 | { &hf_ecmp_source_address, |
3111 | 14 | { "Source Address scheme", "ecmp.source_address", FT_UINT8, BASE_DEC, VALS(address_scheme), 0, NULL, HFILL }}, |
3112 | | |
3113 | 14 | { &hf_ecmp_diagnostic, |
3114 | 14 | { "Diagnostic group", "ecmp.diagnostic", FT_UINT8, BASE_DEC, VALS(diagnostic), 0, NULL, HFILL }}, |
3115 | | |
3116 | 14 | { &hf_ecmp_command, |
3117 | 14 | { "Command", "ecmp.command", FT_UINT8, BASE_DEC, VALS(command_vals), 0x7F, NULL, HFILL }}, |
3118 | | |
3119 | 14 | { &hf_ecmp_option, |
3120 | 14 | { "Option", "ecmp.option", FT_UINT8, BASE_DEC, VALS(option_code), 0x0, NULL, HFILL }}, |
3121 | | |
3122 | 14 | { &hf_ecmp_type_rr, |
3123 | 14 | { "Type", "ecmp.type", FT_BOOLEAN, 8, TFS(&tfs_response_request), 0x80, "ECMP Type (request/response)", HFILL }}, |
3124 | | |
3125 | 14 | { &hf_ecmp_chunking, |
3126 | 14 | { "Chunks allowed","ecmp.chunking", FT_UINT16, BASE_DEC, NULL,0xF000, "ECMP number of chunks allowed", HFILL}}, |
3127 | | |
3128 | 14 | { &hf_ecmp_max_response_size, |
3129 | 14 | { "Maximum Response Size","ecmp.response_size", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0FFF, NULL, HFILL}}, |
3130 | | |
3131 | 14 | { &hf_ecmp_category, |
3132 | 14 | { "Device", "ecmp.category", FT_UINT8, BASE_DEC, VALS(category), 0x0, "ECMP Category (drive or option module)", HFILL }}, |
3133 | | |
3134 | 14 | { &hf_ecmp_attribute, |
3135 | 14 | { "Attribute", "ecmp.attribute", FT_UINT8, BASE_DEC, VALS(attribute), 0x0, NULL, HFILL }}, |
3136 | | |
3137 | 14 | { &hf_ecmp_no_of_attributes, |
3138 | 14 | { "Number of attributes", "ecmp.attribute_number", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3139 | | |
3140 | 14 | { &hf_ecmp_status, |
3141 | 14 | { "Status", "ecmp.status", FT_INT8, BASE_DEC, VALS(status), 0x0, NULL, HFILL }}, |
3142 | | |
3143 | 14 | { &hf_ecmp_chunk_id, |
3144 | 14 | { "Chunk ID", "ecmp.chunkID", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3145 | | |
3146 | 14 | { &hf_ecmp_transaction_id, |
3147 | 14 | { "Transaction ID", "ecmp.transactionID", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3148 | | |
3149 | 14 | { &hf_ecmp_drive_type, |
3150 | 14 | { "Product Type", "ecmp.drive_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3151 | | |
3152 | 14 | { &hf_ecmp_drive_derivative, |
3153 | 14 | { "Drive Derivative", "ecmp.drive_derivative", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3154 | | |
3155 | 14 | { &hf_ecmp_drive_factory_fit_category_id, |
3156 | 14 | { "Factory Fitted Option ID", "ecmp.drive_factory_fit_category_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3157 | | |
3158 | 14 | { &hf_ecmp_category_id, |
3159 | 14 | { "Option ID", "ecmp.category_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3160 | | |
3161 | 14 | { &hf_ecmp_cyclic_link_num, |
3162 | 14 | { "Cyclic Link Number", "ecmp.link_num", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3163 | | |
3164 | 14 | { &hf_ecmp_cyclic_align, |
3165 | 14 | { "Alignment", "ecmp.cyclic_align", FT_UINT8, BASE_DEC, VALS(cyclic_align), 0x0, "ECMP Cyclic Data Alignment", HFILL }}, |
3166 | | |
3167 | 14 | { &hf_ecmp_cyclic_scheme, |
3168 | 14 | { "Scheme", "ecmp.cyclic_scheme", FT_UINT8, BASE_DEC, VALS(cyclic_scheme), 0x0, "ECMP Cyclic Scheme", HFILL }}, |
3169 | | |
3170 | 14 | { &hf_ecmp_cyclic_link_number_display, |
3171 | 14 | { "Cyclic Link Number Display", "ecmp.link_num_display", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3172 | | |
3173 | 14 | { &hf_ecmp_buffer_size, |
3174 | 14 | {"Buffer Size", "ecmp.buffer_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
3175 | | |
3176 | 14 | { &hf_ecmp_max_response, |
3177 | 14 | {"Maximum Response Time", "ecmp.max_response", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
3178 | | |
3179 | 14 | { &hf_ecmp_max_handle, |
3180 | 14 | {"Maximum Handle Period", "ecmp.max_handle", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
3181 | | |
3182 | 14 | { &hf_ecmp_info_address, |
3183 | 14 | {"Number of Default Route Addresses", "ecmp.count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
3184 | | |
3185 | 14 | { &hf_ecmp_parameter_address, |
3186 | 14 | {"Parameter Addressing Scheme", "ecmp.parameter.address", FT_UINT8, BASE_DEC, VALS(parameter_address_scheme), 0x0, NULL, HFILL}}, |
3187 | | |
3188 | 14 | { &hf_ecmp_number_of_parameter_definitions, |
3189 | 14 | {"Number of Parameter Definitions", "ecmp.parameter.definitions", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
3190 | | |
3191 | 14 | { &hf_ecmp_number_of_parameter_responses, |
3192 | 14 | {"Number of Parameter Responses", "ecmp.parameter.response", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
3193 | | |
3194 | 14 | { &hf_ecmp_parameter_status, |
3195 | 14 | {"Parameter Status", "ecmp.parameter.status", FT_INT8, BASE_DEC, VALS(parameter_access_status), 0x0, NULL, HFILL}}, |
3196 | | |
3197 | 14 | { &hf_ecmp_data_type, |
3198 | 14 | {"Parameter Data Type", "ecmp.parameter.data_type", FT_UINT8, BASE_DEC, VALS(parameter_data_types), 0x0, NULL, HFILL}}, |
3199 | | |
3200 | 14 | { &hf_ecmp_info_type, |
3201 | 14 | {"Info Type", "ecmp.info_type", FT_UINT8, BASE_DEC, VALS(info_type), 0x0, NULL, HFILL}}, |
3202 | | |
3203 | 14 | { &hf_ecmp_file_status, |
3204 | 14 | {"File Status", "ecmp.file.status", FT_INT8, BASE_DEC, VALS(file_status), 0x0, NULL, HFILL}}, |
3205 | | |
3206 | 14 | { &hf_ecmp_file_handle, |
3207 | 14 | {"File Handle", "ecmp.file.handle", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
3208 | | |
3209 | 14 | { &hf_ecmp_file_attributes, |
3210 | 14 | {"Attribute", "ecmp.file.attribute", FT_UINT8, BASE_DEC, VALS(file_attributes), 0x0, "File attributes", HFILL}}, |
3211 | | |
3212 | 14 | { &hf_ecmp_file_ref_point, |
3213 | 14 | {"Reference Point", "ecmp.file.reference", FT_UINT8, BASE_DEC, VALS(file_ref_point), 0x0, "File reference points", HFILL}}, |
3214 | | |
3215 | 14 | { &hf_ecmp_tunnel_control, |
3216 | 14 | {"Control", "ecmp.tunnel_control", FT_UINT8, BASE_DEC, NULL, 0x0, "Tunnel frame control field", HFILL}}, |
3217 | | |
3218 | 14 | { &hf_ecmp_tunnel_start_flag, |
3219 | 14 | {"Start", "ecmp.tunnel_control.start", FT_BOOLEAN, 8, NULL, TUNNEL_START_FLAG, "Tunnel frame control field start flag", HFILL}}, |
3220 | | |
3221 | 14 | { &hf_ecmp_tunnel_end_flag, |
3222 | 14 | {"End", "ecmp.tunnel_control.end", FT_BOOLEAN, 8, NULL, TUNNEL_END_FLAG, "Tunnel frame control field end flag", HFILL}}, |
3223 | | |
3224 | 14 | { &hf_ecmp_tunnel_check_output_flag, |
3225 | 14 | {"Check Output", "ecmp.tunnel_control.check", FT_BOOLEAN, 8, NULL, TUNNEL_CHECK_OUTPUT_FLAG, "Tunnel frame control field check output flag", HFILL}}, |
3226 | | |
3227 | 14 | { &hf_ecmp_tunnel_size, |
3228 | 14 | {"Size", "ecmp.tunnel_size", FT_UINT16, BASE_DEC, NULL, 0x0, "Tunnel frame payload size", HFILL}}, |
3229 | | |
3230 | 14 | { &hf_ecmp_cyclic_setup_mode, |
3231 | 14 | {"Mode", "ecmp.cyclic_setup.mode", FT_UINT8, BASE_DEC, VALS(cyclic_setup_mode), 0x0, "Cyclic setup mode", HFILL}}, |
3232 | | |
3233 | 14 | { &hf_ecmp_cyclic_setup_linkno, |
3234 | 14 | {"Link No", "ecmp.cyclic_setup.linkno", FT_UINT8, BASE_DEC, NULL, 0x0, "Cyclic setup link no", HFILL}}, |
3235 | | |
3236 | 14 | { &hf_ecmp_cyclic_setup_dir, |
3237 | 14 | {"Direction", "ecmp.cyclic_setup.direction", FT_UINT8, BASE_DEC, VALS(cyclic_setup_link_dir), 0x0, "Cyclic setup link direction", HFILL}}, |
3238 | | |
3239 | 14 | { &hf_ecmp_cyclic_setup_attrib_count, |
3240 | 14 | {"Count", "ecmp.cyclic_setup.attrib_count", FT_UINT8, BASE_DEC, NULL, 0x0, "Cyclic setup attribute count", HFILL}}, |
3241 | | |
3242 | 14 | { &hf_ecmp_cyclic_setup_attrib, |
3243 | 14 | {"Attribute", "ecmp.cyclic_setup.attrib", FT_UINT8, BASE_DEC, VALS(cyclic_attributes), 0x0, "Cyclic setup attribute", HFILL}}, |
3244 | | |
3245 | 14 | { &hf_ecmp_cyclic_setup_rsp_status, |
3246 | 14 | {"Status", "ecmp.cyclic_setup.rsp_status", FT_INT8, BASE_DEC, NULL, 0x0, "Cyclic setup status", HFILL}}, |
3247 | | |
3248 | 14 | { &hf_ecmp_cyclic_setup_rsp_err_idx, |
3249 | 14 | {"Error Index", "ecmp.cyclic_setup.rsp_err_idx", FT_UINT8, BASE_DEC, NULL, 0x0, "Cyclic setup error index", HFILL}}, |
3250 | | |
3251 | 14 | { &hf_ecmp_cyclic_setup_link_exists, |
3252 | 14 | {"Existence State", "ecmp.cyclic_setup.exists.state", FT_UINT8, BASE_DEC, VALS(cyclic_setup_link_exists), 0x0, "Cyclic setup exists state", HFILL}}, |
3253 | | |
3254 | 14 | { &hf_ecmp_cyclic_link_req_resp, |
3255 | 14 | {"Cyclic Link - Request-Response", "ecmp.cyclic_link.request.response", FT_BOOLEAN, BASE_NONE, TFS(&tfs_response_request), 0x0, "Cyclic link request - response", HFILL}}, |
3256 | | |
3257 | 14 | { &hf_ecmp_attribute_string, |
3258 | 14 | { "Attribute string", "ecmp.attribute_string", FT_UINT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3259 | | |
3260 | 14 | { &hf_ecmp_file_name, |
3261 | 14 | { "File name", "ecmp.file_name", FT_UINT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3262 | | |
3263 | 14 | { &hf_ecmp_directory, |
3264 | 14 | { "Directory", "ecmp.directory", FT_UINT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3265 | | |
3266 | 14 | { &hf_ecmp_names_scheme, |
3267 | 14 | { "Names Scheme", "ecmp.names_scheme", FT_UINT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3268 | | |
3269 | 14 | { &hf_ecmp_variable_name, |
3270 | 14 | { "Variable name", "ecmp.variable_name", FT_UINT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3271 | | |
3272 | 14 | { &hf_ecmp_unit_id_string, |
3273 | 14 | { "Unit ID String", "ecmp.unit_id_string", FT_UINT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3274 | | |
3275 | 14 | { &hf_ecmp_ecmp_string, |
3276 | 14 | { "ECMP string", "ecmp.ecmp_string", FT_UINT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3277 | | |
3278 | 14 | { &hf_ecmp_info_command, |
3279 | 14 | { "Info command data", "ecmp.info_command", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3280 | | |
3281 | 14 | { &hf_ecmp_process_time, |
3282 | 14 | { "ProcessAt time", "ecmp.processat_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3283 | | |
3284 | 14 | { &hf_ecmp_cyclic_frame_time, |
3285 | 14 | { "Cyclic frame time", "ecmp.cyclic_frame_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3286 | | |
3287 | 14 | { &hf_ecmp_grandmaster, |
3288 | 14 | { "Grandmaster", "ecmp.grandmaster", FT_EUI64, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3289 | | |
3290 | 14 | { &hf_ecmp_data, |
3291 | 14 | { "Data", "ecmp.data", FT_BYTES, SEP_SPACE, NULL, 0x0, NULL, HFILL }}, |
3292 | | |
3293 | 14 | { &hf_ecmp_response_data, |
3294 | 14 | { "Response Data", "ecmp.response_data", FT_BYTES, SEP_SPACE, NULL, 0x0, NULL, HFILL }}, |
3295 | | |
3296 | | /* Generated from convert_proto_tree_add_text.pl */ |
3297 | 14 | { &hf_ecmp_physical_address, { "Physical address", "ecmp.physical_address", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }}, |
3298 | 14 | { &hf_ecmp_logical_address, { "Logical address", "ecmp.logical_address", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }}, |
3299 | 14 | { &hf_ecmp_primary_colour, { "Primary Colour", "ecmp.primary_colour", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
3300 | 14 | { &hf_ecmp_secondary_colour, { "Secondary Colour", "ecmp.secondary_colour", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
3301 | 14 | { &hf_ecmp_number_of_subsequent_object_requests, { "Number of subsequent object requests", "ecmp.number_of_subsequent_object_requests", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3302 | 14 | { &hf_ecmp_number_of_decimal_places, { "Number of decimal places", "ecmp.number_of_decimal_places", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3303 | 14 | { &hf_ecmp_no_information_available, { "No Information available", "ecmp.no_information_available", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3304 | 14 | { &hf_ecmp_param_format_bit_default_unipolar, { "BU- Bit default/Unipolar", "ecmp.param_format.bit_default_unipolar", FT_UINT32, BASE_DEC, NULL, 0x00000001, NULL, HFILL }}, |
3305 | 14 | { &hf_ecmp_param_format_write_allowed, { "W- Write allowed", "ecmp.param_format.write_allowed", FT_UINT32, BASE_DEC, NULL, 0x00000002, NULL, HFILL }}, |
3306 | 14 | { &hf_ecmp_param_format_read_not_allowed, { "NR- Read not allowed", "ecmp.param_format.read_not_allowed", FT_UINT32, BASE_DEC, NULL, 0x00000004, NULL, HFILL }}, |
3307 | 14 | { &hf_ecmp_param_format_protected_from_destinations, { "PT- Protected from destinations", "ecmp.param_format.protected_from_destinations", FT_UINT32, BASE_DEC, NULL, 0x00000008, NULL, HFILL }}, |
3308 | 14 | { &hf_ecmp_param_format_parameter_not_visible, { "NV- Parameter not visible", "ecmp.param_format.parameter_not_visible", FT_UINT32, BASE_DEC, NULL, 0x00000010, NULL, HFILL }}, |
3309 | 14 | { &hf_ecmp_param_format_not_clonable, { "NC- Not clonable", "ecmp.param_format.not_clonable", FT_UINT32, BASE_DEC, NULL, 0x00000020, NULL, HFILL }}, |
3310 | 14 | { &hf_ecmp_param_format_voltage_or_current_rating_dependent, { "RA- Voltage or current rating dependent", "ecmp.param_format.voltage_or_current_rating_dependent", FT_UINT32, BASE_DEC, NULL, 0x00000040, NULL, HFILL }}, |
3311 | 14 | { &hf_ecmp_param_format_parameter_has_no_default, { "ND- Parameter has no default", "ecmp.param_format.parameter_has_no_default", FT_UINT32, BASE_DEC, NULL, 0x00000080, NULL, HFILL }}, |
3312 | 14 | { &hf_ecmp_param_format_number_of_decimal_places, { "DP- Number of Decimal places", "ecmp.param_format.number_of_decimal_places", FT_UINT32, BASE_DEC, NULL, 0x00000F00, NULL, HFILL }}, |
3313 | 14 | { &hf_ecmp_param_format_variable_maximum_and_minimum, { "VM- Variable maximum and minimum", "ecmp.param_format.variable_maximum_and_minimum", FT_UINT32, BASE_DEC, NULL, 0x00001000, NULL, HFILL }}, |
3314 | 14 | { &hf_ecmp_param_format_string_parameter, { "TE- String parameter", "ecmp.param_format.string_parameter", FT_UINT32, BASE_DEC, NULL, 0x00002000, NULL, HFILL }}, |
3315 | 14 | { &hf_ecmp_param_format_destination_set_up_parameter, { "DE- destination set-up parameter", "ecmp.param_format.destination_set_up_parameter", FT_UINT32, BASE_DEC, NULL, 0x00004000, NULL, HFILL }}, |
3316 | 14 | { &hf_ecmp_param_format_filtered_when_displayed, { "FI- Filtered when displayed", "ecmp.param_format.filtered_when_displayed", FT_UINT32, BASE_DEC, NULL, 0x00008000, NULL, HFILL }}, |
3317 | 14 | { &hf_ecmp_param_format_pseudo_read_only, { "PR- Pseudo read only", "ecmp.param_format.pseudo_read_only", FT_UINT32, BASE_DEC, NULL, 0x00010000, NULL, HFILL }}, |
3318 | 14 | { &hf_ecmp_param_format_display_format, { "DF- Display Format", "ecmp.param_format.display_format", FT_UINT32, BASE_DEC, VALS(display_format), 0x001E0000, NULL, HFILL }}, |
3319 | 14 | { &hf_ecmp_param_format_floating_point_value, { "FL- Floating point value", "ecmp.param_format.floating_point_value", FT_UINT32, BASE_DEC, NULL, 0x00200000, NULL, HFILL }}, |
3320 | 14 | { &hf_ecmp_param_format_units, { "UNITS", "ecmp.param_format.units", FT_UINT32, BASE_DEC, VALS(format_units), 0x0FC00000, NULL, HFILL }}, |
3321 | 14 | { &hf_ecmp_string_id, { "String ID", "ecmp.string_id", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3322 | 14 | { &hf_ecmp_address_scheme_menu, { "Menu", "ecmp.address_scheme.menu", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3323 | 14 | { &hf_ecmp_address_scheme_parameter, { "Parameter", "ecmp.address_scheme.parameter", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3324 | 14 | { &hf_ecmp_address_scheme_slot, { "Slot", "ecmp.address_scheme.slot", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3325 | 14 | { &hf_ecmp_address_scheme_null_byte_size, { "NULL byte size", "ecmp.address_scheme.null_byte_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3326 | 14 | { &hf_ecmp_display_unit_id, { "Unit ID", "ecmp.display_unit_id", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3327 | 14 | { &hf_ecmp_data_boolean, { "Data", "ecmp.data.boolean", FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL }}, |
3328 | 14 | { &hf_ecmp_data_int8, { "Data", "ecmp.data.int8", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3329 | 14 | { &hf_ecmp_data_uint8, { "Data", "ecmp.data.uint8", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3330 | 14 | { &hf_ecmp_data_int16, { "Data", "ecmp.data.int16", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3331 | 14 | { &hf_ecmp_data_uint16, { "Data", "ecmp.data.uint16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3332 | 14 | { &hf_ecmp_data_int32, { "Data", "ecmp.data.int32", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3333 | 14 | { &hf_ecmp_data_uint32, { "Data", "ecmp.data.uint32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3334 | 14 | { &hf_ecmp_data_int64, { "Data", "ecmp.data.int64", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3335 | 14 | { &hf_ecmp_data_uint64, { "Data", "ecmp.data.uint64", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3336 | 14 | { &hf_ecmp_data_float, { "Data", "ecmp.data.float", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3337 | 14 | { &hf_ecmp_data_double, { "Data", "ecmp.data.double", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3338 | 14 | { &hf_ecmp_access_mode, { "Access Mode", "ecmp.access_mode", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
3339 | 14 | { &hf_ecmp_open_in_non_blocking_mode, { "Open in non-blocking mode", "ecmp.open_in_non_blocking_mode", FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }}, |
3340 | 14 | { &hf_ecmp_open_file_relative_to_specified_directory_handle, { "Open file relative to specified directory handle", "ecmp.open_file_relative_to_specified_directory_handle", FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }}, |
3341 | 14 | { &hf_ecmp_file_access_mode, { "File Access Mode", "ecmp.file_access_mode", FT_UINT8, BASE_DEC, VALS(file_status_mode), 0x0F, NULL, HFILL }}, |
3342 | 14 | { &hf_ecmp_additional_scheme, { "Additional Scheme", "ecmp.additional_scheme", FT_UINT8, BASE_DEC, VALS(additional_scheme_vals), 0x0, NULL, HFILL }}, |
3343 | 14 | { &hf_ecmp_scheme_data_length, { "Length", "ecmp.scheme_data_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3344 | 14 | { &hf_ecmp_number_of_requested_bytes, { "Number of requested bytes", "ecmp.number_of_requested_bytes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3345 | 14 | { &hf_ecmp_number_of_bytes_transferred, { "Number of bytes transferred", "ecmp.number_of_bytes_transferred", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3346 | 14 | { &hf_ecmp_crc, { "CRC", "ecmp.crc", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3347 | 14 | { &hf_ecmp_ref_offset, { "Offset", "ecmp.ref_offset", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3348 | 14 | { &hf_ecmp_number_of_files_to_list, { "Number of files to list", "ecmp.number_of_files_to_list", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3349 | 14 | { &hf_ecmp_file_hash, { "Hash", "ecmp.file_hash", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3350 | 14 | { &hf_ecmp_item_type, { "Item type", "ecmp.item_type", FT_UINT8, BASE_DEC, VALS(item_type_vals), 0x0, NULL, HFILL }}, |
3351 | 14 | { &hf_ecmp_file_integrity, { "File Integrity", "ecmp.file_integrity", FT_BOOLEAN, 8, TFS(&tfs_ok_error), 0x01, NULL, HFILL }}, |
3352 | 14 | { &hf_ecmp_display_attr_read_only, { "Read Only", "ecmp.display_attr.read_only", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }}, |
3353 | 14 | { &hf_ecmp_display_attr_hidden, { "Hidden", "ecmp.display_attr.hidden", FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }}, |
3354 | 14 | { &hf_ecmp_display_attr_system, { "System", "ecmp.display_attr.system", FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }}, |
3355 | 14 | { &hf_ecmp_display_attr_volume_label, { "Volume Label", "ecmp.display_attr.volume_label", FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }}, |
3356 | 14 | { &hf_ecmp_display_attr_subdirectory, { "Subdirectory", "ecmp.display_attr.subdirectory", FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }}, |
3357 | 14 | { &hf_ecmp_display_attr_archive, { "Archive", "ecmp.display_attr.archive", FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }}, |
3358 | 14 | { &hf_ecmp_display_creation, { "Display creation", "ecmp.display_creation", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3359 | 14 | { &hf_ecmp_display_modification, { "Display modification", "ecmp.display_modification", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3360 | 14 | { &hf_ecmp_interrogate_item_type, { "Item Type", "ecmp.interrogate_item_type", FT_UINT8, BASE_DEC, VALS(Interrogate_command_option_state), 0x0, NULL, HFILL }}, |
3361 | 14 | { &hf_ecmp_interrogate_count, { "Count", "ecmp.interrogate_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3362 | 14 | { &hf_ecmp_modbus_pdu_size, { "Size", "ecmp.modbus_pdu_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3363 | | #if 0 |
3364 | | { &hf_ecmp_destination_scheme, { "Destination Scheme", "ecmp.destination_scheme", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3365 | | #endif |
3366 | 14 | { &hf_ecmp_program_control_target, { "Target", "ecmp.program_control_target", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3367 | 14 | { &hf_ecmp_program_control_command, { "Command", "ecmp.program_control_command", FT_UINT8, BASE_DEC, VALS(command_code_list), 0x0, NULL, HFILL }}, |
3368 | 14 | { &hf_ecmp_program_control_sub_command, { "Sub-Command", "ecmp.program_control_sub_command", FT_UINT8, BASE_DEC, VALS(sub_command_code_list), 0x0, NULL, HFILL }}, |
3369 | 14 | { &hf_ecmp_program_control_status, { "Status", "ecmp.program_control_status", FT_UINT8, BASE_DEC, VALS(status_list), 0x0, NULL, HFILL }}, |
3370 | 14 | { &hf_ecmp_program_status_target, { "Target", "ecmp.program_status_target", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3371 | 14 | { &hf_ecmp_program_status_status, { "Status", "ecmp.program_status_status", FT_UINT8, BASE_DEC, VALS(running_state_list), 0x0, NULL, HFILL }}, |
3372 | 14 | { &hf_ecmp_program_status_additional_items, { "Additional Items", "ecmp.program_status_additional_items", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3373 | 14 | { &hf_ecmp_cyclic_setup_max_mappings, { "Max Mappings", "ecmp.cyclic_setup.max_mappings", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3374 | 14 | { &hf_ecmp_cyclic_setup_start_offset, { "Start Offset", "ecmp.cyclic_setup.start_offset", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3375 | 14 | { &hf_ecmp_cyclic_setup_tx_count, { "Tx Count", "ecmp.cyclic_setup.tx_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3376 | 14 | { &hf_ecmp_cyclic_setup_rx_count, { "Rx Count", "ecmp.cyclic_setup.rx_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3377 | 14 | { &hf_ecmp_udp_alignment, { "Alignment", "ecmp.udp_alignment", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3378 | 14 | { &hf_ecmp_udp_scheme, { "Scheme", "ecmp.udp_scheme", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3379 | 14 | { &hf_ecmp_cyclic_data, { "Cyclic Data", "ecmp.cyclic_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3380 | 14 | { &hf_ecmp_version_summary, { "Version summary", "ecmp.version_summary", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3381 | 14 | { &hf_ecmp_min_param_menu, { "Min parameter in menu", "ecmp.min_param_menu", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3382 | 14 | { &hf_ecmp_max_param_menu, { "Max parameter in menu", "ecmp.max_param_menu", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3383 | 14 | { &hf_ecmp_file_length, { "File length", "ecmp.file_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3384 | 14 | { &hf_ecmp_mec_offset, { "mec_offset", "ecmp.mec_offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3385 | 14 | { &hf_ecmp_sample_period, { "Sample period", "ecmp.sample_period", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3386 | 14 | { &hf_ecmp_rx_timeout, { "RX Timeout", "ecmp.rx_timeout", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0x0, NULL, HFILL }}, |
3387 | 14 | { &hf_ecmp_rx_action, { "Action", "ecmp.rx_action", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3388 | 14 | { &hf_ecmp_rx_event_destination, { "Event Destination", "ecmp.rx_event_destination", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3389 | 14 | { &hf_ecmp_rx_event, { "Event", "ecmp.rx_event", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3390 | 14 | { &hf_ecmp_rx_late_handler_action, { "Action", "ecmp.rx_late_handler_action", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3391 | 14 | { &hf_ecmp_rx_late_handler_event_destination, { "Event Destination", "ecmp.rx_late_handler_event_destination", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3392 | 14 | { &hf_ecmp_rx_late_handler_event, { "Event", "ecmp.rx_late_handler_event", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3393 | 14 | { &hf_ecmp_transport_addr_scheme, { "Scheme", "ecmp.transport_addr_scheme", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3394 | 14 | { &hf_ecmp_transport_addr, { "Transport address", "ecmp.transport_addr", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
3395 | 14 | { &hf_ecmp_mapping_item_offset, { "Offset", "ecmp.mapping_item_offset", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3396 | 14 | { &hf_ecmp_mapping_item_scheme, { "Scheme", "ecmp.mapping_item_scheme", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3397 | 14 | { &hf_ecmp_setup_attribute, { "Attribute", "ecmp.setup_attribute", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3398 | 14 | { &hf_ecmp_mec_period, { "mec period", "ecmp.mec_period", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
3399 | 14 | { &hf_ecmp_interrogate_command, { "Command", "ecmp.interrogate_command", FT_UINT8, BASE_DEC, VALS(command_vals), 0x0, NULL, HFILL }} |
3400 | 14 | }; |
3401 | | |
3402 | | /* array to store pointers to the ids of the subtrees that we may be creating */ |
3403 | 14 | static int *ett[] = { |
3404 | 14 | &ett_ecmp, |
3405 | 14 | &ett_ecmp_address, |
3406 | 14 | &ett_ecmp_response_size, |
3407 | 14 | &ett_ecmp_command, |
3408 | 14 | &ett_ecmp_category, |
3409 | 14 | &ett_ecmp_option, |
3410 | 14 | &ett_ecmp_option_data, |
3411 | 14 | &ett_ecmp_attribute, |
3412 | 14 | &ett_ecmp_attribute_data, |
3413 | 14 | &ett_ecmp_cyclic_scheme, |
3414 | 14 | &ett_ecmp_interrogate_message, |
3415 | 14 | &ett_ecmp_info_type, |
3416 | 14 | &ett_ecmp_info_count, |
3417 | 14 | &ett_ecmp_param_address, |
3418 | 14 | &ett_ecmp_access_mode, |
3419 | 14 | &ett_ecmp_access_file, |
3420 | 14 | &ett_ecmp_file_read, |
3421 | 14 | &ett_ecmp_file_write, |
3422 | 14 | &ett_ecmp_file_info, |
3423 | 14 | &ett_ecmp_file_info_att, |
3424 | 14 | &ett_ecmp_file_position, |
3425 | 14 | &ett_ecmp_file_list_no, |
3426 | 14 | &ett_ecmp_file_list, |
3427 | 14 | &ett_ecmp_tunnel_3s_goodframe, |
3428 | 14 | &ett_ecmp_tunnel_3s_size, |
3429 | 14 | &ett_ecmp_tunnel_3s_service, |
3430 | 14 | &ett_cyclic_setup_attribs, |
3431 | 14 | &ett_cyclic_setup_transport_addr, |
3432 | 14 | &ett_cyclic_setup_attrib_item, |
3433 | 14 | &ett_ecmp_cyclic_data_32_bit_display, |
3434 | 14 | &ett_ecmp_cyclic_data_16_bit_display, |
3435 | 14 | &ett_ecmp_cyclic_data_8_bit_display, |
3436 | 14 | &ett_ecmp_modbus_pdu_message, |
3437 | 14 | &ett_ecmp_program_control_message, |
3438 | 14 | &ett_ecmp_program_status_message |
3439 | 14 | }; |
3440 | | |
3441 | 14 | static ei_register_info ei[] = { |
3442 | 14 | { &ei_ecmp_unknown_command, { "ecmp.unknown_command", PI_PROTOCOL, PI_WARN, "Unknown Command", EXPFILL }}, |
3443 | 14 | { &ei_ecmp_color, { "ecmp.color_invalid", PI_PROTOCOL, PI_WARN, "Invalid color data value", EXPFILL }}, |
3444 | 14 | { &ei_ecmp_option, { "ecmp.ecmp_option.unknown", PI_PROTOCOL, PI_WARN, "ERROR - Unrecognised Option Code", EXPFILL }}, |
3445 | 14 | { &ei_ecmp_data_type, { "ecmp.data_type.unknown", PI_PROTOCOL, PI_WARN, "Unknown Data Type", EXPFILL }}, |
3446 | 14 | { &ei_ecmp_parameter_addressing_scheme, { "ecmp.incorrect_parameter_addressing_scheme", PI_PROTOCOL, PI_WARN, "Incorrect parameter addressing scheme", EXPFILL }}, |
3447 | 14 | { &ei_ecmp_info_type, { "ecmp.info_type.unknown", PI_PROTOCOL, PI_WARN, "Unknown info type", EXPFILL }}, |
3448 | 14 | { &ei_ecmp_attribute_type, { "ecmp.attribute_type.unknown", PI_PROTOCOL, PI_WARN, "Wrong attribute type", EXPFILL }}, |
3449 | 14 | { &ei_ecmp_item_type, { "ecmp.item_type.unknown", PI_PROTOCOL, PI_WARN, "Unknown item type", EXPFILL }}, |
3450 | 14 | { &ei_ecmp_options_not_implemented, { "ecmp.options_not_implemented", PI_UNDECODED, PI_WARN, "ECMP Options Not Implemented", EXPFILL }} |
3451 | 14 | }; |
3452 | | |
3453 | 14 | expert_module_t* expert_ecmp; |
3454 | | |
3455 | 14 | proto_ecmp = proto_register_protocol ("ECMP", "ECMP", "ecmp"); |
3456 | 14 | ecmp_tcp_handle = register_dissector("ecmp_tcp", dissect_ecmp_tcp, proto_ecmp); |
3457 | 14 | ecmp_udp_handle = register_dissector("ecmp_udp", dissect_ecmp_udp, proto_ecmp); |
3458 | | |
3459 | | |
3460 | | /* full name short name and abbreviation (display filter name)*/ |
3461 | 14 | proto_register_field_array(proto_ecmp, hf, array_length (hf)); |
3462 | 14 | proto_register_subtree_array (ett, array_length (ett)); |
3463 | 14 | expert_ecmp = expert_register_protocol(proto_ecmp); |
3464 | 14 | expert_register_field_array(expert_ecmp, ei, array_length(ei)); |
3465 | 14 | } |
3466 | | |
3467 | | /* Function to initialise the dissector*/ |
3468 | | /* Wireshark literally scans this file (packet-ecmp.c) to find this function */ |
3469 | | void proto_reg_handoff_ecmp(void) |
3470 | 14 | { |
3471 | | /* Cyclic frames are over UDP and non-cyclic are over TCP */ |
3472 | 14 | dissector_add_uint_with_preference("udp.port", ECMP_TCP_PORT, ecmp_udp_handle); |
3473 | 14 | dissector_add_uint_with_preference("tcp.port", ECMP_TCP_PORT, ecmp_tcp_handle); |
3474 | | |
3475 | | /* Modbus dissector hooks */ |
3476 | 14 | modbus_handle = find_dissector_add_dependency("modbus", proto_ecmp); |
3477 | 14 | proto_modbus = proto_get_id_by_filter_name( "modbus" ); |
3478 | 14 | } |
3479 | | |
3480 | | |
3481 | | /* |
3482 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
3483 | | * |
3484 | | * Local variables: |
3485 | | * c-basic-offset: 8 |
3486 | | * tab-width: 8 |
3487 | | * indent-tabs-mode: t |
3488 | | * End: |
3489 | | * |
3490 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
3491 | | * :indentSize=8:tabSize=8:noTabs=false: |
3492 | | */ |