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
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" },
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" },
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" },
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" },
189 /* Code to actually dissect the packets */
191 dissect_pcomtcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
194 /* Set up structures needed to add the protocol subtree and manage it */
196 proto_tree
*pcomtcp_tree
;
201 const char *pkt_type
;
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
)
211 pcom_mode
= tvb_get_uint8(tvb
, 2);
212 if ( pcom_mode
!= PCOM_ASCII
&& pcom_mode
!= PCOM_BINARY
)
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
))
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
);
235 proto_tree_add_item(pcomtcp_tree
, hf_pcomtcp_protocol
, tvb
,
238 hf_pcomtcp_reserved_item
= proto_tree_add_item(pcomtcp_tree
, hf_pcomtcp_reserved
, tvb
,
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");
245 proto_tree_add_item(pcomtcp_tree
, hf_pcomtcp_length
, tvb
,
246 offset
, 2, ENC_LITTLE_ENDIAN
);
248 /* dissect the PCOM Data */
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
);
255 call_dissector_with_data(pcombinary_handle
, next_tvb
, pinfo
, tree
, &pcom_mode
);
258 return tvb_reported_length(tvb
);
262 dissect_pcomascii(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
265 /* Set up structures needed to add the protocol subtree and manage it */
267 proto_tree
*pcomascii_tree
;
268 proto_item
*hf_pcomascii_command_item
= NULL
;
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"
289 proto_tree_add_item(pcomascii_tree
, hf_pcomascii_stx
, tvb
,
290 offset
, 1, ENC_ASCII
); // "/"
294 proto_tree_add_item(pcomascii_tree
, hf_pcomascii_unitid
, tvb
,
295 offset
, 2, ENC_ASCII
|ENC_NA
);
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
)) {
304 cc
= tvb_get_ntohs(tvb
, offset
);
305 cc_str
= try_val_to_str(cc
, pcomascii_cc_vals
);
306 if (cc_str
!= NULL
){
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
);
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
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
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
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
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
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
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
);
369 proto_tree_add_item(pcomascii_tree
, hf_pcomascii_length
,
370 tvb
, offset
, 2, ENC_ASCII
);
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
);
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
);
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
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
);
407 proto_tree_add_item(pcomascii_tree
, hf_pcomascii_etx
, tvb
,
408 offset
, 1, ENC_ASCII
);
410 return tvb_reported_length(tvb
);
414 dissect_pcombinary(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
417 /* Set up structures needed to add the protocol subtree and manage it */
419 proto_tree
*pcombinary_tree
;
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
;
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
);
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");
447 proto_tree_add_item(pcombinary_tree
, hf_pcombinary_id
, tvb
,
451 proto_tree_add_item(pcombinary_tree
, hf_pcombinary_id
, tvb
,
454 proto_tree_add_item(pcombinary_tree
, hf_pcombinary_reserved1
, tvb
,
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");
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");
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
);
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
);
482 hf_pcombinary_command_item
= proto_tree_add_item(pcombinary_tree
, hf_pcombinary_command
, tvb
,
484 expert_add_info_format(pinfo
, hf_pcombinary_command_item
,
485 &ei_pcombinary_command_unsupported
,"Unsupported Command");}
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");
494 proto_tree_add_item(pcombinary_tree
, hf_pcombinary_command_specific
, tvb
,
497 proto_tree_add_item(pcombinary_tree
, hf_pcombinary_data_length
, tvb
,
498 offset
, 2, ENC_LITTLE_ENDIAN
);
500 proto_tree_add_item(pcombinary_tree
, hf_pcombinary_header_checksum
, tvb
,
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
);
510 proto_tree_add_item(pcombinary_tree
, hf_pcombinary_etx
, tvb
,
511 offset
, 1, ENC_ASCII
);
513 return tvb_reported_length(tvb
);
517 apply_pcomtcp_prefs(void)
519 global_pcomtcp_tcp_ports
= prefs_get_range_value("pcomtcp", "tcp.port");
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,
531 { &hf_pcomtcp_protocol
,
532 { "Protocol Mode", "pcomtcp.protocol",
533 FT_UINT8
, BASE_DEC
, VALS(pcomp_protocol_vals
), 0x0,
536 { &hf_pcomtcp_reserved
,
537 { "Reserved", "pcomtcp.reserved",
538 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
541 { &hf_pcomtcp_length
,
542 { "Length (bytes)", "pcomtcp.length",
543 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
549 static hf_register_info hf_pcomascii
[] = {
551 { "STX", "pcomascii.stx",
552 FT_STRING
, BASE_NONE
, NULL
, 0x0,
555 { &hf_pcomascii_unitid
,
556 { "Unit Identifier", "pcomascii.unitid",
557 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
560 { &hf_pcomascii_command_code
,
561 { "Command Code", "pcomascii.command_code",
562 FT_STRING
, BASE_NONE
, NULL
, 0x0,
565 { &hf_pcomascii_address
,
566 { "Address", "pcomascii.address",
567 FT_STRING
, BASE_NONE
, NULL
, 0x0,
570 { &hf_pcomascii_length
,
571 { "Length", "pcomascii.length",
572 FT_STRING
, BASE_NONE
, NULL
, 0x0,
575 { &hf_pcomascii_address_value
,
576 { "Address Value", "pcomascii.address_value",
577 FT_STRING
, BASE_NONE
, NULL
, 0x0,
580 { &hf_pcomascii_command
,
581 { "Command", "pcomascii.command",
582 FT_STRING
, BASE_NONE
, NULL
, 0x0,
585 { &hf_pcomascii_checksum
,
586 { "Checksum", "pcomascii.checksum",
587 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
591 { "ETX", "pcomascii.etx",
592 FT_STRING
, BASE_NONE
, NULL
, 0x0,
598 static hf_register_info hf_pcombinary
[] = {
599 { &hf_pcombinary_stx
,
600 { "STX", "pcombinary.stx",
601 FT_STRING
, BASE_NONE
, NULL
, 0x0,
605 { "ID (CANBUS or RS485)", "pcombinary.id",
606 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
609 { &hf_pcombinary_reserved1
,
610 { "Reserved", "pcombinary.reserved1",
611 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
614 { &hf_pcombinary_reserved2
,
615 { "Reserved", "pcombinary.reserved2",
616 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
619 { &hf_pcombinary_reserved3
,
620 { "Reserved", "pcombinary.reserved3",
621 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
624 { &hf_pcombinary_command
,
625 { "Command", "pcombinary.command",
626 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
629 { &hf_pcombinary_reserved4
,
630 { "Reserved", "pcombinary.reserved0",
631 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
634 { &hf_pcombinary_command_specific
,
635 { "Command Details", "pcombinary.command_specific",
636 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
639 { &hf_pcombinary_data_length
,
640 { "Data Length", "pcombinary.data_length",
641 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
644 { &hf_pcombinary_header_checksum
,
645 { "(Header) Checksum", "pcombinary.header_checksum",
646 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
649 { &hf_pcombinary_data
,
650 { "Data", "pcombinary.data",
651 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
654 { &hf_pcombinary_footer_checksum
,
655 { "(Footer) Checksum", "pcombinary.footer_checksum",
656 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
659 { &hf_pcombinary_etx
,
660 { "ETX", "pcombinary.etx",
661 FT_STRING
, BASE_NONE
, NULL
, 0x0,
666 /* Setup protocol subtree array */
667 static int *ett
[] = {
673 static ei_register_info pcomtcp_ei
[] = {
674 { &ei_pcomtcp_reserved_bad_value
,
675 { "pcombinary.reserved.bad_value", PI_PROTOCOL
, PI_WARN
,
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
,
689 { &ei_pcombinary_reserved3_bad_value
,
690 { "pcombinary.reserved3.bad_value", PI_PROTOCOL
, PI_WARN
,
693 { &ei_pcombinary_reserved4_bad_value
,
694 { "pcombinary.reserved4.bad_value", PI_PROTOCOL
, PI_WARN
,
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
);
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
753 * indent-tabs-mode: nil
756 * vi: set shiftwidth=4 tabstop=8 expandtab:
757 * :indentSize=4:tabSize=8:noTabs=true: