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