2 * Routines for optommp dissection
3 * Copyright 2014, Opto22 wiresharkdissectorcoder@gmail.com
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include "packet-tcp.h"
17 #define OPTO_FRAME_HEADER_LEN 8
18 #define OPTOMMP_MIN_LENGTH 12
20 #define OPTOMMP_WRITE_QUADLET_REQUEST 0
21 #define OPTOMMP_WRITE_BLOCK_REQUEST 1
22 #define OPTOMMP_WRITE_RESPONSE 2
23 #define OPTOMMP_READ_QUADLET_REQUEST 4
24 #define OPTOMMP_READ_BLOCK_REQUEST 5
25 #define OPTOMMP_READ_QUADLET_RESPONSE 6
26 #define OPTOMMP_READ_BLOCK_RESPONSE 7
28 /* Initialize the protocol and registered fields */
29 static int proto_optommp
;
30 static dissector_handle_t optommp_tcp_handle
;
31 static dissector_handle_t optommp_udp_handle
;
32 static int hf_optommp_nodest_id
;
33 static int hf_optommp_dest_id
;
34 static int hf_optommp_boot_id
;
35 static int hf_optommp_tl
;
36 static int hf_optommp_tcode
;
37 static int hf_optommp_source_ID
;
38 static int hf_optommp_rcode
;
39 static int hf_optommp_quadlet_data
;
40 static int hf_optommp_data_length
;
41 static int hf_optommp_dest_offset
;
42 static int hf_optommp_data_block_byte
;
43 static int hf_optommp_data_block_quadlet
;
44 /* Initialize the subtree pointers */
45 static int ett_optommp
;
46 static int ett_dest_id
;
47 static int ett_data_block_q
;
48 static int ett_data_block_b
;
50 static const value_string optommp_tcode_names
[] = {
51 { 0, "Write Quadlet Request" },
52 { 1, "Write Block Request" },
53 { 2, "Write Response" },
54 { 4, "Read Quadlet Request" },
55 { 5, "Read Block Request" },
56 { 6, "Read Quadlet Response" },
57 { 7, "Read Block Response" },
61 static const value_string optommp_rcode_meanings
[] = {
63 { 0x1, "Undefined command" },
64 { 0x2, "Invalid point type" },
65 { 0x3, "Invalid float" },
66 { 0x4, "Powerup Clear expected" },
67 { 0x5, "Invalid memory address/data" },
68 { 0x6, "Invalid command length" },
71 { 0x9, "Cannot erase flash" },
72 { 0xa, "Cannot program flash" },
73 { 0xb, "Downloaded image too small" },
74 { 0xc, "Image CRC mismatch" },
75 { 0xd, "Image length mismatch" },
76 { 0xe, "Feature is not yet implemented" },
77 { 0xf, "Communications watchdog timeout" },
81 static const range_string optommp_mm_areas
[] = {
82 { 0xf0100000, 0xf01bffff,
83 "Expanded Analog & Digital Channel Configuration - Read/Write" },
84 { 0xf01c0000, 0xf01c7fff,
85 "Expanded Analog Channel Calc & Set - Read/Write" },
86 { 0xf01d4000, 0xf01dffff,
87 "Expanded Analog Channel Read & Clear - Read/Write" },
88 { 0xF01E0000, 0xF021FFFF,
89 "Expanded Digital Channel Read - Read Only" },
90 { 0xF0220000, 0xF025FFFF,
91 "Expanded Digital Channel Write - Read/Write" },
92 { 0xf0260000, 0xf029ffff,
93 "Expanded Analog Channel Read - Read Only" },
94 { 0xf02a0000, 0xf02dffff,
95 "Expanded Analog Channel Write - Read/Write" },
96 { 0xf02e0000, 0xf02f7fff,
97 "Expanded Digital Channel Read & Clear - Read/Write" },
98 { 0xF02F8000, 0xF02FFFFF,
99 "I/O Channel Data Preserved Area (64-bit energy counters)" },
100 { 0xf0300000, 0xf030024b,
101 "Status Area Read - Read Only" },
102 { 0xF0380000, 0xF03802B3,
103 "Status Write Area - Read/Write" },
104 { 0xf0310400, 0xf031110f,
105 "Communications Port Configuration - Read/Write" },
106 { 0xf0329000, 0xf032efff,
107 "Serial Pass-Through - Read/Write" },
108 { 0xf0350000, 0xf0350023,
109 "Date and Time Configuration - Read/Write" },
110 { 0xf0390000, 0xf0390003,
111 "Modbus Configuration - Read/Write" },
112 { 0xf03a0004, 0xf03a007F,
113 "Network Security Configuration - Read/Write" },
114 { 0xf03a1000, 0xf03a1fff,
115 "SSI Module Configuration - Read/Write" },
116 { 0xf03a7f00, 0xf03a7ffa,
117 "Serial Module Identification - Read Only" },
118 { 0xf03a8000, 0xf03a840f,
119 "Serial Module Configuration - Read/Write" },
120 { 0xf03a8500, 0xf03a8dc3,
121 "Wiegand Serial Module Configuration - Read/Write" },
122 { 0xf03a9000, 0xf03a92bf,
123 "SNAP-SCM-CAN2B Serial Module Configuration -Read/Write" },
124 { 0xf03c0000, 0xf03c030b,
125 "SNMP Configuration - Read/Write" },
126 { 0xf03d0000, 0xf03d0079,
127 "FTP User Name/Password Configuration - Read/Write" },
128 { 0xf03e0000, 0xf03eb107,
129 "PPP Configuration - Read/Write" },
130 { 0xf03eb800, 0xf03fb827,
131 "PPP Status - Read Only" },
132 { 0xf03fffc0, 0xf03fffff,
133 "Streaming Configuration - Read/Write" },
134 { 0xf0400000, 0xf04001ff,
135 "Digital Bank Read - Read Only" },
136 { 0xf0500000, 0xf050001f,
137 "Digital Bank Write - Read/Write" },
138 { 0xf0600000, 0xf06003ff,
139 "Analog Bank Read - Read Only" },
140 { 0xf0700000, 0xf07001ff,
141 "Analog Bank Write - Read/Write" },
142 { 0xf0800000, 0xf0800fd3,
143 "Digital Channel Read - Read Only" },
144 { 0xf0900000, 0xf0900fcf,
145 "Digital Channel Write - Read/Write" },
146 { 0xf0a00000, 0xf0a00fcf,
147 "Old Analog Channel Read - Read Only" },
148 { 0xf0b00000, 0xf0b00fcf,
149 "Old Analog Channel Write - Read/Write" },
150 { 0xf0c00000, 0xf0c011ff,
151 "Old A&D Channel Configuration Information - Read/Write" },
152 { 0xf0d00000, 0xf0d01fff,
153 "Old Digital Events and Reactions - Read/Write" },
154 { 0xf0d40000, 0xf0d4ffff,
155 "Digital Events - Expanded - Read/Write" },
156 { 0xf0d80000, 0xf0dc81ff,
157 "Scratch Pad - Read/Write" },
158 { 0xf0e00000, 0xf0e001ff,
159 "Old Analog Channel Calculation and Set - Read Only" },
160 { 0xf0f00000, 0xf0f002ff,
161 "Old Digital Read and Clear - Read Only" },
162 { 0xf0f80000, 0xf0f801ff,
163 "Old Analog Read and Clear/Restart - Read Only" },
164 { 0xf1000000, 0xf100021f,
165 "Streaming - Read Only" },
166 { 0xF1000300, 0xF1000BFF,
167 "Expanded Streaming Data - Read Only" },
168 { 0xf1001000, 0xf10017ff,
169 "Analog EU or Digital Counter Packed Data - Read" },
170 { 0xf1001800, 0xf100183f,
171 "Digital Packed Data - Read/Write" },
172 { 0xf1001900, 0xF10019FF,
173 "Expanded Digital Packed Data Read - Read Only" },
174 { 0xF1001A00, 0xF1001A7F,
175 "Expanded Digital Packed Must On/Off (MOMO) - Read/Write" },
176 { 0xF1002000, 0xF100607F,
177 "Analog/Digital Channel Quality of Data - Read Only" },
178 { 0xF1008000, 0xF100BFFF,
179 "Expanded Analog EU or Digital Counter (Feature) Packed Area - Read Only" },
180 { 0xf1100000, 0xf1101fff,
181 "Alarm Event Settings - Read/Write" },
182 { 0xf1200000, 0xf12111ff,
183 "Event Message Configuration - Read/Write" },
184 { 0xf1300000, 0xf13000a3,
185 "Email Configuration - Read/Write" },
186 { 0xf1540000, 0xf1540efc,
187 "Serial Event Configuration - Read/Write" },
188 { 0xf1560000, 0xf1560f7f,
189 "Wiegand Serial Event Configuration - Read/Write" },
190 { 0xf1808000, 0xf1809ffe,
191 "SNAP High-Density Digital - Read Only" },
192 { 0xF1809000, 0xF1809FFF,
193 "SNAP High-Density Digital Read Counter Area - Read Only" },
194 { 0xf180a000, 0xf180bffe,
195 "SNAP High-Density Digital Read and Clear Latches - Read/Write" },
196 { 0xF180B000, 0xF180BFFF,
197 "SNAP High-Density Digital Read and Clear Counter - Read/Write" },
198 { 0xf180c000, 0xf180c3fe,
199 "SNAP High-Density Digital Write - Read/Write" },
200 { 0xf2000000, 0xf2002edf,
201 "PID Configuration and Status - Read/Write" },
202 { 0xf2100000, 0xf21047ff,
203 "PID Configuration and Status - Read/Write" },
204 { 0xF2180000, 0xF218137F,
206 { 0xF2280000, 0xF228FFFF,
207 "Public I/O Tag Configuration (Channels 0-31) - Read/Write" },
208 { 0xF2290000, 0xF2295FFF,
209 "Public Tag Revision Number" },
210 { 0xF2293000, 0xF229FFFF,
211 "Public PID Tag Configuration" },
212 { 0xF22A0000, 0xF22AFFFF,
213 "Public I/O Tag Configuration (Channels 32-63) - Read/Write" },
214 { 0xF22B0000, 0xF22B01FF,
215 "Public Scratchpad Tag Configuration" },
216 { 0xf3000000, 0xf3000707,
217 "Data Logging Configuration - Read/Write" },
218 { 0xf3020000, 0xf302176f,
219 "Data Log - Read/Write" },
220 { 0xf4000000, 0xf4000f6f,
221 "PID Module Configuration - Read/Write" },
222 { 0xf4080000, 0xf4080007,
223 "Control Engine - Read/Write" },
224 { 0xf7002000, 0xf7002103,
225 "Serial Brain Communication - Read/Write" },
226 { 0xf7002200, 0xf7002207,
227 "microSD Card - Read/Write" },
228 { 0xf7003000, 0xf700308f,
229 "WLAN Status - Read Only" },
230 { 0xf7004000, 0xf700553b,
231 "WLAN Configuration - Read/Write" },
232 { 0xf8000000, 0xf800000b,
233 "WLAN Enable - Read/Write" },
234 { 0xF8110000, 0xF81107FF,
235 "Module Build Info" },
236 { 0xfffff008, 0xfffff077,
237 "IP Settings - Read/Write" },
241 /* Function Prototypes */
242 static unsigned get_optommp_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
243 int offset
, void *data _U_
);
244 static int dissect_optommp_reassemble_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
,
245 proto_tree
*tree
, void *data
);
246 static int dissect_optommp_reassemble_udp(tvbuff_t
*tvb
, packet_info
*pinfo
,
247 proto_tree
*tree
, void *data
);
248 static int dissect_optommp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
249 *tree
, void * data _U_
);
250 static void dissect_optommp_dest_id(proto_tree
*tree
,
251 tvbuff_t
*tvb
, unsigned *poffset
);
252 static void dissect_optommp_write_quadlet_request(proto_item
**ti
,
253 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
);
254 static void dissect_optommp_write_block_request(proto_item
**ti
,
255 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
);
256 static void dissect_optommp_write_response(proto_item
**ti
,
257 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
);
258 static void dissect_optommp_read_quadlet_request(proto_item
**ti
,
259 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
);
260 static void dissect_optommp_read_block_request(proto_item
**ti
,
261 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
);
262 static void dissect_optommp_read_quadlet_response(proto_item
**ti
,
263 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
);
264 static void dissect_optommp_read_block_response(proto_item
**ti
, proto_tree
265 *tree
, tvbuff_t
*tvb
, unsigned *poffset
);
266 static void dissect_optommp_source_ID(proto_item
**ti
, proto_tree
*tree
,
267 tvbuff_t
*tvb
, unsigned *poffset
);
268 static void dissect_optommp_destination_offset_6(proto_item
**ti
,
269 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
);
270 static void dissect_optommp_quadlet_data(proto_item
**ti
, proto_tree
*tree
,
271 tvbuff_t
*tvb
, unsigned *poffset
);
272 static void dissect_optommp_rcode(proto_item
**ti
, proto_tree
*tree
,
273 tvbuff_t
*tvb
, unsigned *poffset
);
274 static uint16_t dissect_optommp_data_length(proto_item
**ti
, proto_tree
*tree
,
275 tvbuff_t
*tvb
, unsigned *poffset
);
276 static void dissect_optommp_data_block(proto_item
**ti
, proto_tree
*tree
,
277 tvbuff_t
*tvb
, unsigned *poffset
, uint16_t data_length
);
278 static void dissect_optommp_data_block_byte(proto_item
**ti
, proto_tree
*tree
,
279 tvbuff_t
*tvb
, unsigned *poffset
);
280 static void dissect_optommp_data_block_quadlet(proto_item
**ti
, proto_tree
281 *tree
, tvbuff_t
*tvb
, unsigned *poffset
);
282 static int optommp_has_destination_offset(uint8_t tcode
);
284 void proto_register_optommp(void);
285 void proto_reg_handoff_optommp(void);
288 /****************************************************************************
289 function: get_optommp_message_len()
290 parameters: pinfo: not used
291 tvb: poiner to packet data
293 purpose: Gets the message length depending on tcode and data_block len
294 ****************************************************************************/
295 static unsigned get_optommp_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
296 int offset
, void *data _U_
)
298 unsigned len
= OPTO_FRAME_HEADER_LEN
;
301 /* Just want the most significant nibble */
302 tcode
= tvb_get_uint8(tvb
, offset
+ 3) >> 4;
304 if( tcode
== OPTOMMP_WRITE_QUADLET_REQUEST
||
305 tcode
== OPTOMMP_WRITE_BLOCK_REQUEST
||
306 tcode
== OPTOMMP_READ_BLOCK_REQUEST
||
307 tcode
== OPTOMMP_READ_QUADLET_RESPONSE
||
308 tcode
== OPTOMMP_READ_BLOCK_RESPONSE
)
312 else if( tcode
== OPTOMMP_WRITE_RESPONSE
||
313 tcode
== OPTOMMP_READ_QUADLET_REQUEST
)
318 if( (tcode
== OPTOMMP_WRITE_BLOCK_REQUEST
||
319 tcode
== OPTOMMP_READ_BLOCK_RESPONSE
) &&
320 tvb_reported_length_remaining(tvb
, offset
) >= 14 )
322 /* offset + 12 is the data_length of the packet */
323 len
+= (unsigned) tvb_get_ntohs(tvb
, offset
+ 12);
329 /****************************************************************************
330 function: dissect_optommp_reassemble_tcp()
332 purpose: reassemble packets then send to dissector
333 ****************************************************************************/
334 static int dissect_optommp_reassemble_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
,
335 proto_tree
*tree
, void *data
)
337 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, OPTO_FRAME_HEADER_LEN
,
338 get_optommp_message_len
, dissect_optommp
, data
);
340 return tvb_captured_length(tvb
);
343 /****************************************************************************
344 function: dissect_optommp_reassemble_udp()
346 purpose: reassemble packets then send to dissector
347 ****************************************************************************/
348 static int dissect_optommp_reassemble_udp(tvbuff_t
*tvb
, packet_info
*pinfo
,
349 proto_tree
*tree
, void *data
)
351 dissect_optommp(tvb
, pinfo
, tree
, data
);
353 return tvb_captured_length(tvb
);
356 /****************************************************************************
357 function: dissect_optommp()
359 purpose: add the optommp protocol subtree
360 ****************************************************************************/
361 static int dissect_optommp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
362 *tree
, void *data _U_
)
364 /* Declare and init variables for each part of the packet */
367 /* Provide a summary label */
368 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "OptoMMP");
369 col_clear(pinfo
->cinfo
, COL_INFO
);
370 if( tvb_reported_length(tvb
) >= OPTOMMP_MIN_LENGTH
)
372 /* the tcode is the most sig nibble of the 3rd byte */
373 tcode
= tvb_get_uint8(tvb
, 3) >> 4;
374 if( optommp_has_destination_offset(tcode
) != 0 &&
375 tvb_reported_length(tvb
) >= 12)
377 uint64_t destination_offset
= 0;
378 destination_offset
= tvb_get_ntoh48(tvb
, 6);
379 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
380 " type: %s, dest_off: 0x%012" PRIx64
,
381 val_to_str(tcode
, optommp_tcode_names
, "Unknown (0x%02x)"),
386 col_add_fstr(pinfo
->cinfo
, COL_INFO
, " type: %s",
387 val_to_str(tcode
, optommp_tcode_names
, "Unknown (0x%02x)"));
393 proto_item
*root_ti
= NULL
;
394 proto_item
*ti
= NULL
;
395 proto_tree
*optommp_tree
= NULL
;
398 /* Add the root node of our protocol */
399 root_ti
= proto_tree_add_item(tree
, proto_optommp
, tvb
, 0, -1,
401 if( tvb_reported_length(tvb
) >= OPTOMMP_MIN_LENGTH
)
403 tcode
= tvb_get_uint8(tvb
, 3) >> 4;
404 proto_item_append_text(root_ti
, ", type: %s", val_to_str(tcode
,
405 optommp_tcode_names
, "Unknown (0x%02x)"));
406 if( optommp_has_destination_offset(tcode
) != 0 )
408 uint64_t destination_offset
= 0;
409 destination_offset
= tvb_get_ntoh48(tvb
, 6);
410 proto_item_append_text(root_ti
,
411 ", dest_off: 0x%012" PRIx64
,
414 /* Add an expansion to the tree */
415 optommp_tree
= proto_item_add_subtree(root_ti
, ett_optommp
);
416 /* The destination id is the first two bytes of the packet */
417 dissect_optommp_dest_id(optommp_tree
, tvb
, &offset
);
418 /* Dissect transaction label */
419 ti
= proto_tree_add_item(optommp_tree
, hf_optommp_tl
, tvb
, offset
,
423 proto_tree_add_item(optommp_tree
, hf_optommp_tcode
, tvb
,
424 offset
, 1, ENC_BIG_ENDIAN
);
425 tcode
= tvb_get_uint8(tvb
, offset
) >> 4;
427 /* Dissect the rest of the packet according to type */
431 dissect_optommp_write_quadlet_request(&ti
, optommp_tree
, tvb
,
435 dissect_optommp_write_block_request(&ti
, optommp_tree
, tvb
,
439 dissect_optommp_write_response(&ti
, optommp_tree
, tvb
,
443 dissect_optommp_read_quadlet_request(&ti
, optommp_tree
, tvb
,
447 dissect_optommp_read_block_request(&ti
, optommp_tree
, tvb
,
451 dissect_optommp_read_quadlet_response(&ti
, optommp_tree
, tvb
,
455 dissect_optommp_read_block_response(&ti
, optommp_tree
, tvb
,
462 return tvb_captured_length(tvb
);
465 /****************************************************************************
466 function: dissect_optommp_dest_id()
467 parameters: tree: The subtree to append nodes to
468 tvb: The data of the current node
469 poffset: Keeps track of our location in the tree
470 purpose: Dissect destination id and boot id
471 ****************************************************************************/
472 static void dissect_optommp_dest_id(proto_tree
*tree
,
473 tvbuff_t
*tvb
, unsigned *poffset
)
475 proto_tree
*dest_id_tree
= NULL
;
476 uint16_t dest_id
= 0;
478 /* Check whether boot id present */
479 dest_id
= tvb_get_ntohs(tvb
, *poffset
);
480 if( (dest_id
& 0x8000) == 0x8000 )
482 dest_id_tree
= proto_tree_add_subtree(tree
, tvb
, *poffset
,
483 2, ett_dest_id
, NULL
, "destination_ID");
484 proto_tree_add_item(dest_id_tree
, hf_optommp_dest_id
,
485 tvb
, *poffset
, 2, ENC_BIG_ENDIAN
);
486 proto_tree_add_item(dest_id_tree
, hf_optommp_boot_id
,
487 tvb
, *poffset
, 2, ENC_BIG_ENDIAN
);
491 proto_tree_add_item(tree
, hf_optommp_nodest_id
,
492 tvb
, *poffset
, 2, ENC_BIG_ENDIAN
);
497 /****************************************************************************
498 function: dissect_optommp_write_quadlet_request()
499 parameters: ti: Reserved for future use
500 tree: The subtree to append nodes to
501 tvb: The data of the current node
502 poffset: Keeps track of our location in the tree
503 purpose: Dissect a write quadlet request
504 ****************************************************************************/
505 static void dissect_optommp_write_quadlet_request(proto_item
**ti
,
506 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
)
508 dissect_optommp_source_ID(ti
, tree
, tvb
, poffset
);
509 dissect_optommp_destination_offset_6(ti
, tree
, tvb
, poffset
);
510 dissect_optommp_quadlet_data(ti
, tree
, tvb
, poffset
);
513 /****************************************************************************
514 function: dissect_optommp_write_block_request()
515 parameters: ti: Reserved for future use
516 tree: The subtree to append nodes to
517 tvb: The data of the current node
518 poffset: Keeps track of our location in the tree
519 purpose: Dissect a write block request
520 ****************************************************************************/
521 static void dissect_optommp_write_block_request(proto_item
**ti
,
522 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
)
524 uint16_t data_length
= 0;
525 dissect_optommp_source_ID(ti
, tree
, tvb
, poffset
);
526 dissect_optommp_destination_offset_6(ti
, tree
, tvb
, poffset
);
527 data_length
= dissect_optommp_data_length(ti
, tree
, tvb
, poffset
);
528 *poffset
+= 2; /* skip extended_tcode */
529 dissect_optommp_data_block(ti
, tree
, tvb
, poffset
, data_length
);
532 /****************************************************************************
533 function: dissect_optommp_write_response()
534 parameters: ti: Reserved for future use
535 tree: The subtree to append nodes to
536 tvb: The data of the current node
537 poffset: Keeps track of our location in the tree
538 purpose: Dissect a write response
539 ****************************************************************************/
540 static void dissect_optommp_write_response(proto_item
**ti
,
541 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
)
543 dissect_optommp_source_ID(ti
, tree
, tvb
, poffset
);
544 dissect_optommp_rcode(ti
, tree
, tvb
, poffset
);
547 /****************************************************************************
548 function: dissect_optommp_read_quadlet_request()
549 parameters: ti: Reserved for future use
550 tree: The subtree to append nodes to
551 tvb: The data of the current node
552 poffset: Keeps track of our location in the tree
553 purpose: Dissect a read quadlet request
554 ****************************************************************************/
555 static void dissect_optommp_read_quadlet_request(proto_item
**ti
,
556 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
)
558 dissect_optommp_source_ID(ti
, tree
, tvb
, poffset
);
559 dissect_optommp_destination_offset_6(ti
, tree
, tvb
, poffset
);
562 /****************************************************************************
563 function: dissect_optommp_read_block_request()
564 parameters: ti: Reserved for future use
565 tree: The subtree to append nodes to
566 tvb: The data of the current node
567 poffset: Keeps track of our location in the tree
568 purpose: Dissect a read block request
569 ****************************************************************************/
570 static void dissect_optommp_read_block_request(proto_item
**ti
,
571 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
)
573 dissect_optommp_source_ID(ti
, tree
, tvb
, poffset
);
574 dissect_optommp_destination_offset_6(ti
, tree
, tvb
, poffset
);
575 dissect_optommp_data_length(ti
, tree
, tvb
, poffset
);
578 /****************************************************************************
579 function: dissect_optommp_read_quadlet_response
580 parameters: ti: Reserved for future use
581 tree: The subtree to append nodes to
582 tvb: The data of the current node
583 poffset: Keeps track of our location in the tree
584 purpose: Dissect a read quadlet response
585 ****************************************************************************/
586 static void dissect_optommp_read_quadlet_response(proto_item
**ti
,
587 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
)
589 dissect_optommp_source_ID(ti
, tree
, tvb
, poffset
);
590 dissect_optommp_rcode(ti
, tree
, tvb
, poffset
);
591 *poffset
+= 5; /* Skip reserved part for now */
592 dissect_optommp_quadlet_data(ti
, tree
, tvb
, poffset
);
595 /****************************************************************************
596 function: dissect_optommp_read_block_response()
597 parameters: ti: Reserved for future use
598 tree: The subtree to append nodes to
599 tvb: The data of the current node
600 poffset: Keeps track of our location in the tree
601 purpose: Dissect a read block response
602 ****************************************************************************/
603 static void dissect_optommp_read_block_response(proto_item
**ti
, proto_tree
604 *tree
, tvbuff_t
*tvb
, unsigned *poffset
)
606 uint16_t data_length
= 0;
607 dissect_optommp_source_ID(ti
, tree
, tvb
, poffset
);
608 dissect_optommp_rcode(ti
, tree
, tvb
, poffset
);
609 *poffset
+= 5; /* Skip the reserved part for now */
610 data_length
= dissect_optommp_data_length(ti
, tree
, tvb
, poffset
);
611 *poffset
+= 2; /* skip extended_tcode */
612 dissect_optommp_data_block(ti
, tree
, tvb
, poffset
, data_length
);
615 /****************************************************************************
616 function: dissect_optommp_source_ID()
617 parameters: ti: Reserved for future use
618 tree: The subtree to append nodes to
619 tvb: The data of the current node
620 poffset: Keeps track of our location in the tree
621 purpose: Dissect the source id field.
622 ****************************************************************************/
623 static void dissect_optommp_source_ID(proto_item
**ti
, proto_tree
*tree
,
624 tvbuff_t
*tvb
, unsigned *poffset
)
626 if( tvb_reported_length(tvb
) >= *poffset
+ 2 )
628 *ti
= proto_tree_add_item(tree
, hf_optommp_source_ID
, tvb
, *poffset
,
634 /****************************************************************************
635 function: dissect_optommp_destination_offset_6()
636 parameters: ti: Reserved for future use
637 tree: The subtree to append nodes to
638 tvb: The data of the current node
639 poffset: Keeps track of our location in the tree
640 purpose: Get the destination offset byte by byte and then reassemble
641 note: This must be called when the reported length < offset + 8
642 ****************************************************************************/
643 static void dissect_optommp_destination_offset_6(proto_item
**ti
,
644 proto_tree
*tree
, tvbuff_t
*tvb
, unsigned *poffset
)
646 if( tvb_reported_length(tvb
) >= *poffset
+ 6 )
648 *poffset
+= 2; /* The first two bytes are always 0xFFFF */
649 *ti
= proto_tree_add_item(tree
, hf_optommp_dest_offset
, tvb
,
650 *poffset
, 4, ENC_BIG_ENDIAN
);
655 /****************************************************************************
656 function: dissect_optommp_quadlet_data()
657 parameters: ti: Reserved for future use
658 tree: The subtree to append nodes to
659 tvb: The data of the current node
660 poffset: Keeps track of our location in the tree
661 purpose: Dissect the quadlet data part for packets that have it
662 ****************************************************************************/
663 static void dissect_optommp_quadlet_data(proto_item
**ti
, proto_tree
*tree
,
664 tvbuff_t
*tvb
, unsigned *poffset
)
666 if( tvb_reported_length(tvb
) >= *poffset
+ 4 )
668 *ti
= proto_tree_add_item(tree
, hf_optommp_quadlet_data
, tvb
,
669 *poffset
, 4, ENC_BIG_ENDIAN
);
674 /****************************************************************************
675 function: dissect_optommp_data_length()
676 parameters: ti: Reserved for future use
677 tree: The subtree to append nodes to
678 tvb: The data of the current node
679 poffset: Keeps track of our location in the tree
680 purpose: Dissect data length
681 ****************************************************************************/
682 static uint16_t dissect_optommp_data_length(proto_item
**ti
, proto_tree
*tree
,
683 tvbuff_t
*tvb
, unsigned *poffset
)
685 uint16_t data_length
= 0;
687 if( tvb_reported_length(tvb
) >= *poffset
+ 2 )
689 data_length
= tvb_get_ntohs(tvb
, *poffset
);
690 *ti
= proto_tree_add_item(tree
, hf_optommp_data_length
, tvb
,
691 *poffset
, 2, ENC_BIG_ENDIAN
);
699 /****************************************************************************
700 function: dissect_optommp_rcode()
701 parameters: ti: Reserved for future use
702 tree: The subtree to append nodes to
703 tvb: The data of the current node
704 poffset: Keeps track of our location in the tree
705 purpose: Dissect rcode part for packets that have it
706 ****************************************************************************/
707 static void dissect_optommp_rcode(proto_item
**ti
, proto_tree
*tree
,
708 tvbuff_t
*tvb
, unsigned *poffset
)
710 if( tvb_reported_length(tvb
) >= *poffset
+ 1 )
712 *ti
= proto_tree_add_item(tree
, hf_optommp_rcode
, tvb
, *poffset
,
719 /****************************************************************************
720 function: dissect_optommp_data_block()
721 parameters: ti: The node to add the subtree to
722 tree: The subtree to append nodes to
723 tvb: The data of the current node
724 poffset: Keeps track of our location in the tree
725 data_length:number of bytes in the data_block
726 purpose: Dissect a data block.
727 ****************************************************************************/
728 static void dissect_optommp_data_block(proto_item
**ti
, proto_tree
*tree
,
729 tvbuff_t
*tvb
, unsigned *poffset
, uint16_t data_length
)
731 proto_tree
*data_block_tree_b
= NULL
;
732 proto_tree
*data_block_tree_q
= NULL
;
734 unsigned quadlet_offset
= 0;
735 unsigned byte_offset
= 0;
736 quadlet_offset
= *poffset
;
737 byte_offset
= *poffset
;
739 /* Create and fill quadlet subtree */
740 data_block_tree_q
= proto_tree_add_subtree(tree
, tvb
, *poffset
,
741 data_length
, ett_data_block_q
, ti
, "data_block (as quadlets)");
743 for( i
= 0; i
< (uint16_t) (data_length
/ 4); ++i
)
745 dissect_optommp_data_block_quadlet(ti
, data_block_tree_q
, tvb
,
749 /* Create and fill byte subtree */
750 data_block_tree_b
= proto_tree_add_subtree(tree
, tvb
, *poffset
,
751 data_length
, ett_data_block_b
, ti
, "data_block (as bytes)");
753 for( i
= 0; i
< data_length
; ++i
)
755 dissect_optommp_data_block_byte(ti
, data_block_tree_b
, tvb
,
760 /****************************************************************************
761 function: dissect_optommp_data_block_byte()
762 parameters: ti: Reserved for future use
763 tree: The subtree to append nodes to
764 tvb: The data of the current node
765 poffset: Keeps track of our location in the tree
766 purpose: Dissect a data block.
767 ****************************************************************************/
768 static void dissect_optommp_data_block_byte(proto_item
**ti
, proto_tree
*tree
,
769 tvbuff_t
*tvb
, unsigned *poffset
)
771 if( tvb_reported_length(tvb
) >= *poffset
+ 1 )
773 *ti
= proto_tree_add_item(tree
, hf_optommp_data_block_byte
, tvb
,
774 *poffset
, 1, ENC_NA
);
780 /****************************************************************************
781 function: dissect_optommp_data_block_quadlet()
782 parameters: ti: Reserved for future use
783 tree: The subtree to append nodes to
784 tvb: The data of the current node
785 poffset: Keeps track of our location in the tree
786 purpose: Dissect a data block.
787 ****************************************************************************/
788 static void dissect_optommp_data_block_quadlet(proto_item
**ti
, proto_tree
789 *tree
, tvbuff_t
*tvb
, unsigned *poffset
)
791 if( tvb_reported_length(tvb
) >= *poffset
+ 4 )
793 *ti
= proto_tree_add_item(tree
, hf_optommp_data_block_quadlet
,
794 tvb
, *poffset
, 4, ENC_NA
);
800 /****************************************************************************
801 function: dissect_optommp_data_block_quadlet()
802 parameters: ti: Reserved for future use
803 tree: The subtree to append nodes to
804 tvb: The data of the current node
805 poffset: Keeps track of our location in the tree
806 returns: 1 if packet type has destination_offset field, 0 otherwise
807 purpose: Dissect a data block.
808 ****************************************************************************/
809 static int optommp_has_destination_offset(uint8_t tcode
)
811 if( tcode
== 0 || tcode
== 1 || tcode
== 4 || tcode
== 5 )
817 /****************************************************************************
818 function: proto_register_optommp()
820 purpose: create and register the protocol, trees, and fields
821 ****************************************************************************/
822 void proto_register_optommp(void)
825 static hf_register_info hf
[] =
827 /* When MSB not set, dest_ID is 0 */
828 { &hf_optommp_nodest_id
,
829 { "destination_ID", "optommp.destination_ID",
834 { &hf_optommp_dest_id
,
835 { "destination_ID", "optommp.destination_ID",
840 { &hf_optommp_boot_id
,
841 { "boot_ID", "optommp.boot_ID",
847 { "tl", "optommp.tl",
853 { "tcode", "optommp.tcode",
855 VALS(optommp_tcode_names
), 0xF0,
858 { &hf_optommp_source_ID
,
859 { "source_ID", "optommp.source_id",
865 { "rcode", "optommp.rcode",
867 VALS(optommp_rcode_meanings
), 0xF0,
870 { &hf_optommp_quadlet_data
,
871 { "quadlet_data", "optommp.quadlet_data",
876 { &hf_optommp_data_length
,
877 { "data_length", "optommp.data_length",
882 { &hf_optommp_dest_offset
,
883 { "destination_offset", "optommp.destination_offset",
884 FT_UINT32
, BASE_HEX
| BASE_RANGE_STRING
,
885 RVALS(optommp_mm_areas
), 0x0,
888 { &hf_optommp_data_block_byte
,
889 { "data_block_byte", "optommp.data_block_byte",
894 { &hf_optommp_data_block_quadlet
,
895 { "data_block_quadlet", "optommp.data_block_quadlet",
911 proto_optommp
= proto_register_protocol("OptoMMP", "OptoMMP", "optommp");
912 proto_register_field_array(proto_optommp
, hf
, array_length(hf
));
913 proto_register_subtree_array(ett
, array_length(ett
));
916 optommp_tcp_handle
= register_dissector("optommp.tcp", dissect_optommp_reassemble_tcp
, proto_optommp
);
917 optommp_udp_handle
= register_dissector("optommp.udp", dissect_optommp_reassemble_udp
, proto_optommp
);
920 /****************************************************************************
921 function: proto_reg_handoff()
923 purpose: plug into wireshark with a handle
924 ****************************************************************************/
925 void proto_reg_handoff_optommp(void)
927 dissector_add_for_decode_as_with_preference("tcp.port", optommp_tcp_handle
);
928 dissector_add_for_decode_as_with_preference("udp.port", optommp_udp_handle
);
932 * Editor modelines - https://www.wireshark.org/tools/modelines.html
937 * indent-tabs-mode: nil
940 * vi: set shiftwidth=4 tabstop=8 expandtab:
941 * :indentSize=4:tabSize=8:noTabs=true: