Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-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
 */