Rename the routines that handle dissector tables with unsigned integer
[obnox/wireshark/wip.git] / epan / dissectors / packet-cpha.c
1 /* packet-cpha.c
2  * Routines for the Check Point High-Availability Protocol (CPHAP)
3  * Copyright 2002, Yaniv Kaul <ykaul-at-netvision.net.il>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  *
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.
20  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <glib.h>
31
32 #include <epan/packet.h>
33 #include <epan/ipproto.h>
34
35 static int proto_cphap = -1;
36
37 static int hf_magic_number = -1;
38 static int hf_cpha_protocol_ver = -1;
39 static int hf_cluster_number = -1;
40 static int hf_opcode = -1;
41 static int hf_src_if_num = -1;
42 static int hf_random_id = -1;
43 static int hf_src_machine_id = -1;
44 static int hf_dst_machine_id = -1;
45 static int hf_policy_id = -1;
46 static int hf_filler = -1;
47 static int hf_id_num = -1;
48 static int hf_report_code = -1;
49 static int hf_ha_mode = -1;
50 static int hf_ha_time_unit = -1;
51 /*static int hf_problem = -1;*/
52 static int hf_num_reported_ifs = -1;
53 static int hf_ethernet_add = -1;
54 static int hf_is_if_trusted = -1;
55 static int hf_ip = -1;
56 static int hf_slot_num = -1;
57 static int hf_machine_num = -1;
58 static int hf_seed = -1;
59 static int hf_hash_len = -1;
60 static int hf_status = -1;
61 static int hf_in_up_num = -1;
62 static int hf_in_assumed_up_num = -1;
63 static int hf_out_up_num = -1;
64 static int hf_out_assumed_up_num = -1;
65 static int hf_ifn = -1;
66
67 static gint ett_cphap = -1;
68
69 #define UDP_PORT_CPHA   8116
70 #define CPHA_MAGIC 0x1A90
71
72 struct cpha_hdr {
73   guint16       magic_number;
74   guint16       ha_protocol_ver;
75   guint16       cluster_number;
76   guint16       opcode;
77   guint16       src_if_num;
78   guint16       random_id;
79   guint16       src_machine_id;
80   guint16       dst_machine_id;
81   guint16       policy_id;
82   guint16       filler;
83   guint32       data;
84 };
85
86 struct fwha_my_state_hdr {
87   guint16       id_num;
88   guint16       report_code;
89   guint16       ha_mode;
90   guint16       ha_time_unit;
91   /*guint16     problem;*/
92 };
93
94 struct conf_reply_hdr {
95   guint32       num_reported_ifs;
96   guint8        ethernet_add[6];
97   guint16       is_if_trusted;
98   guint32       ip;
99 };
100
101 struct lb_conf_hdr {
102   guint16       slot_num;
103   guint16       machine_num;
104   guint32       seed;
105   guint32       hash_list_len;
106 };
107
108 struct fwhap_if_state_s {
109   guint8        in_up_num;
110   guint8        in_assumed_up_num;
111   guint8        out_up_num;
112   guint8        out_assumed_up_num;
113 };
114
115 #define NUM_OPCODE_TYPES 10
116
117 static const char *opcode_type_str_short[NUM_OPCODE_TYPES+1] = {
118   "Unknown",
119   "FWHA_MY_STATE",
120   "FWHA_QUERY_STATE",
121   "FWHA_IF_PROBE_REQ",
122   "FWHA_IF_PROBE_REPLY",
123   "FWHA_IFCONF_REQ",
124   "FWHA_IFCONF_REPLY",
125   "FWHA_LB_CONF",
126   "FWHA_LB_CONFIRM",
127   "FWHA_POLICY_CHANGE",
128   "FWHAP_SYNC"
129 };
130
131 static const char *opcode_type_str_long[NUM_OPCODE_TYPES+1] = {
132   "Unknown OpCode",
133   "Report source machine's state",
134   "Query other machine's state",
135   "Interface active check request",
136   "Interface active check reply",
137   "Interface configuration request",
138   "Interface configuration reply",
139   "LB configuration report request",
140   "LB configuration report reply",
141   "Policy ID change request/notification",
142   "New Sync packet"
143 };
144
145 #define NUM_STATES 5
146 static const char *state_str[NUM_STATES] = {
147   "Down/Dead",
148   "Initializing",
149   "Standby",
150   "Ready",
151   "Active/Active-Attention"
152 };
153
154 static const value_string status_vals[] = {
155   { 1, "New policy arrived - no need to modify HA configuration" },
156   { 2, "New policy arrived - need to modify HA configuration" },
157   { 3, "Ready to change configuration" },
158   { 0, NULL }
159 };
160
161 #define NUM_HA_MODES 4
162 static const char *ha_mode_str[NUM_HA_MODES+1] = {
163   "FWHA_UNDEF_MODE",
164   "FWHA_NOT_ACTIVE_MODE - CPHA is not active",
165   "FWHA_BALANCE_MODE - More than one machine active",
166   "FWHA_PRIMARY_UP_MODE",
167   "FWHA_ONE_UP_MODE"
168 };
169
170 static const char *ha_magic_num2str(guint16 magic);
171 static const char *version2str(guint16 version);
172 static const char *opcode2str_short(guint16 opcode);
173 static const char *opcode2str_long(guint16 opcode);
174 static void dissect_my_state(tvbuff_t *, int, proto_tree *);
175 static void dissect_lb_conf(tvbuff_t *, int, proto_tree *);
176 static void dissect_policy_change(tvbuff_t *, int, proto_tree *);
177 static void dissect_probe(tvbuff_t *, int, proto_tree *);
178 static void dissect_conf_reply(tvbuff_t *, int, proto_tree *);
179 static int is_report_ifs(guint16);
180 static const char *report_code2str(guint16);
181 static const char *ha_mode2str(guint16);
182 static const char *state2str(guint8);
183
184 static int
185 dissect_cpha(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
186 {
187   int                   offset = 0;
188   struct cpha_hdr       hdr;
189   proto_item *          ti;
190   proto_item *          nti;
191   proto_tree *          cpha_tree = NULL;
192   proto_tree *          ntree = NULL;
193   guint16               opcode;
194
195   /*
196    * If the magic number or protocol version is unknown, don't treat this
197    * frame as a CPHA frame.
198    */
199   if (tvb_length(tvb) < 4) {
200     /* Not enough data for the magic number or protocol version */
201     return 0;
202   }
203   hdr.magic_number = tvb_get_ntohs(tvb, 0);
204   hdr.ha_protocol_ver = tvb_get_ntohs(tvb, 2);
205   if (ha_magic_num2str(hdr.magic_number) == NULL) {
206     /* Bad magic number */
207     return 0;
208   }
209   if (version2str(hdr.ha_protocol_ver) == NULL) {
210     /* Bad version number */
211     return 0;
212   }
213
214   col_set_str(pinfo->cinfo, COL_PROTOCOL, "CPHA");
215   col_clear(pinfo->cinfo, COL_INFO);
216
217   tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
218   hdr.magic_number = g_ntohs(hdr.magic_number);
219   hdr.ha_protocol_ver = g_ntohs(hdr.ha_protocol_ver);
220   hdr.random_id = g_ntohs(hdr.random_id);
221   hdr.src_if_num = g_ntohs(hdr.src_if_num);
222   hdr.src_machine_id = g_ntohs(hdr.src_machine_id);
223   hdr.dst_machine_id = g_ntohs(hdr.dst_machine_id);
224   hdr.policy_id = g_ntohs(hdr.policy_id);
225   hdr.filler = g_ntohs(hdr.filler);
226   opcode  = g_ntohs(hdr.opcode);
227
228   if (check_col(pinfo->cinfo, COL_INFO))
229     col_add_fstr(pinfo->cinfo, COL_INFO, "CPHAv%d: %s",
230         hdr.ha_protocol_ver, opcode2str_short(opcode));
231
232   if (tree) {
233     ti = proto_tree_add_item(tree, proto_cphap, tvb, offset, -1, FALSE);
234     cpha_tree = proto_item_add_subtree(ti, ett_cphap);
235   }
236   if (tree) {
237     proto_tree_add_uint_format(cpha_tree, hf_magic_number, tvb, offset, sizeof(hdr.magic_number), hdr.magic_number, "Magic Number: 0x%x (%s)", hdr.magic_number, ha_magic_num2str(hdr.magic_number));
238     offset += sizeof(hdr.magic_number);
239
240     proto_tree_add_uint_format_value(cpha_tree, hf_cpha_protocol_ver, tvb, offset, sizeof(hdr.ha_protocol_ver), hdr.ha_protocol_ver, "%d (%s)", hdr.ha_protocol_ver,version2str(hdr.ha_protocol_ver));
241     offset += sizeof(hdr.ha_protocol_ver);
242
243     proto_tree_add_uint(cpha_tree, hf_cluster_number, tvb, offset, sizeof(hdr.cluster_number), g_ntohs(hdr.cluster_number));
244     offset += sizeof(hdr.cluster_number);
245
246     proto_tree_add_uint_format(cpha_tree, hf_opcode, tvb, offset, sizeof(hdr.opcode), opcode,
247                         "HA OpCode: %d (%s - %s)", opcode, opcode2str_short(opcode), opcode2str_long(opcode));
248     offset += sizeof(hdr.opcode);
249
250     proto_tree_add_uint(cpha_tree, hf_src_if_num, tvb, offset, sizeof(hdr.src_if_num),
251                         hdr.src_if_num);
252     offset += sizeof(hdr.src_if_num);
253
254     proto_tree_add_uint(cpha_tree, hf_random_id, tvb, offset, sizeof(hdr.random_id), hdr.random_id);
255     offset += sizeof(hdr.random_id);
256
257     proto_tree_add_uint(cpha_tree, hf_src_machine_id, tvb, offset, sizeof(hdr.src_machine_id), hdr.src_machine_id);
258     offset += sizeof(hdr.src_machine_id);
259
260     proto_tree_add_uint(cpha_tree, hf_dst_machine_id, tvb, offset, sizeof(hdr.dst_machine_id), hdr.dst_machine_id);
261     offset += sizeof(hdr.dst_machine_id);
262     if(hdr.ha_protocol_ver != 1) {/* 4.1 - no policy_id and filler*/
263         proto_tree_add_uint(cpha_tree, hf_policy_id, tvb, offset, sizeof(hdr.policy_id), hdr.policy_id);
264         offset += sizeof(hdr.policy_id);
265
266         proto_tree_add_uint(cpha_tree, hf_filler, tvb, offset, sizeof(hdr.filler), g_ntohs(hdr.filler));
267         offset += sizeof(hdr.filler);
268     }
269     nti = proto_tree_add_text(cpha_tree, tvb, offset, -1, "%s", opcode2str_short(opcode));
270     ntree = proto_item_add_subtree(nti, ett_cphap);
271
272     switch(opcode) {
273         case 1: dissect_my_state(tvb, offset, ntree); /* FWHAP_MY_STATE */
274                 break;
275         case 2: break;
276         case 3:                                      /* FWHAP_IF_PROBE_REQ */
277         case 4: dissect_probe(tvb, offset, ntree);   /* FWHAP_IF_PROBE_RPLY */
278                 break;
279         case 5: break;
280         case 6: dissect_conf_reply(tvb, offset, ntree); /* FWHAP_IFCONF_RPLY */
281                 break;
282         case 7: dissect_lb_conf(tvb, offset, ntree); /* FWHAP_LB_CONF */
283                 break;
284         case 9: dissect_policy_change(tvb, offset, ntree); /* FWHAP_POLICY_CHANGE */
285                 break;
286         default: break;
287     }
288   }
289
290   return tvb_length(tvb);
291 }
292
293 static void dissect_my_state(tvbuff_t * tvb, int offset, proto_tree * tree) {
294   struct fwha_my_state_hdr hdr;
295   struct fwhap_if_state_s  if_hdr;
296   int rep_mode, i;
297   proto_item *  nti = NULL;
298   proto_tree *  ntree = NULL;
299
300   tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
301   hdr.id_num = g_ntohs(hdr.id_num);
302   hdr.report_code = g_ntohs(hdr.report_code);
303   hdr.ha_mode = g_ntohs(hdr.ha_mode);
304   hdr.ha_time_unit = g_ntohs(hdr.ha_time_unit);
305
306   proto_tree_add_uint(tree, hf_id_num, tvb, offset, sizeof(hdr.id_num), hdr.id_num);
307   offset += sizeof(hdr.id_num);
308
309   proto_tree_add_text(tree, tvb, offset, sizeof(hdr.report_code), "Report Code: %s",report_code2str(hdr.report_code));
310   offset += sizeof(hdr.report_code);
311
312   proto_tree_add_uint_format_value(tree, hf_ha_mode, tvb, offset, sizeof(hdr.ha_mode), hdr.ha_mode, "%d (%s)", hdr.ha_mode, ha_mode2str(hdr.ha_mode));
313   offset += sizeof(hdr.ha_mode);
314
315   proto_tree_add_uint_format_value(tree, hf_ha_time_unit, tvb, offset, sizeof(hdr.ha_time_unit), hdr.ha_time_unit, "%d milliseconds", hdr.ha_time_unit);
316   offset += sizeof(hdr.ha_time_unit);
317
318   rep_mode = is_report_ifs(hdr.report_code);
319   if (hdr.report_code & 1) {
320         /* states */
321         nti = proto_tree_add_text(tree, tvb, offset, hdr.id_num * sizeof(guint8), "Machine states");
322         ntree = proto_item_add_subtree(nti, ett_cphap);
323         for(i=0; i < hdr.id_num; i++) {
324                 proto_tree_add_text(ntree, tvb, offset, sizeof(guint8), "State of node %d: %d (%s)", i, tvb_get_guint8(tvb, offset), state2str(tvb_get_guint8(tvb, offset)));
325                 offset += sizeof(guint8);
326         }
327   }
328   if (hdr.report_code & 2) {
329         /* interface information */
330         nti = proto_tree_add_text(tree, tvb, offset, sizeof(struct fwhap_if_state_s), "Interface states");
331         ntree = proto_item_add_subtree(nti, ett_cphap);
332         tvb_memcpy(tvb, (guint8 *)&if_hdr, offset, sizeof(if_hdr));
333         proto_tree_add_int(ntree, hf_in_up_num, tvb, offset, sizeof(if_hdr.in_up_num), if_hdr.in_up_num);
334         offset += sizeof(if_hdr.in_up_num);
335         proto_tree_add_int(ntree, hf_in_assumed_up_num, tvb, offset, sizeof(if_hdr.in_assumed_up_num), if_hdr.in_assumed_up_num);
336         offset += sizeof(if_hdr.in_assumed_up_num);
337         proto_tree_add_int(ntree, hf_out_up_num, tvb, offset, sizeof(if_hdr.out_up_num), if_hdr.out_up_num);
338         offset += sizeof(if_hdr.out_up_num);
339         proto_tree_add_int(ntree, hf_out_assumed_up_num, tvb, offset, sizeof(if_hdr.out_assumed_up_num), if_hdr.out_assumed_up_num);
340         offset += sizeof(if_hdr.out_assumed_up_num);
341
342         for(i=0; i < hdr.id_num; i++) {
343                 proto_tree_add_text(tree, tvb, offset, sizeof(guint8), "Cluster %d: last packet seen %d time units ago", i, tvb_get_guint8(tvb, offset));
344                 offset += sizeof(guint8);
345         }
346   }
347
348 }
349
350 static void dissect_lb_conf(tvbuff_t * tvb, int offset, proto_tree * tree) {
351   struct lb_conf_hdr hdr;
352
353   tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
354   hdr.slot_num = g_ntohs(hdr.slot_num);
355   hdr.machine_num = g_ntohs(hdr.machine_num);
356   hdr.seed = g_ntohs(hdr.seed);
357   hdr.hash_list_len = g_ntohs(hdr.hash_list_len);
358
359   proto_tree_add_uint(tree, hf_slot_num, tvb, offset, sizeof(hdr.slot_num), hdr.slot_num);
360   offset += sizeof(hdr.slot_num);
361
362   proto_tree_add_int(tree, hf_machine_num, tvb, offset, sizeof(hdr.machine_num), hdr.machine_num);
363   offset += sizeof(hdr.machine_num);
364
365   proto_tree_add_uint(tree, hf_seed, tvb, offset, sizeof(hdr.seed), hdr.seed);
366   offset += sizeof(hdr.seed);
367
368   proto_tree_add_uint(tree, hf_hash_len, tvb, offset, sizeof(hdr.hash_list_len), hdr.hash_list_len);
369   offset += sizeof(hdr.hash_list_len);
370
371 }
372
373 static void dissect_policy_change(tvbuff_t * tvb, int offset, proto_tree * tree) {
374   guint32 status;
375
376   status = tvb_get_ntohl(tvb, offset);
377
378   proto_tree_add_uint(tree, hf_status, tvb, offset, sizeof(status), status);
379   offset += sizeof(guint32);
380 }
381
382 static void dissect_probe(tvbuff_t * tvb, int offset, proto_tree * tree) {
383   guint32 ifn;
384
385   ifn = tvb_get_ntohl(tvb, offset);
386
387   proto_tree_add_uint(tree, hf_ifn, tvb, offset, sizeof(ifn), ifn);
388   offset += sizeof(guint32);
389 }
390
391 static void dissect_conf_reply(tvbuff_t * tvb, int offset, proto_tree * tree) {
392   struct conf_reply_hdr hdr;
393
394   tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
395   hdr.num_reported_ifs = g_ntohl(hdr.num_reported_ifs);
396   hdr.is_if_trusted = g_ntohs(hdr.is_if_trusted);
397
398   proto_tree_add_uint(tree, hf_num_reported_ifs, tvb, offset, sizeof(hdr.num_reported_ifs), hdr.num_reported_ifs);
399   offset += sizeof(hdr.num_reported_ifs);
400   proto_tree_add_ether(tree, hf_ethernet_add, tvb, offset, 6, hdr.ethernet_add);
401   offset += 6;
402
403   proto_tree_add_boolean(tree, hf_is_if_trusted, tvb, offset, sizeof(hdr.is_if_trusted), hdr.is_if_trusted);
404   offset += sizeof(hdr.is_if_trusted);
405
406   proto_tree_add_ipv4(tree, hf_ip, tvb, offset, sizeof(hdr.ip), hdr.ip);
407   offset += 4;
408 }
409
410 static int
411 is_report_ifs(guint16 report_code) {
412   if(report_code & 2)
413         return 1;
414   return 0;
415 }
416
417 static const char *
418 report_code2str(guint16 report_code) {
419   int ret;
420   ret = is_report_ifs(report_code);
421   if(!(report_code & 1))
422         return "Machine information NOT present";
423   if(ret == 1)
424         return "Interface information included";
425   return "Unknown report code!";
426 }
427 static const char *
428 ha_magic_num2str(guint16 magic) {
429   if(magic == CPHA_MAGIC)
430         return "correct";
431   return NULL;
432 }
433
434 static const char *
435 version2str(guint16 version) {
436   switch(version) {
437         case 1: return "4.1";
438         case 6: return "NG Feature Pack 2";
439         case 530: return "NG Feature Pack 3";
440         case 540: return "NG with Application Intelligence (Early Availability)";
441         case 541: return "NG with Application Intelligence";
442         default: break;
443   }
444   return "Unknown Version";
445 }
446 static const char *
447 opcode2str_short(guint16 opcode) {
448   if(opcode <= NUM_OPCODE_TYPES)
449         return opcode_type_str_short[opcode];
450   return opcode_type_str_short[0];
451 }
452
453 static const char *
454 ha_mode2str(guint16 hamode) {
455   if(hamode <= NUM_HA_MODES)
456         return ha_mode_str[hamode];
457   return "Unknown HA mode";
458 }
459
460 static const char *
461 state2str(guint8 state) {
462   if(state < NUM_STATES)
463         return state_str[state];
464   return "Unknown";
465 }
466
467
468 static const char *
469 opcode2str_long(guint16 opcode) {
470   if(opcode <= NUM_OPCODE_TYPES)
471         return opcode_type_str_long[opcode];
472   return opcode_type_str_long[0];
473 }
474
475 void
476 proto_register_cpha(void)
477 {
478   static hf_register_info hf[] = {
479     { &hf_magic_number,
480     { "CPHAP Magic Number", "cpha.magic_number", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
481     { &hf_cpha_protocol_ver,
482     { "Protocol Version", "cpha.version", FT_UINT16, BASE_DEC, NULL, 0x0, "CPHAP Version", HFILL}},
483     { &hf_cluster_number,
484     { "Cluster Number", "cpha.cluster_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
485     { &hf_opcode,
486     { "OpCode", "cpha.opcode", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
487     { &hf_src_if_num,
488     { "Source Interface", "cpha.src_if", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
489     { &hf_random_id,
490     { "Random ID", "cpha.random_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
491     { &hf_src_machine_id,
492     { "Source Machine ID", "cpha.src_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
493     { &hf_dst_machine_id,
494     { "Destination Machine ID", "cpha.dst_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
495     { &hf_policy_id,
496     { "Policy ID", "cpha.policy_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
497     { &hf_filler,
498     { "Filler", "cpha.filler", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
499     { &hf_id_num,
500     { "Number of IDs reported", "cpha.id_num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
501     { &hf_report_code,
502     { "Report code", "cpha.id_num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
503     { &hf_ha_mode,
504     { "HA mode", "cpha.ha_mode", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
505     { &hf_ha_time_unit,
506     { "HA Time unit", "cpha.ha_time_unit", FT_UINT16, BASE_DEC, NULL, 0x0, "HA Time unit (ms)", HFILL}},
507     { &hf_num_reported_ifs,
508     { "Reported Interfaces", "cpha.reported_ifs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
509     { &hf_ethernet_add,
510     { "Ethernet Address", "cpha.ethernet_addr", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL}},
511     { &hf_is_if_trusted,
512     { "Interface Trusted", "cpha.if_trusted", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}},
513     { &hf_ip,
514     { "IP Address", "cpha.ip", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL}},
515     { &hf_slot_num,
516     { "Slot Number", "cpha.slot_num", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
517     { &hf_machine_num,
518     { "Machine Number", "cpha.machine_num", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
519     { &hf_seed,
520     { "Seed", "cpha.seed", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
521     { &hf_hash_len,
522     { "Hash list length", "cpha.hash_len", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
523     { &hf_in_up_num,
524     { "Interfaces up in the Inbound", "cpha.in_up", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
525     { &hf_in_assumed_up_num,
526     { "Interfaces assumed up in the Inbound", "cpha.in_assume_up", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
527     { &hf_out_up_num,
528     { "Interfaces up in the Outbound", "cpha.out_up", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
529     { &hf_out_assumed_up_num,
530     { "Interfaces assumed up in the Outbound", "cpha.out_assume_up", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
531     { &hf_status,
532     { "Status", "cpha.status", FT_UINT32, BASE_DEC, VALS(status_vals), 0x0, NULL, HFILL}},
533     { &hf_ifn,
534     { "Interface Number", "cpha.ifn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
535   };
536   static gint *ett[] = {
537     &ett_cphap,
538   };
539
540   proto_cphap = proto_register_protocol("Check Point High Availability Protocol",
541                                                "CPHA", "cpha");
542   proto_register_field_array(proto_cphap, hf, array_length(hf));
543   proto_register_subtree_array(ett, array_length(ett));
544 }
545
546 void
547 proto_reg_handoff_cpha(void)
548 {
549   dissector_handle_t cpha_handle;
550
551   cpha_handle = new_create_dissector_handle(dissect_cpha, proto_cphap);
552   dissector_add_uint("udp.port", UDP_PORT_CPHA, cpha_handle);
553 }