Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-pcomtcp.c
blob22f69f693c4bc8d4a01dfddabef4864f04a70ba2
1 /* packet-pcomtcp.c
2 * Routines for PCOM/TCP dissection
3 * Copyright 2018, Luis Rosa <lmrosa@dei.uc.pt>
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
13 * PCOM is a protocol to communicate with Unitronics PLCs either by serial or TCP.
14 * Two modes are available, ASCII and Binary.
16 * See https://unitronicsplc.com/Download/SoftwareUtilities/Unitronics%20PCOM%20Protocol.pdf
20 #include <config.h>
21 #include <epan/packet.h>
22 #include <epan/expert.h>
24 void proto_reg_handoff_pcomtcp(void);
25 void proto_register_pcomtcp(void);
27 /* Initialize the protocol and registered fields */
28 static int proto_pcomtcp;
29 static int proto_pcomascii;
30 static int proto_pcombinary;
32 static int hf_pcomtcp_transid;
33 static int hf_pcomtcp_protocol;
34 static int hf_pcomtcp_reserved;
35 static int hf_pcomtcp_length;
37 static int hf_pcomascii_stx;
38 static int hf_pcomascii_unitid;
39 static int hf_pcomascii_command_code;
40 static int hf_pcomascii_address;
41 static int hf_pcomascii_length;
42 static int hf_pcomascii_address_value;
43 static int hf_pcomascii_command;
44 static int hf_pcomascii_checksum;
45 static int hf_pcomascii_etx;
47 static int hf_pcombinary_stx;
48 static int hf_pcombinary_id;
49 static int hf_pcombinary_reserved1;
50 static int hf_pcombinary_reserved2;
51 static int hf_pcombinary_reserved3;
52 static int hf_pcombinary_command;
53 static int hf_pcombinary_reserved4;
54 static int hf_pcombinary_command_specific;
55 static int hf_pcombinary_data_length;
56 static int hf_pcombinary_header_checksum;
57 static int hf_pcombinary_data;
58 static int hf_pcombinary_footer_checksum;
59 static int hf_pcombinary_etx;
61 static expert_field ei_pcomtcp_reserved_bad_value;
62 static expert_field ei_pcomascii_command_unsupported;
63 static expert_field ei_pcombinary_reserved1_bad_value;
64 static expert_field ei_pcombinary_reserved2_bad_value;
65 static expert_field ei_pcombinary_reserved3_bad_value;
66 static expert_field ei_pcombinary_reserved4_bad_value;
67 static expert_field ei_pcombinary_command_unsupported;
69 /* Initialize the subtree pointers */
70 static int ett_pcomtcp;
71 static int ett_pcomascii;
72 static int ett_pcombinary;
74 static dissector_handle_t pcomtcp_handle;
75 static dissector_handle_t pcomascii_handle;
76 static dissector_handle_t pcombinary_handle;
78 /* PCOM/TCP definitions */
79 #define PCOMTCP_MIN_LENGTH 6
80 #define PCOMTCP_TCP_PORT 20256
81 #define PCOM_ASCII 101
82 #define PCOM_BINARY 102
84 static range_t *global_pcomtcp_tcp_ports; /* Port 20256, by default */
86 /* Translate pcomp_protocol to string */
87 static const value_string pcomp_protocol_vals[] = {
88 { PCOM_ASCII, "ASCII mode" },
89 { PCOM_BINARY, "Binary mode" },
90 { 0, NULL },
93 #define PCOMASCII_ID_COMMAND 0x4944 // "ID"
94 #define PCOMASCII_START_COMMAND 0x434352 // "CCR"
95 #define PCOMASCII_STOP_COMMAND 0x434353 // "CCS"
96 #define PCOMASCII_RESET_COMMAND 0x434345 // "CCE"
97 #define PCOMASCII_INIT_COMMAND 0x434349 // "CCI"
98 #define PCOMASCII_REPLY_ADMIN_COMMAND 0x4343 // "CC"
99 #define PCOMASCII_GET_UNITID 0x5547 // "UG"
100 #define PCOMASCII_SET_UNITID 0x5553 // "US"
101 #define PCOMASCII_GET_RTC 0x5243 // "RC"
102 #define PCOMASCII_SET_RTC 0x5343 // "SC"
103 #define PCOMASCII_READ_INPUTS 0x5245 // "RE"
104 #define PCOMASCII_READ_OUTPUTS 0x5241 // "RA"
105 #define PCOMASCII_READ_SYSTEM_BITS 0x4753 // "GS"
106 #define PCOMASCII_READ_SYSTEM_INTEGERS 0x4746 // "GF"
107 #define PCOMASCII_READ_SYSTEM_LONGS 0x524e48 // "RNH"
108 #define PCOMASCII_READ_SYSTEM_DOUBLE_WORDS 0x524e4a // "RNJ"
109 #define PCOMASCII_READ_MEMORY_BITS 0x5242 // "RB"
110 #define PCOMASCII_READ_MEMORY_INTEGERS 0x5257 // "RW"
111 #define PCOMASCII_READ_MEMORY_LONGS 0x524e4c // "RNL"
112 #define PCOMASCII_READ_MEMORY_DOUBLE_WORDS 0x524e44 // "RND"
113 #define PCOMASCII_READ_LONGS 0x524e // "RN"
114 #define PCOMASCII_WRITE_OUTPUTS 0x5341 // "SA"
115 #define PCOMASCII_WRITE_SYSTEM_BITS 0x5353 // "SS"
116 #define PCOMASCII_WRITE_SYSTEM_INTEGERS 0x5346 // "SF"
117 #define PCOMASCII_WRITE_SYSTEM_LONGS 0x534e48 // "SNH"
118 #define PCOMASCII_WRITE_SYSTEM_DOUBLE_WORDS 0x534e4a // "SNJ"
119 #define PCOMASCII_WRITE_MEMORY_BITS 0x5342 // "SB"
120 #define PCOMASCII_WRITE_MEMORY_INTEGERS 0x5357 // "SW"
121 #define PCOMASCII_WRITE_MEMORY_LONGS 0x534e4c // "SNL"
122 #define PCOMASCII_WRITE_MEMORY_DOUBLE_WORDS 0x534e44 // "SND"
123 #define PCOMASCII_WRITE_LONGS 0x534e // "SN"
125 #define PCOMBINARY_GET_PLC_NAME_REQUEST 0x0c
126 #define PCOMBINARY_GET_PLC_NAME_REPLY 0x8c
127 #define PCOMBINARY_READ_OPERANDS_REQUEST 0x4d
128 #define PCOMBINARY_READ_OPERANDS_REPLY 0xcd
129 #define PCOMBINARY_READ_DATA_TABLE_REQUEST 0x04
130 #define PCOMBINARY_READ_DATA_TABLE_REPLY 0x84
131 #define PCOMBINARY_WRITE_DATA_TABLE_REQUEST 0x44
132 #define PCOMBINARY_WRITE_DATA_TABLE_REPLY 0xc4
134 /* Translate pcomascii_command_code to string */
135 static const value_string pcomascii_cc_vals[] = {
136 { PCOMASCII_ID_COMMAND, "Send Identification Command" },
137 { PCOMASCII_START_COMMAND, "Send Start Command" },
138 { PCOMASCII_STOP_COMMAND, "Send Stop Command" },
139 { PCOMASCII_RESET_COMMAND, "Send Reset Command" },
140 { PCOMASCII_INIT_COMMAND, "Send Init Command" },
141 { PCOMASCII_REPLY_ADMIN_COMMAND, "Reply of Admin Commands (CC*)" },
142 { PCOMASCII_GET_UNITID, "Get UnitID" },
143 { PCOMASCII_SET_UNITID, "Set UnitID" },
144 { PCOMASCII_GET_RTC, "Get RTC" },
145 { PCOMASCII_SET_RTC, "Set RTC" },
146 { PCOMASCII_READ_INPUTS, "Read Inputs" },
147 { PCOMASCII_READ_OUTPUTS, "Read Outputs" },
148 { PCOMASCII_READ_SYSTEM_BITS, "Read System Bits" },
149 { PCOMASCII_READ_SYSTEM_INTEGERS, "Read System Integers" },
150 { PCOMASCII_READ_SYSTEM_LONGS, "Read System Longs" },
151 { PCOMASCII_READ_SYSTEM_DOUBLE_WORDS, "Read System Double Words" },
152 { PCOMASCII_READ_MEMORY_BITS, "Read Memory Bits" },
153 { PCOMASCII_READ_MEMORY_INTEGERS, "Read Memory Integers" },
154 { PCOMASCII_READ_MEMORY_LONGS, "Read Memory Longs" },
155 { PCOMASCII_READ_MEMORY_DOUBLE_WORDS, "Read Memory Double Words" },
156 { PCOMASCII_READ_LONGS, "Read Longs / Double Words" },
157 { PCOMASCII_WRITE_OUTPUTS, "Write Outputs" },
158 { PCOMASCII_WRITE_SYSTEM_BITS, "Write System Bits" },
159 { PCOMASCII_WRITE_SYSTEM_INTEGERS, "Write System Integers" },
160 { PCOMASCII_WRITE_SYSTEM_LONGS, "Write System Longs" },
161 { PCOMASCII_WRITE_SYSTEM_DOUBLE_WORDS,"Write System Double Words" },
162 { PCOMASCII_WRITE_MEMORY_BITS, "Write Memory Bits" },
163 { PCOMASCII_WRITE_MEMORY_INTEGERS, "Write Memory Integers" },
164 { PCOMASCII_WRITE_MEMORY_LONGS, "Write Memory Longs" },
165 { PCOMASCII_WRITE_MEMORY_DOUBLE_WORDS,"Write Memory Double Words" },
166 { PCOMASCII_WRITE_LONGS, "Write Longs / Double Words" },
167 { 0, NULL },
170 /* Translate pcombinary_command requests to string */
171 static const value_string pcombinary_command_vals_request[] = {
172 { PCOMBINARY_GET_PLC_NAME_REQUEST, "Get PLC Name Request" },
173 { PCOMBINARY_READ_OPERANDS_REQUEST, "Read Operands Request" },
174 { PCOMBINARY_READ_DATA_TABLE_REQUEST, "Read Data Table Request" },
175 { PCOMBINARY_WRITE_DATA_TABLE_REQUEST, "Write Data Table Request" },
176 { 0, NULL },
179 /* Translate pcombinary_command reply to string */
180 static const value_string pcombinary_command_vals_reply[] = {
181 { PCOMBINARY_GET_PLC_NAME_REPLY, "Get PLC Name Reply" },
182 { PCOMBINARY_READ_OPERANDS_REPLY, "Read Operands Reply" },
183 { PCOMBINARY_READ_DATA_TABLE_REPLY, "Read Data Table Reply" },
184 { PCOMBINARY_WRITE_DATA_TABLE_REPLY, "Write Data Table Reply" },
185 { 0, NULL },
189 /* Code to actually dissect the packets */
190 static int
191 dissect_pcomtcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
192 void *data _U_)
194 /* Set up structures needed to add the protocol subtree and manage it */
195 proto_item *ti;
196 proto_tree *pcomtcp_tree;
198 tvbuff_t *next_tvb;
200 unsigned offset = 0;
201 const char *pkt_type;
202 uint8_t pcom_mode;
203 const char *pcom_mode_str;
205 proto_item *hf_pcomtcp_reserved_item = NULL;
207 /* Check that the packet is long enough for it to belong to us. */
208 if (tvb_reported_length(tvb) < PCOMTCP_MIN_LENGTH)
209 return 0;
211 pcom_mode = tvb_get_uint8(tvb, 2);
212 if ( pcom_mode != PCOM_ASCII && pcom_mode != PCOM_BINARY )
213 return 0;
215 pcom_mode_str = val_to_str(pcom_mode, pcomp_protocol_vals, "Unknown mode (%d)");
217 if (value_is_in_range(global_pcomtcp_tcp_ports, pinfo->srcport))
218 pkt_type = "Reply";
219 else
220 pkt_type = "Query";
222 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PCOM/TCP");
223 col_clear(pinfo->cinfo, COL_INFO);
224 col_add_fstr(pinfo->cinfo, COL_INFO, "%s in %s",
225 pkt_type, pcom_mode_str);
228 /* create display subtree for the protocol */
229 ti = proto_tree_add_item(tree, proto_pcomtcp, tvb, 0, -1, ENC_NA);
230 pcomtcp_tree = proto_item_add_subtree(ti, ett_pcomtcp);
232 proto_tree_add_item(pcomtcp_tree, hf_pcomtcp_transid, tvb,
233 offset, 2, ENC_LITTLE_ENDIAN);
234 offset += 2;
235 proto_tree_add_item(pcomtcp_tree, hf_pcomtcp_protocol, tvb,
236 offset, 1, ENC_NA);
237 offset += 1;
238 hf_pcomtcp_reserved_item = proto_tree_add_item(pcomtcp_tree, hf_pcomtcp_reserved, tvb,
239 offset, 1, ENC_NA);
240 if(tvb_get_uint8(tvb, offset) !=0){
241 expert_add_info_format(pinfo, hf_pcomtcp_reserved_item,
242 &ei_pcomtcp_reserved_bad_value,"Isn't 0");
244 offset += 1;
245 proto_tree_add_item(pcomtcp_tree, hf_pcomtcp_length, tvb,
246 offset, 2, ENC_LITTLE_ENDIAN);
248 /* dissect the PCOM Data */
249 offset += 2;
250 next_tvb = tvb_new_subset_remaining(tvb, offset);
251 if( tvb_reported_length_remaining(tvb, offset) > 0 ){
252 if ( pcom_mode == PCOM_ASCII)
253 call_dissector_with_data(pcomascii_handle, next_tvb, pinfo, tree, &pcom_mode);
254 else
255 call_dissector_with_data(pcombinary_handle, next_tvb, pinfo, tree, &pcom_mode);
258 return tvb_reported_length(tvb);
261 static int
262 dissect_pcomascii(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
263 void *data _U_)
265 /* Set up structures needed to add the protocol subtree and manage it */
266 proto_item *ti;
267 proto_tree *pcomascii_tree;
268 proto_item *hf_pcomascii_command_item = NULL;
270 unsigned offset = 0;
271 uint16_t nvalues;
272 uint8_t i;
273 uint8_t cc_len;
274 uint32_t cc;
275 const char* cc_str;
276 const char* cc_str2;
277 uint8_t op_type;
278 uint8_t op_size;
280 /* Create protocol tree */
281 ti = proto_tree_add_item(tree, proto_pcomascii, tvb, offset, -1, ENC_NA);
282 pcomascii_tree = proto_item_add_subtree(ti, ett_pcomascii);
284 if (value_is_in_range(global_pcomtcp_tcp_ports, pinfo->srcport)) { // Reply
285 proto_tree_add_item(pcomascii_tree, hf_pcomascii_stx, tvb,
286 offset, 2, ENC_ASCII); // "/A"
287 offset += 2;
288 }else{
289 proto_tree_add_item(pcomascii_tree, hf_pcomascii_stx, tvb,
290 offset, 1, ENC_ASCII); // "/"
291 offset += 1;
294 proto_tree_add_item(pcomascii_tree, hf_pcomascii_unitid, tvb,
295 offset, 2, ENC_ASCII|ENC_NA);
296 offset += 2;
298 // CCs can be 2 or 3 hex chars
299 cc = tvb_get_ntoh24(tvb, offset);
300 cc_str = try_val_to_str(cc, pcomascii_cc_vals);
301 if ( cc_str != NULL && !value_is_in_range(global_pcomtcp_tcp_ports, pinfo->srcport)) {
302 cc_len = 3;
303 }else {
304 cc = tvb_get_ntohs(tvb, offset);
305 cc_str = try_val_to_str(cc, pcomascii_cc_vals);
306 if (cc_str != NULL ){
307 cc_len = 2;
308 }else{
309 cc_len = 0;
312 if ( cc_len > 0 ){
313 cc_str2 = tvb_get_string_enc(pinfo->pool, tvb, offset, cc_len, ENC_ASCII);
314 proto_tree_add_string_format_value(pcomascii_tree,
315 hf_pcomascii_command_code, tvb, offset, cc_len,
316 cc_str2, "%s (%s)", cc_str, cc_str2);
317 offset += cc_len;
318 switch(cc)
320 case PCOMASCII_READ_INPUTS:
321 case PCOMASCII_READ_OUTPUTS:
322 case PCOMASCII_READ_SYSTEM_BITS:
323 case PCOMASCII_READ_MEMORY_BITS:
324 op_type = 1; // read operation
325 op_size = 1; // 1 char per operand
326 break;
327 case PCOMASCII_READ_SYSTEM_INTEGERS:
328 case PCOMASCII_READ_MEMORY_INTEGERS:
329 op_type = 1; // read operation
330 op_size = 4; // 4 chars per operand
331 break;
332 case PCOMASCII_READ_SYSTEM_LONGS:
333 case PCOMASCII_READ_MEMORY_LONGS:
334 case PCOMASCII_READ_SYSTEM_DOUBLE_WORDS:
335 case PCOMASCII_READ_MEMORY_DOUBLE_WORDS:
336 case PCOMASCII_READ_LONGS:
337 op_type = 1; // read operation
338 op_size = 8; // 8 chars per operand
339 break;
340 case PCOMASCII_WRITE_OUTPUTS:
341 case PCOMASCII_WRITE_SYSTEM_BITS:
342 case PCOMASCII_WRITE_MEMORY_BITS:
343 op_type = 2; // write operation
344 op_size = 1; // 1 char per operand
345 break;
346 case PCOMASCII_WRITE_SYSTEM_INTEGERS:
347 case PCOMASCII_WRITE_MEMORY_INTEGERS:
348 op_type = 2; // write operation
349 op_size = 4; // 4 chars per operand
350 break;
351 case PCOMASCII_WRITE_MEMORY_LONGS:
352 case PCOMASCII_WRITE_SYSTEM_LONGS:
353 case PCOMASCII_WRITE_SYSTEM_DOUBLE_WORDS:
354 case PCOMASCII_WRITE_MEMORY_DOUBLE_WORDS:
355 case PCOMASCII_WRITE_LONGS:
356 op_type = 2; // write operation
357 op_size = 8; // 8 chars per operand
358 break;
359 default:
360 op_type = 0;
361 op_size = 0;
362 break;
364 if (value_is_in_range(global_pcomtcp_tcp_ports, pinfo->destport)) { // Request
365 if(op_type == 1 || op_type == 2) { // read & write op
366 proto_tree_add_item(pcomascii_tree, hf_pcomascii_address,
367 tvb, offset, 4, ENC_ASCII);
368 offset += 4;
369 proto_tree_add_item(pcomascii_tree, hf_pcomascii_length,
370 tvb, offset, 2, ENC_ASCII);
371 offset += 2;
373 if(op_type == 2) { // write only
374 nvalues = (tvb_reported_length(tvb)-3-offset) / op_size;
375 for (i = 0; i < nvalues; i++) {
376 proto_tree_add_item(pcomascii_tree, hf_pcomascii_address_value,
377 tvb, offset, op_size , ENC_ASCII);
378 offset += op_size;
381 } else { // reply
382 if(op_type == 1) { // read only
383 nvalues = (tvb_reported_length(tvb)-offset-3) / op_size;
384 for (i = 0; i < nvalues; i++) {
385 proto_tree_add_item(pcomascii_tree, hf_pcomascii_address_value,
386 tvb, offset, op_size , ENC_ASCII);
387 offset += op_size;
394 if (tvb_reported_length(tvb)-offset-3 > 0){ // remaining (variable) bytes between CC and checksum
395 hf_pcomascii_command_item = proto_tree_add_item(pcomascii_tree, hf_pcomascii_command, tvb,
396 offset, tvb_reported_length(tvb)-offset-3, ENC_ASCII);
397 offset += (tvb_reported_length(tvb)-offset-3); //-3 from checksum and etx
398 if(cc_len <= 0){
399 expert_add_info_format(pinfo, hf_pcomascii_command_item,
400 &ei_pcomascii_command_unsupported, "Unsupported Command");
404 proto_tree_add_item(pcomascii_tree, hf_pcomascii_checksum, tvb,
405 offset, 2, ENC_LITTLE_ENDIAN);
406 offset += 2;
407 proto_tree_add_item(pcomascii_tree, hf_pcomascii_etx, tvb,
408 offset, 1, ENC_ASCII);
410 return tvb_reported_length(tvb);
413 static int
414 dissect_pcombinary(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
415 void *data _U_)
417 /* Set up structures needed to add the protocol subtree and manage it */
418 proto_item *ti;
419 proto_tree *pcombinary_tree;
421 unsigned offset = 0;
422 proto_item *hf_pcombinary_reserved1_item = NULL;
423 proto_item *hf_pcombinary_reserved2_item = NULL;
424 proto_item *hf_pcombinary_reserved3_item = NULL;
425 proto_item *hf_pcombinary_reserved4_item = NULL;
426 proto_item *hf_pcombinary_command_item = NULL;
428 uint8_t command;
429 const char* command_str;
431 /* Create protocol tree */
432 ti = proto_tree_add_item(tree, proto_pcombinary, tvb, offset, -1, ENC_NA);
433 pcombinary_tree = proto_item_add_subtree(ti, ett_pcombinary);
435 proto_tree_add_item(pcombinary_tree, hf_pcombinary_stx, tvb,
436 offset, 6, ENC_ASCII);
438 offset += 6;
439 if (value_is_in_range(global_pcomtcp_tcp_ports, pinfo->srcport)) { // these bytes are transposed
440 hf_pcombinary_reserved1_item = proto_tree_add_item(pcombinary_tree,
441 hf_pcombinary_reserved1, tvb, offset, 1, ENC_NA);
442 if(tvb_get_uint8(tvb, offset) !=254){
443 expert_add_info_format(pinfo, hf_pcombinary_reserved1_item,
444 &ei_pcombinary_reserved1_bad_value,"Isn't 0xfe");
446 offset += 1;
447 proto_tree_add_item(pcombinary_tree, hf_pcombinary_id, tvb,
448 offset, 1, ENC_NA);
449 offset += 1;
450 }else{
451 proto_tree_add_item(pcombinary_tree, hf_pcombinary_id, tvb,
452 offset, 1, ENC_NA);
453 offset += 1;
454 proto_tree_add_item(pcombinary_tree, hf_pcombinary_reserved1, tvb,
455 offset, 1, ENC_NA);
456 offset += 1;
458 hf_pcombinary_reserved2_item = proto_tree_add_item(pcombinary_tree,
459 hf_pcombinary_reserved2, tvb, offset, 1, ENC_NA);
460 if( tvb_get_uint8(tvb, offset) !=1)
461 expert_add_info_format(pinfo, hf_pcombinary_reserved2_item,
462 &ei_pcombinary_reserved2_bad_value,"Isn't 1");
463 offset += 1;
464 hf_pcombinary_reserved3_item = proto_tree_add_item(pcombinary_tree,
465 hf_pcombinary_reserved3, tvb, offset, 3, ENC_LITTLE_ENDIAN);
466 if( tvb_get_letoh24(tvb,offset) != 0)
467 expert_add_info_format(pinfo, hf_pcombinary_reserved3_item,
468 &ei_pcombinary_reserved3_bad_value,"Isn't 0");
469 offset += 3;
471 command = tvb_get_uint8(tvb, offset);
472 if (value_is_in_range(global_pcomtcp_tcp_ports, pinfo->srcport)) { // reply
473 command_str = try_val_to_str(command, pcombinary_command_vals_reply);
474 }else{
475 command_str = try_val_to_str(command, pcombinary_command_vals_request);
477 if ( command_str != NULL ) {
478 proto_tree_add_uint_format_value(pcombinary_tree,
479 hf_pcombinary_command, tvb, offset, 1,
480 command, "%s (%02x)", command_str, command);
481 }else{
482 hf_pcombinary_command_item = proto_tree_add_item(pcombinary_tree, hf_pcombinary_command, tvb,
483 offset, 1, ENC_NA);
484 expert_add_info_format(pinfo, hf_pcombinary_command_item,
485 &ei_pcombinary_command_unsupported,"Unsupported Command");}
486 offset += 1;
488 hf_pcombinary_reserved4_item = proto_tree_add_item(pcombinary_tree,
489 hf_pcombinary_reserved4, tvb, offset, 1, ENC_NA);
490 if( tvb_get_uint8(tvb, offset) !=0)
491 expert_add_info_format(pinfo, hf_pcombinary_reserved4_item,
492 &ei_pcombinary_reserved4_bad_value,"Isn't 0");
493 offset += 1;
494 proto_tree_add_item(pcombinary_tree, hf_pcombinary_command_specific, tvb,
495 offset, 6, ENC_NA);
496 offset += 6;
497 proto_tree_add_item(pcombinary_tree, hf_pcombinary_data_length, tvb,
498 offset, 2, ENC_LITTLE_ENDIAN);
499 offset += 2;
500 proto_tree_add_item(pcombinary_tree, hf_pcombinary_header_checksum, tvb,
501 offset, 2, ENC_NA);
502 offset += 2;
503 if ((tvb_reported_length(tvb) - 27) > 0) // ( -3 footer - 24 header)
504 proto_tree_add_item(pcombinary_tree, hf_pcombinary_data, tvb,
505 offset, tvb_reported_length(tvb)-27, ENC_NA);
506 offset += (tvb_reported_length(tvb)-27);
507 proto_tree_add_item(pcombinary_tree, hf_pcombinary_footer_checksum, tvb,
508 offset, 2, ENC_LITTLE_ENDIAN);
509 offset += 2;
510 proto_tree_add_item(pcombinary_tree, hf_pcombinary_etx, tvb,
511 offset, 1, ENC_ASCII);
513 return tvb_reported_length(tvb);
516 static void
517 apply_pcomtcp_prefs(void)
519 global_pcomtcp_tcp_ports = prefs_get_range_value("pcomtcp", "tcp.port");
522 void
523 proto_register_pcomtcp(void)
525 static hf_register_info hf_pcomtcp[] = {
526 { &hf_pcomtcp_transid,
527 { "Transaction Identifier", "pcomtcp.trans_id",
528 FT_UINT16, BASE_DEC, NULL, 0x0,
529 NULL, HFILL }
531 { &hf_pcomtcp_protocol,
532 { "Protocol Mode", "pcomtcp.protocol",
533 FT_UINT8, BASE_DEC, VALS(pcomp_protocol_vals), 0x0,
534 NULL, HFILL }
536 { &hf_pcomtcp_reserved,
537 { "Reserved", "pcomtcp.reserved",
538 FT_UINT8, BASE_DEC, NULL, 0x0,
539 NULL, HFILL }
541 { &hf_pcomtcp_length,
542 { "Length (bytes)", "pcomtcp.length",
543 FT_UINT16, BASE_DEC, NULL, 0x0,
544 NULL, HFILL }
549 static hf_register_info hf_pcomascii[] = {
550 { &hf_pcomascii_stx,
551 { "STX", "pcomascii.stx",
552 FT_STRING, BASE_NONE, NULL, 0x0,
553 NULL, HFILL }
555 { &hf_pcomascii_unitid,
556 { "Unit Identifier", "pcomascii.unitid",
557 FT_UINT16, BASE_HEX, NULL, 0x0,
558 NULL, HFILL }
560 { &hf_pcomascii_command_code,
561 { "Command Code", "pcomascii.command_code",
562 FT_STRING, BASE_NONE, NULL, 0x0,
563 NULL, HFILL }
565 { &hf_pcomascii_address,
566 { "Address", "pcomascii.address",
567 FT_STRING, BASE_NONE, NULL, 0x0,
568 NULL, HFILL }
570 { &hf_pcomascii_length,
571 { "Length", "pcomascii.length",
572 FT_STRING, BASE_NONE, NULL, 0x0,
573 NULL, HFILL }
575 { &hf_pcomascii_address_value,
576 { "Address Value", "pcomascii.address_value",
577 FT_STRING, BASE_NONE, NULL, 0x0,
578 NULL, HFILL }
580 { &hf_pcomascii_command,
581 { "Command", "pcomascii.command",
582 FT_STRING, BASE_NONE, NULL, 0x0,
583 NULL, HFILL }
585 { &hf_pcomascii_checksum,
586 { "Checksum", "pcomascii.checksum",
587 FT_UINT16, BASE_HEX, NULL, 0x0,
588 NULL, HFILL }
590 { &hf_pcomascii_etx,
591 { "ETX", "pcomascii.etx",
592 FT_STRING, BASE_NONE, NULL, 0x0,
593 NULL, HFILL }
598 static hf_register_info hf_pcombinary[] = {
599 { &hf_pcombinary_stx,
600 { "STX", "pcombinary.stx",
601 FT_STRING, BASE_NONE, NULL, 0x0,
602 NULL, HFILL }
604 { &hf_pcombinary_id,
605 { "ID (CANBUS or RS485)", "pcombinary.id",
606 FT_UINT8, BASE_DEC, NULL, 0x0,
607 NULL, HFILL }
609 { &hf_pcombinary_reserved1,
610 { "Reserved", "pcombinary.reserved1",
611 FT_UINT8, BASE_HEX, NULL, 0x0,
612 NULL, HFILL }
614 { &hf_pcombinary_reserved2,
615 { "Reserved", "pcombinary.reserved2",
616 FT_UINT8, BASE_HEX, NULL, 0x0,
617 NULL, HFILL }
619 { &hf_pcombinary_reserved3,
620 { "Reserved", "pcombinary.reserved3",
621 FT_UINT24, BASE_HEX, NULL, 0x0,
622 NULL, HFILL }
624 { &hf_pcombinary_command,
625 { "Command", "pcombinary.command",
626 FT_UINT8, BASE_HEX, NULL, 0x0,
627 NULL, HFILL }
629 { &hf_pcombinary_reserved4,
630 { "Reserved", "pcombinary.reserved0",
631 FT_UINT8, BASE_HEX, NULL, 0x0,
632 NULL, HFILL }
634 { &hf_pcombinary_command_specific,
635 { "Command Details", "pcombinary.command_specific",
636 FT_BYTES, BASE_NONE, NULL, 0x0,
637 NULL, HFILL }
639 { &hf_pcombinary_data_length,
640 { "Data Length", "pcombinary.data_length",
641 FT_UINT16, BASE_DEC, NULL, 0x0,
642 NULL, HFILL }
644 { &hf_pcombinary_header_checksum,
645 { "(Header) Checksum", "pcombinary.header_checksum",
646 FT_UINT16, BASE_HEX, NULL, 0x0,
647 NULL, HFILL }
649 { &hf_pcombinary_data,
650 { "Data", "pcombinary.data",
651 FT_BYTES, BASE_NONE, NULL, 0x0,
652 NULL, HFILL }
654 { &hf_pcombinary_footer_checksum,
655 { "(Footer) Checksum", "pcombinary.footer_checksum",
656 FT_UINT16, BASE_HEX, NULL, 0x0,
657 NULL, HFILL }
659 { &hf_pcombinary_etx,
660 { "ETX", "pcombinary.etx",
661 FT_STRING, BASE_NONE, NULL, 0x0,
662 NULL, HFILL }
666 /* Setup protocol subtree array */
667 static int *ett[] = {
668 &ett_pcomtcp,
669 &ett_pcomascii,
670 &ett_pcombinary
673 static ei_register_info pcomtcp_ei[] = {
674 { &ei_pcomtcp_reserved_bad_value,
675 { "pcombinary.reserved.bad_value", PI_PROTOCOL, PI_WARN,
676 "Isn't 0", EXPFILL }
680 static ei_register_info pcombinary_ei[] = {
681 { &ei_pcombinary_reserved1_bad_value,
682 { "pcombinary.reserved1.bad_value", PI_PROTOCOL, PI_WARN,
683 "Isn't 0xfe", EXPFILL }
685 { &ei_pcombinary_reserved2_bad_value,
686 { "pcombinary.reserved2.bad_value", PI_PROTOCOL, PI_WARN,
687 "Isn't 1", EXPFILL }
689 { &ei_pcombinary_reserved3_bad_value,
690 { "pcombinary.reserved3.bad_value", PI_PROTOCOL, PI_WARN,
691 "Isn't 0", EXPFILL }
693 { &ei_pcombinary_reserved4_bad_value,
694 { "pcombinary.reserved4.bad_value", PI_PROTOCOL, PI_WARN,
695 "Isn't 0", EXPFILL }
697 { &ei_pcombinary_command_unsupported,
698 { "pcombinary.command.unsupported", PI_PROTOCOL, PI_WARN,
699 "Unsupported Command", EXPFILL }
702 static ei_register_info pcomascii_ei[] = {
703 { &ei_pcomascii_command_unsupported,
704 { "pcomascii.command.unsupported", PI_PROTOCOL, PI_WARN,
705 "Unsupported Command", EXPFILL }
709 expert_module_t* expert_pcomtcp;
710 expert_module_t* expert_pcomascii;
711 expert_module_t* expert_pcombinary;
713 /* Register the protocol name and description */
714 proto_pcomtcp = proto_register_protocol("PCOM/TCP","PCOM/TCP", "pcomtcp");
715 proto_pcomascii = proto_register_protocol("PCOM ASCII","PCOM ASCII", "pcomascii");
716 proto_pcombinary = proto_register_protocol("PCOM BINARY","PCOM BINARY", "pcombinary");
718 pcomtcp_handle = register_dissector("pcomtcp", dissect_pcomtcp, proto_pcomtcp);
719 pcomascii_handle = register_dissector("pcomascii", dissect_pcomascii, proto_pcomascii);
720 pcombinary_handle = register_dissector("pcombinary", dissect_pcombinary, proto_pcombinary);
722 /* Required function calls to register the header fields and subtrees */
723 proto_register_field_array(proto_pcomtcp, hf_pcomtcp, array_length(hf_pcomtcp));
724 proto_register_field_array(proto_pcomascii, hf_pcomascii, array_length(hf_pcomascii));
725 proto_register_field_array(proto_pcombinary, hf_pcombinary, array_length(hf_pcombinary));
727 proto_register_subtree_array(ett, array_length(ett));
728 expert_pcomtcp = expert_register_protocol(proto_pcomtcp);
729 expert_pcomascii = expert_register_protocol(proto_pcomascii);
730 expert_pcombinary = expert_register_protocol(proto_pcombinary);
732 expert_register_field_array(expert_pcomtcp, pcomtcp_ei, array_length(pcomtcp_ei));
733 expert_register_field_array(expert_pcomascii, pcomascii_ei, array_length(pcomascii_ei));
734 expert_register_field_array(expert_pcombinary, pcombinary_ei, array_length(pcombinary_ei));
736 prefs_register_protocol(proto_pcomtcp, apply_pcomtcp_prefs);
740 void
741 proto_reg_handoff_pcomtcp(void)
743 dissector_add_uint_with_preference("tcp.port", PCOMTCP_TCP_PORT, pcomtcp_handle);
744 apply_pcomtcp_prefs();
748 * Editor modelines - https://www.wireshark.org/tools/modelines.html
750 * Local variables:
751 * c-basic-offset: 4
752 * tab-width: 8
753 * indent-tabs-mode: nil
754 * End:
756 * vi: set shiftwidth=4 tabstop=8 expandtab:
757 * :indentSize=4:tabSize=8:noTabs=true: