2 * Routines for the Check Point High-Availability Protocol (CPHAP)
3 * Copyright 2002, Yaniv Kaul <mykaul -at- 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>
16 void proto_register_cpha(void);
17 void proto_reg_handoff_cpha(void);
19 static dissector_handle_t cpha_handle
;
21 static int proto_cphap
;
23 static int hf_magic_number
;
24 static int hf_cpha_protocol_ver
;
25 static int hf_cluster_number
;
27 static int hf_payload
;
28 static int hf_src_if_num
;
29 static int hf_random_id
;
30 static int hf_src_machine_id
;
31 static int hf_dst_machine_id
;
32 static int hf_policy_id
;
34 static int hf_unknown_data
;
36 static int hf_report_code
;
37 static int hf_ha_mode
;
38 static int hf_ha_time_unit
;
39 static int hf_machine_states
;
40 static int hf_state_node
;
41 static int hf_interface_states
;
42 static int hf_num_reported_ifs
;
43 static int hf_ethernet_add
;
44 static int hf_is_if_trusted
;
46 static int hf_slot_num
;
47 static int hf_machine_num
;
49 static int hf_hash_len
;
51 static int hf_in_up_num
;
52 static int hf_in_assumed_up_num
;
53 static int hf_out_up_num
;
54 static int hf_out_assumed_up_num
;
55 static int hf_cluster_last_packet
;
60 #define UDP_PORT_CPHA 8116
61 #define CPHA_MAGIC 0x1A90
64 static const value_string opcode_type_short_vals
[] = {
66 { 1, "FWHA_MY_STATE" },
67 { 2, "FWHA_QUERY_STATE" },
68 { 3, "FWHA_IF_PROBE_REQ" },
69 { 4, "FWHA_IF_PROBE_REPLY" },
70 { 5, "FWHA_IFCONF_REQ" },
71 { 6, "FWHA_IFCONF_REPLY" },
72 { 7, "FWHA_LB_CONF" },
73 { 8, "FWHA_LB_CONFIRM" },
74 { 9, "FWHA_POLICY_CHANGE" },
80 static const value_string opcode_type_vals
[] = {
81 { 0, "Unknown OpCode" },
82 { 1, "FWHA_MY_STATE - Report source machine's state" },
83 { 2, "FWHA_QUERY_STATE - Query other machine's state" },
84 { 3, "FWHA_IF_PROBE_REQ - Interface active check request" },
85 { 4, "FWHA_IF_PROBE_REPLY - Interface active check reply" },
86 { 5, "FWHA_IFCONF_REQ - Interface configuration request" },
87 { 6, "FWHA_IFCONF_REPLY - Interface configuration reply" },
88 { 7, "FWHA_LB_CONF - LB configuration report request" },
89 { 8, "FWHA_LB_CONFIRM - LB configuration report reply" },
90 { 9, "FWHA_POLICY_CHANGE - Policy ID change request/notification" },
91 { 10, "FWHAP_SYNC - New Sync packet" },
95 static const value_string state_vals
[] = {
97 { 1, "Initializing" },
100 { 4, "Active/Active-Attention" },
104 static const value_string status_vals
[] = {
105 { 1, "New policy arrived - no need to modify HA configuration" },
106 { 2, "New policy arrived - need to modify HA configuration" },
107 { 3, "Ready to change configuration" },
111 static const value_string ha_mode_vals
[] = {
112 { 0, "FWHA_UNDEF_MODE" },
113 { 1, "FWHA_NOT_ACTIVE_MODE - CPHA is not active" },
114 { 2, "FWHA_BALANCE_MODE - More than one machine active" },
115 { 3, "FWHA_PRIMARY_UP_MODE" },
116 { 4, "FWHA_ONE_UP_MODE" },
120 static const value_string ha_version_vals
[] = {
126 { 534, "VSX NG AIR2" },
127 { 537, "VSX NGX EA" },
128 { 538, "VSX NGX GA" },
129 { 540, "NG AIR54 EA" },
130 { 541, "NG AIR54 GA" },
131 { 550, "NG AIR55 (up to HFA_16)" },
132 { 551, "NG AIR55 HFA_17" },
133 { 552, "NG AIR55W" },
134 { 553, "NG AIR55 HFA_18" },
135 { 591, "NG AIR55 LSV" },
136 { 593, "NGXR60 EA" },
137 { 601, "NGXR60 GA / NGXR60 HFA_01" },
138 { 602, "NGXR60 HFA_02" },
139 { 646, "NGXR60 Multicast acceleration" },
140 { 650, "NGXR60 with Anti-Virus" },
141 { 665, "NGXR61 EA2" },
142 { 667, "NGXR61 GA" },
143 { 690, "NGXR62 EA" },
144 { 691, "NGXR62 GA" },
145 { 700, "Connectra NGXR61 EA" },
146 { 705, "Connectra NGXR61 GA" },
147 { 710, "Connectra NGXR66 GA" },
148 { 800, "NGXR65 EA" },
149 { 801, "NGXR65 GA" },
150 { 802, "NGXR65 HFA_01" },
151 { 803, "NGXR65 HFA_02" },
152 { 804, "NGXR65 HFA_02 / Connectra NGXR66.1" },
153 { 805, "NGXR65 HFA_03" },
154 { 810, "NGXR65 HFA_03 GA" },
155 { 811, "NGXR65 HFA_40" },
156 { 813, "NGXR65 HFA_50" },
157 { 814, "NGXR65 HFA_50" },
158 { 815, "NGXR65 HFA_60" },
159 { 816, "NGXR65 HFA_70" },
160 { 850, "VSX NGX Scalability Pack" },
161 { 900, "VSX NGXR65 GA" },
162 { 901, "VSX NGXR65 HFA_10" },
163 { 902, "VSX NGXR65 HFA_20" },
164 { 1000, "NGXR65 with CoreXL LE" },
165 { 1001, "VSX NGXR67 GA" },
166 { 1010, "VSX NGXR67 EA" },
167 { 1100, "VSX NGXR68 GA" },
170 { 1502, "R70.1 EA /R70.1 IPv6Pack HCC" },
171 { 1505, "R70.1 GA" },
172 { 1506, "2R70.1 IPv6Pack" },
176 { 1520, "R70.40 / GX 5.0 HCC" },
178 { 1555, "R71.10 /R71 VE" },
184 { 2000, "R75 GA / R75.050 for 61000 /R75.051 for 61000 /R75.052 for 61000" },
188 { 2210, "R75.40 32-bit" },
189 { 2211, "R75.40 64-bit" },
190 { 2220, "R75.45 32-bit" },
191 { 2221, "R75.45 64-bit" },
192 { 2225, "R75.46 32-bit" },
193 { 2226, "R75.46 64-bit" },
194 { 2230, "R75.47 32-bit" },
195 { 2231, "R75.47 64-bit" },
196 { 2500, "R75.40VS 32-bit" },
197 { 2501, "R75.40VS 64-bit" },
198 { 2502, "R75.40VS in VSX mode" },
199 { 2700, "R76 32-bit" },
200 { 2701, "DR76 64-bit" },
201 { 2702, "R76 in VSX mode" },
202 { 2720, "R76.10 32-bit" },
203 { 2721, "R76.10 64-bit" },
204 { 2722, "R76.10 in VSX mode" },
205 { 2900, "R77 32-bit" },
206 { 2901, "R77 64-bit" },
207 { 2902, "R77 in VSX mode" },
208 { 2905, "R77.10 32-bit" },
209 { 2906, "R77.10 64-bit" },
210 { 2907, "R77.10 in VSX mode" },
211 { 2910, "R77.20 32-bit" },
212 { 2911, "R77.20 64-bit" },
213 { 2912, "R77.20 in VSX mode" },
214 { 2920, "R77.30 32-bit" },
215 { 2921, "R77.30 64-bit" },
216 { 2922, "R77.30 in VSX mode" },
217 { 62700, "R76SP for 61000 32-bit" },
218 { 62701, "R76SP for 61000 64-bit" },
219 { 62702, "R76SP for 61000 in VSX mode" },
220 { 62710, "R76SP.10 for 61000 32-bit" },
221 { 62711, "R76SP.10 for 61000 64-bit" },
222 { 62712, "R76SP.10 for 61000 in VSX mode" },
226 static value_string_ext ha_version_vals_ext
= VALUE_STRING_EXT_INIT(ha_version_vals
);
229 static const value_string report_code_vals
[] = {
230 { 1, "Machine information included" },
231 { 2, "Interface information included" },
232 { 3, "Machine & Interface information included" },
235 static int dissect_my_state(tvbuff_t
*, int, proto_tree
*);
236 static int dissect_lb_conf(tvbuff_t
*, int, proto_tree
*);
237 static int dissect_policy_change(tvbuff_t
*, int, proto_tree
*);
238 static int dissect_probe(tvbuff_t
*, int, proto_tree
*);
239 static int dissect_conf_reply(tvbuff_t
*, int, proto_tree
*);
242 dissect_cpha(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
247 proto_tree
* cpha_tree
= NULL
;
248 proto_tree
* ntree
= NULL
;
250 uint16_t magic_number
;
253 * If the magic number or protocol version is unknown, don't treat this
254 * frame as a CPHA frame.
256 if (tvb_reported_length(tvb
) < 4) {
257 /* Not enough data for the magic number or protocol version */
260 magic_number
= tvb_get_ntohs(tvb
, 0);
261 ha_version
= tvb_get_ntohs(tvb
, 2);
262 if (magic_number
!= CPHA_MAGIC
) {
263 /* Bad magic number */
267 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "CPHA");
268 col_clear(pinfo
->cinfo
, COL_INFO
);
270 opcode
= tvb_get_ntohs(tvb
, 6);
272 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "CPHAv%d: %s",
273 ha_version
, val_to_str(opcode
, opcode_type_vals
, "Unknown %d"));
276 ti
= proto_tree_add_item(tree
, proto_cphap
, tvb
, offset
, -1, ENC_NA
);
277 cpha_tree
= proto_item_add_subtree(ti
, ett_cphap
);
279 proto_tree_add_item(cpha_tree
, hf_magic_number
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
282 proto_tree_add_item(cpha_tree
, hf_cpha_protocol_ver
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
285 proto_tree_add_item(cpha_tree
, hf_cluster_number
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
288 proto_tree_add_item(cpha_tree
, hf_opcode
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
291 proto_tree_add_item(cpha_tree
, hf_src_if_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
294 proto_tree_add_item(cpha_tree
, hf_random_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
297 proto_tree_add_item(cpha_tree
, hf_src_machine_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
300 proto_tree_add_item(cpha_tree
, hf_dst_machine_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
302 if(ha_version
!= 1) {/* 4.1 - no policy_id and filler*/
303 proto_tree_add_item(cpha_tree
, hf_policy_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
306 proto_tree_add_item(cpha_tree
, hf_filler
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
309 nti
= proto_tree_add_item(cpha_tree
, hf_payload
, tvb
, offset
, -1, ENC_NA
);
310 proto_item_append_text(nti
, " - %s", val_to_str(opcode
, opcode_type_vals
, "Unknown %d"));
311 ntree
= proto_item_add_subtree(nti
, ett_cphap
);
314 case 1: dissect_my_state(tvb
, offset
, ntree
); /* FWHAP_MY_STATE */
317 case 3: /* FWHAP_IF_PROBE_REQ */
318 case 4: dissect_probe(tvb
, offset
, ntree
); /* FWHAP_IF_PROBE_RPLY */
321 case 6: dissect_conf_reply(tvb
, offset
, ntree
); /* FWHAP_IFCONF_RPLY */
323 case 7: dissect_lb_conf(tvb
, offset
, ntree
); /* FWHAP_LB_CONF */
325 case 9: dissect_policy_change(tvb
, offset
, ntree
); /* FWHAP_POLICY_CHANGE */
327 default: proto_tree_add_item(ntree
, hf_unknown_data
, tvb
, offset
, -1, ENC_NA
);
332 return tvb_reported_length(tvb
);
335 static int dissect_my_state(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
337 proto_item
* nti
= NULL
;
338 proto_tree
* ntree
= NULL
;
339 uint16_t report_code
, id_num
;
341 proto_tree_add_item(tree
, hf_id_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
342 id_num
= tvb_get_ntohs(tvb
, offset
);
345 proto_tree_add_item(tree
, hf_report_code
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
346 report_code
= tvb_get_ntohs(tvb
, offset
);
349 proto_tree_add_item(tree
, hf_ha_mode
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
352 proto_tree_add_item(tree
, hf_ha_time_unit
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
355 if (report_code
& 1) {
357 nti
= proto_tree_add_item(tree
, hf_machine_states
, tvb
, offset
, id_num
, ENC_NA
);
358 ntree
= proto_item_add_subtree(nti
, ett_cphap
);
359 for(i
=0; i
< id_num
; i
++) {
360 nti
= proto_tree_add_item(ntree
, hf_state_node
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
361 proto_item_append_text(nti
, " (Nodes %d)", i
);
365 if (report_code
& 2) {
366 /* interface information */
367 nti
= proto_tree_add_item(tree
, hf_interface_states
, tvb
, offset
, 4, ENC_NA
);
368 ntree
= proto_item_add_subtree(nti
, ett_cphap
);
369 proto_tree_add_item(ntree
, hf_in_up_num
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
371 proto_tree_add_item(ntree
, hf_in_assumed_up_num
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
373 proto_tree_add_item(ntree
, hf_out_up_num
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
375 proto_tree_add_item(ntree
, hf_out_assumed_up_num
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
378 for(i
=0; i
< id_num
; i
++) {
379 proto_tree_add_item(tree
, hf_cluster_last_packet
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
380 proto_item_append_text(nti
, " (Cluster %d)", i
);
387 static int dissect_lb_conf(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
389 proto_tree_add_item(tree
, hf_slot_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
392 proto_tree_add_item(tree
, hf_machine_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
395 proto_tree_add_item(tree
, hf_seed
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
398 proto_tree_add_item(tree
, hf_hash_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
404 static int dissect_policy_change(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
406 proto_tree_add_item(tree
, hf_status
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
412 static int dissect_probe(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
414 proto_tree_add_item(tree
, hf_ifn
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
420 static int dissect_conf_reply(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
422 proto_tree_add_item(tree
, hf_num_reported_ifs
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
425 proto_tree_add_item(tree
, hf_ethernet_add
, tvb
, offset
, 6, ENC_NA
);
428 proto_tree_add_item(tree
, hf_is_if_trusted
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
431 proto_tree_add_item(tree
, hf_ip
, tvb
, offset
, 4, ENC_NA
);
438 proto_register_cpha(void)
440 static hf_register_info hf
[] = {
442 { "Magic Number", "cpha.magic_number", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
443 { &hf_cpha_protocol_ver
,
444 { "Protocol Version", "cpha.version", FT_UINT16
, BASE_DEC
|BASE_EXT_STRING
, &ha_version_vals_ext
, 0x0, "CPHAP Version", HFILL
}},
445 { &hf_cluster_number
,
446 { "Cluster Number", "cpha.cluster_number", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
448 { "HA OpCode", "cpha.opcode", FT_UINT16
, BASE_DEC
, VALS(opcode_type_vals
), 0x0, NULL
, HFILL
}},
450 { "Payload", "cpha.payload", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
452 { "Source Interface", "cpha.src_if", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
454 { "Random ID", "cpha.random_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
455 { &hf_src_machine_id
,
456 { "Source Machine ID", "cpha.src_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
457 { &hf_dst_machine_id
,
458 { "Destination Machine ID", "cpha.dst_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
460 { "Policy ID", "cpha.policy_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
462 { "Filler", "cpha.filler", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
464 { "Data", "cpha.unknown_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
466 { "Number of IDs reported", "cpha.id_num", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
468 { "Report code", "cpha.report_code", FT_UINT16
, BASE_DEC
, VALS(report_code_vals
), 0x0, NULL
, HFILL
}},
470 { "HA mode", "cpha.ha_mode", FT_UINT16
, BASE_DEC
, VALS(ha_mode_vals
), 0x0, NULL
, HFILL
}},
472 { "HA Time unit", "cpha.ha_time_unit", FT_UINT16
, BASE_DEC
, NULL
, 0x0, "HA Time unit (ms)", HFILL
}},
473 { &hf_machine_states
,
474 { "Machines States", "cpha.machine_states", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
476 { "State node", "cpha.state_node", FT_UINT8
, BASE_DEC
, VALS(state_vals
), 0x0, NULL
, HFILL
}},
477 { &hf_interface_states
,
478 { "Interface States", "cpha.interface_states", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
479 { &hf_num_reported_ifs
,
480 { "Reported Interfaces", "cpha.reported_ifs", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
482 { "Ethernet Address", "cpha.ethernet_addr", FT_ETHER
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
484 { "Interface Trusted", "cpha.if_trusted", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
486 { "IP Address", "cpha.ip", FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
488 { "Slot Number", "cpha.slot_num", FT_INT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
490 { "Machine Number", "cpha.machine_num", FT_INT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
492 { "Seed", "cpha.seed", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
494 { "Hash list length", "cpha.hash_len", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
496 { "Interfaces up in the Inbound", "cpha.in_up", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
497 { &hf_in_assumed_up_num
,
498 { "Interfaces assumed up in the Inbound", "cpha.in_assume_up", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
500 { "Interfaces up in the Outbound", "cpha.out_up", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
501 { &hf_out_assumed_up_num
,
502 { "Interfaces assumed up in the Outbound", "cpha.out_assume_up", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
503 { &hf_cluster_last_packet
,
504 { "Last packet seen", "cpha.cluster_last_packet", FT_INT8
, BASE_DEC
, NULL
, 0x0, "Time units ago", HFILL
}},
506 { "Status", "cpha.status", FT_UINT32
, BASE_DEC
, VALS(status_vals
), 0x0, NULL
, HFILL
}},
508 { "Interface Number", "cpha.ifn", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
510 static int *ett
[] = {
514 proto_cphap
= proto_register_protocol("Check Point High Availability Protocol", "CPHA", "cpha");
515 proto_register_field_array(proto_cphap
, hf
, array_length(hf
));
516 proto_register_subtree_array(ett
, array_length(ett
));
518 cpha_handle
= register_dissector("cpha", dissect_cpha
, proto_cphap
);
522 proto_reg_handoff_cpha(void)
524 dissector_add_uint_with_preference("udp.port", UDP_PORT_CPHA
, cpha_handle
);
532 * indent-tabs-mode: nil
535 * ex: set shiftwidth=2 tabstop=8 expandtab:
536 * :indentSize=2:tabSize=8:noTabs=true: