2 * Routines for the Check Point High-Availability Protocol (CPHAP)
3 * Copyright 2002, Yaniv Kaul <mykaul -at- gmail.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/ipproto.h>
33 void proto_register_cpha(void);
34 void proto_reg_handoff_cpha(void);
36 static int proto_cphap
= -1;
38 static int hf_magic_number
= -1;
39 static int hf_cpha_protocol_ver
= -1;
40 static int hf_cluster_number
= -1;
41 static int hf_opcode
= -1;
42 static int hf_payload
= -1;
43 static int hf_src_if_num
= -1;
44 static int hf_random_id
= -1;
45 static int hf_src_machine_id
= -1;
46 static int hf_dst_machine_id
= -1;
47 static int hf_policy_id
= -1;
48 static int hf_filler
= -1;
49 static int hf_id_num
= -1;
50 static int hf_report_code
= -1;
51 static int hf_ha_mode
= -1;
52 static int hf_ha_time_unit
= -1;
53 static int hf_machine_states
= -1;
54 static int hf_state_node
= -1;
55 static int hf_interface_states
= -1;
56 static int hf_num_reported_ifs
= -1;
57 static int hf_ethernet_add
= -1;
58 static int hf_is_if_trusted
= -1;
59 static int hf_ip
= -1;
60 static int hf_slot_num
= -1;
61 static int hf_machine_num
= -1;
62 static int hf_seed
= -1;
63 static int hf_hash_len
= -1;
64 static int hf_status
= -1;
65 static int hf_in_up_num
= -1;
66 static int hf_in_assumed_up_num
= -1;
67 static int hf_out_up_num
= -1;
68 static int hf_out_assumed_up_num
= -1;
69 static int hf_cluster_last_packet
= -1;
70 static int hf_ifn
= -1;
72 static gint ett_cphap
= -1;
74 #define UDP_PORT_CPHA 8116
75 #define CPHA_MAGIC 0x1A90
78 static const value_string opcode_type_short_vals
[] = {
80 { 1, "FWHA_MY_STATE" },
81 { 2, "FWHA_QUERY_STATE" },
82 { 3, "FWHA_IF_PROBE_REQ" },
83 { 4, "FWHA_IF_PROBE_REPLY" },
84 { 5, "FWHA_IFCONF_REQ" },
85 { 6, "FWHA_IFCONF_REPLY" },
86 { 7, "FWHA_LB_CONF" },
87 { 8, "FWHA_LB_CONFIRM" },
88 { 9, "FWHA_POLICY_CHANGE" },
94 static const value_string opcode_type_vals
[] = {
95 { 0, "Unknown OpCode" },
96 { 1, "FWHA_MY_STATE - Report source machine's state" },
97 { 2, "FWHA_QUERY_STATE - Query other machine's state" },
98 { 3, "FWHA_IF_PROBE_REQ - Interface active check request" },
99 { 4, "FWHA_IF_PROBE_REPLY - Interface active check reply" },
100 { 5, "FWHA_IFCONF_REQ - Interface configuration request" },
101 { 6, "FWHA_IFCONF_REPLY - Interface configuration reply" },
102 { 7, "FWHA_LB_CONF - LB configuration report request" },
103 { 8, "FWHA_LB_CONFIRM - LB configuration report reply" },
104 { 9, "FWHA_POLICY_CHANGE - Policy ID change request/notification" },
105 { 10, "FWHAP_SYNC - New Sync packet" },
109 static const value_string state_vals
[] = {
111 { 1, "Initializing" },
114 { 4, "Active/Active-Attention" },
118 static const value_string status_vals
[] = {
119 { 1, "New policy arrived - no need to modify HA configuration" },
120 { 2, "New policy arrived - need to modify HA configuration" },
121 { 3, "Ready to change configuration" },
125 static const value_string ha_mode_vals
[] = {
126 { 0, "FWHA_UNDEF_MODE" },
127 { 1, "FWHA_NOT_ACTIVE_MODE - CPHA is not active" },
128 { 2, "FWHA_BALANCE_MODE - More than one machine active" },
129 { 3, "FWHA_PRIMARY_UP_MODE" },
130 { 4, "FWHA_ONE_UP_MODE" },
134 static const value_string ha_version_vals
[] = {
136 { 6, "NG Feature Pack 2" },
137 { 530, "NG Feature Pack 3" },
138 { 540, "NG with Application Intelligence (Early Availability)" },
139 { 514, "NG with Application Intelligence" },
142 static const value_string report_code_vals
[] = {
143 { 1, "Machine information included" },
144 { 2, "Interface information included" },
145 { 3, "Machine & Interface information included" },
148 static int dissect_my_state(tvbuff_t
*, int, proto_tree
*);
149 static int dissect_lb_conf(tvbuff_t
*, int, proto_tree
*);
150 static int dissect_policy_change(tvbuff_t
*, int, proto_tree
*);
151 static int dissect_probe(tvbuff_t
*, int, proto_tree
*);
152 static int dissect_conf_reply(tvbuff_t
*, int, proto_tree
*);
155 dissect_cpha(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
160 proto_tree
* cpha_tree
= NULL
;
161 proto_tree
* ntree
= NULL
;
163 guint16 magic_number
;
166 * If the magic number or protocol version is unknown, don't treat this
167 * frame as a CPHA frame.
169 if (tvb_length(tvb
) < 4) {
170 /* Not enough data for the magic number or protocol version */
173 magic_number
= tvb_get_ntohs(tvb
, 0);
174 ha_version
= tvb_get_ntohs(tvb
, 2);
175 if (magic_number
!= CPHA_MAGIC
) {
176 /* Bad magic number */
180 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "CPHA");
181 col_clear(pinfo
->cinfo
, COL_INFO
);
183 opcode
= tvb_get_ntohs(tvb
, 6);
185 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "CPHAv%d: %s",
186 ha_version
, val_to_str(opcode
, opcode_type_vals
, "Unknown %d"));
189 ti
= proto_tree_add_item(tree
, proto_cphap
, tvb
, offset
, -1, ENC_NA
);
190 cpha_tree
= proto_item_add_subtree(ti
, ett_cphap
);
193 proto_tree_add_item(cpha_tree
, hf_magic_number
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
196 proto_tree_add_item(cpha_tree
, hf_cpha_protocol_ver
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
199 proto_tree_add_item(cpha_tree
, hf_cluster_number
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
202 proto_tree_add_item(cpha_tree
, hf_opcode
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
205 proto_tree_add_item(cpha_tree
, hf_src_if_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
208 proto_tree_add_item(cpha_tree
, hf_random_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
211 proto_tree_add_item(cpha_tree
, hf_src_machine_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
214 proto_tree_add_item(cpha_tree
, hf_dst_machine_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
216 if(ha_version
!= 1) {/* 4.1 - no policy_id and filler*/
217 proto_tree_add_item(cpha_tree
, hf_policy_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
220 proto_tree_add_item(cpha_tree
, hf_filler
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
223 nti
= proto_tree_add_item(cpha_tree
, hf_payload
, tvb
, offset
, -1, ENC_NA
);
224 proto_item_append_text(nti
, " - %s", val_to_str(opcode
, opcode_type_vals
, "Unknown %d"));
225 ntree
= proto_item_add_subtree(nti
, ett_cphap
);
228 case 1: dissect_my_state(tvb
, offset
, ntree
); /* FWHAP_MY_STATE */
231 case 3: /* FWHAP_IF_PROBE_REQ */
232 case 4: dissect_probe(tvb
, offset
, ntree
); /* FWHAP_IF_PROBE_RPLY */
235 case 6: dissect_conf_reply(tvb
, offset
, ntree
); /* FWHAP_IFCONF_RPLY */
237 case 7: dissect_lb_conf(tvb
, offset
, ntree
); /* FWHAP_LB_CONF */
239 case 9: dissect_policy_change(tvb
, offset
, ntree
); /* FWHAP_POLICY_CHANGE */
245 return tvb_length(tvb
);
248 static int dissect_my_state(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
250 proto_item
* nti
= NULL
;
251 proto_tree
* ntree
= NULL
;
252 guint16 report_code
, id_num
;
254 proto_tree_add_item(tree
, hf_id_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
255 id_num
= tvb_get_ntohs(tvb
, offset
);
258 proto_tree_add_item(tree
, hf_report_code
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
259 report_code
= tvb_get_ntohs(tvb
, offset
);
262 proto_tree_add_item(tree
, hf_ha_mode
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
265 proto_tree_add_item(tree
, hf_ha_time_unit
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
268 if (report_code
& 1) {
270 nti
= proto_tree_add_item(tree
, hf_machine_states
, tvb
, offset
, id_num
, ENC_NA
);
271 ntree
= proto_item_add_subtree(nti
, ett_cphap
);
272 for(i
=0; i
< id_num
; i
++) {
273 nti
= proto_tree_add_item(ntree
, hf_state_node
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
274 proto_item_append_text(nti
, " (Nodes %d)", i
);
278 if (report_code
& 2) {
279 /* interface information */
280 nti
= proto_tree_add_item(tree
, hf_interface_states
, tvb
, offset
, 4, ENC_NA
);
281 ntree
= proto_item_add_subtree(nti
, ett_cphap
);
282 proto_tree_add_item(ntree
, hf_in_up_num
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
284 proto_tree_add_item(ntree
, hf_in_assumed_up_num
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
286 proto_tree_add_item(ntree
, hf_out_up_num
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
288 proto_tree_add_item(ntree
, hf_out_assumed_up_num
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
291 for(i
=0; i
< id_num
; i
++) {
292 proto_tree_add_item(tree
, hf_cluster_last_packet
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
293 proto_item_append_text(nti
, " (Cluster %d)", i
);
300 static int dissect_lb_conf(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
302 proto_tree_add_item(tree
, hf_slot_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
305 proto_tree_add_item(tree
, hf_machine_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
308 proto_tree_add_item(tree
, hf_seed
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
311 proto_tree_add_item(tree
, hf_hash_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
317 static int dissect_policy_change(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
319 proto_tree_add_item(tree
, hf_status
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
325 static int dissect_probe(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
327 proto_tree_add_item(tree
, hf_ifn
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
333 static int dissect_conf_reply(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
) {
335 proto_tree_add_item(tree
, hf_num_reported_ifs
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
338 proto_tree_add_item(tree
, hf_ethernet_add
, tvb
, offset
, 6, ENC_NA
);
341 proto_tree_add_item(tree
, hf_is_if_trusted
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
344 proto_tree_add_item(tree
, hf_ip
, tvb
, offset
, 4, ENC_NA
);
351 proto_register_cpha(void)
353 static hf_register_info hf
[] = {
355 { "Magic Number", "cpha.magic_number", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
356 { &hf_cpha_protocol_ver
,
357 { "Protocol Version", "cpha.version", FT_UINT16
, BASE_DEC
, VALS(ha_version_vals
), 0x0, "CPHAP Version", HFILL
}},
358 { &hf_cluster_number
,
359 { "Cluster Number", "cpha.cluster_number", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
361 { "HA OpCode", "cpha.opcode", FT_UINT16
, BASE_DEC
, VALS(opcode_type_vals
), 0x0, NULL
, HFILL
}},
363 { "Payload", "cpha.payload", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
365 { "Source Interface", "cpha.src_if", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
367 { "Random ID", "cpha.random_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
368 { &hf_src_machine_id
,
369 { "Source Machine ID", "cpha.src_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
370 { &hf_dst_machine_id
,
371 { "Destination Machine ID", "cpha.dst_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
373 { "Policy ID", "cpha.policy_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
375 { "Filler", "cpha.filler", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
377 { "Number of IDs reported", "cpha.id_num", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
379 { "Report code", "cpha.report_code", FT_UINT16
, BASE_DEC
, VALS(report_code_vals
), 0x0, NULL
, HFILL
}},
381 { "HA mode", "cpha.ha_mode", FT_UINT16
, BASE_DEC
, VALS(ha_mode_vals
), 0x0, NULL
, HFILL
}},
383 { "HA Time unit", "cpha.ha_time_unit", FT_UINT16
, BASE_DEC
, NULL
, 0x0, "HA Time unit (ms)", HFILL
}},
384 { &hf_machine_states
,
385 { "Machines States", "cpha.machine_states", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
387 { "State node", "cpha.state_node", FT_UINT8
, BASE_DEC
, VALS(state_vals
), 0x0, NULL
, HFILL
}},
388 { &hf_interface_states
,
389 { "Interface States", "cpha.interface_states", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
390 { &hf_num_reported_ifs
,
391 { "Reported Interfaces", "cpha.reported_ifs", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
393 { "Ethernet Address", "cpha.ethernet_addr", FT_ETHER
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
395 { "Interface Trusted", "cpha.if_trusted", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
397 { "IP Address", "cpha.ip", FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
399 { "Slot Number", "cpha.slot_num", FT_INT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
401 { "Machine Number", "cpha.machine_num", FT_INT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
403 { "Seed", "cpha.seed", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
405 { "Hash list length", "cpha.hash_len", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
407 { "Interfaces up in the Inbound", "cpha.in_up", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
408 { &hf_in_assumed_up_num
,
409 { "Interfaces assumed up in the Inbound", "cpha.in_assume_up", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
411 { "Interfaces up in the Outbound", "cpha.out_up", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
412 { &hf_out_assumed_up_num
,
413 { "Interfaces assumed up in the Outbound", "cpha.out_assume_up", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
414 { &hf_cluster_last_packet
,
415 { "Last packet seen", "cpha.cluster_last_packet", FT_INT8
, BASE_DEC
, NULL
, 0x0, "Time units ago", HFILL
}},
417 { "Status", "cpha.status", FT_UINT32
, BASE_DEC
, VALS(status_vals
), 0x0, NULL
, HFILL
}},
419 { "Interface Number", "cpha.ifn", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
421 static gint
*ett
[] = {
425 proto_cphap
= proto_register_protocol("Check Point High Availability Protocol",
427 proto_register_field_array(proto_cphap
, hf
, array_length(hf
));
428 proto_register_subtree_array(ett
, array_length(ett
));
432 proto_reg_handoff_cpha(void)
434 dissector_handle_t cpha_handle
;
436 cpha_handle
= new_create_dissector_handle(dissect_cpha
, proto_cphap
);
437 dissector_add_uint("udp.port", UDP_PORT_CPHA
, cpha_handle
);
445 * indent-tabs-mode: nil
448 * ex: set shiftwidth=2 tabstop=8 expandtab:
449 * :indentSize=2:tabSize=8:noTabs=true: