Use the new dissector API, and check whether the magic number and
[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.2 2002/08/20 22:56:29 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   static char           info[30];
203   guint16               opcode;
204
205   /*
206    * If the magic number or protocol version is unknown, don't treat this
207    * frame as a CPHA frame.
208    */
209   if (!tvb_bytes_exist(tvb, 0, 4)) {
210     /* Not enough data for the magic number or protocol version */
211     return 0;
212   }
213   hdr.magic_number = tvb_get_ntohs(tvb, 0);
214   hdr.ha_protocol_ver = tvb_get_ntohs(tvb, 2);
215   if (ha_magic_num2str(hdr.magic_number) == NULL) {
216     /* Bad magic number */
217     return 0;
218   }
219   if (version2str(hdr.ha_protocol_ver) == NULL) {
220     /* Bad version number */
221     return 0;
222   }
223
224   if (check_col(pinfo->cinfo, COL_PROTOCOL))
225     col_set_str(pinfo->cinfo, COL_PROTOCOL, "CPHA");
226   if (check_col(pinfo->cinfo, COL_INFO))
227     col_clear(pinfo->cinfo, COL_INFO);
228  
229   tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
230   hdr.magic_number = g_ntohs(hdr.magic_number);
231   hdr.ha_protocol_ver = g_ntohs(hdr.ha_protocol_ver);
232   hdr.random_id = g_ntohs(hdr.random_id);
233   hdr.src_if_num = g_ntohs(hdr.src_if_num);
234   hdr.src_machine_id = g_ntohs(hdr.src_machine_id);
235   hdr.dst_machine_id = g_ntohs(hdr.dst_machine_id);
236   hdr.policy_id = g_ntohs(hdr.policy_id);
237   hdr.filler = g_ntohs(hdr.filler);
238   opcode  = g_ntohs(hdr.opcode);
239
240   snprintf(info,50,"CPHAv%d: %s",g_ntohs(hdr.ha_protocol_ver), opcode2str_short(opcode)); 
241   if (check_col(pinfo->cinfo, COL_INFO)) 
242     col_add_str(pinfo->cinfo, COL_INFO,info);
243   
244   if (tree) {
245     ti = proto_tree_add_item(tree, proto_cphap, tvb, offset, -1, FALSE);
246     cpha_tree = proto_item_add_subtree(ti, ett_cphap);
247   }
248   if (tree) {
249     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));
250     offset += sizeof(hdr.magic_number);
251
252     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));
253     offset += sizeof(hdr.ha_protocol_ver);
254
255     proto_tree_add_uint(cpha_tree, hf_cluster_number, tvb, offset, sizeof(hdr.cluster_number), g_ntohs(hdr.cluster_number));
256     offset += sizeof(hdr.cluster_number);
257
258     proto_tree_add_uint_format(cpha_tree, hf_opcode, tvb, offset, sizeof(hdr.opcode), opcode,
259                         "HA OpCode: %d (%s - %s)", opcode, opcode2str_short(opcode), opcode2str_long(opcode));
260     offset += sizeof(hdr.opcode);
261
262     proto_tree_add_uint(cpha_tree, hf_src_if_num, tvb, offset, sizeof(hdr.src_if_num),
263                         hdr.src_if_num);
264     offset += sizeof(hdr.src_if_num);
265
266     proto_tree_add_uint(cpha_tree, hf_random_id, tvb, offset, sizeof(hdr.random_id), hdr.random_id);
267     offset += sizeof(hdr.random_id);
268
269     proto_tree_add_uint(cpha_tree, hf_src_machine_id, tvb, offset, sizeof(hdr.src_machine_id), hdr.src_machine_id);
270     offset += sizeof(hdr.src_machine_id);
271
272     proto_tree_add_uint(cpha_tree, hf_dst_machine_id, tvb, offset, sizeof(hdr.dst_machine_id), hdr.dst_machine_id);
273     offset += sizeof(hdr.dst_machine_id);
274     if(hdr.ha_protocol_ver != 1) {/* 4.1 - no policy_id and filler*/
275         proto_tree_add_uint(cpha_tree, hf_policy_id, tvb, offset, sizeof(hdr.policy_id), hdr.policy_id);
276         offset += sizeof(hdr.policy_id);
277   
278         proto_tree_add_uint(cpha_tree, hf_filler, tvb, offset, sizeof(hdr.filler), g_ntohs(hdr.filler));
279         offset += sizeof(hdr.filler);
280     }
281     nti = proto_tree_add_text(cpha_tree, tvb, offset, -1, opcode2str_short(opcode));
282     ntree = proto_item_add_subtree(nti, ett_cphap);
283  
284     switch(opcode) {
285         case 1: dissect_my_state(tvb, offset, ntree); /* FWHAP_MY_STATE */
286                 break;
287         case 2: break;
288         case 3:                                      /* FWHAP_IF_PROBE_REQ */
289         case 4: dissect_probe(tvb, offset, ntree);   /* FWHAP_IF_PROBE_RPLY */
290                 break;
291         case 5: break;
292         case 6: dissect_conf_reply(tvb, offset, ntree); /* FWHAP_IFCONF_RPLY */
293                 break;
294         case 7: dissect_lb_conf(tvb, offset, ntree); /* FWHAP_LB_CONF */
295                 break;
296         case 9: dissect_policy_change(tvb, offset, ntree); /* FWHAP_POLICY_CHANGE */
297                 break;
298         default: break;
299     }
300   }
301
302   return tvb_length(tvb);
303 }
304
305 static void dissect_my_state(tvbuff_t * tvb, int offset, proto_tree * tree) {
306   struct fwha_my_state_hdr hdr;
307   struct fwhap_if_state_s  if_hdr;
308   int rep_mode, i;
309   proto_item *  nti = NULL;
310   proto_tree *  ntree = NULL;
311  
312   tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr)); 
313   hdr.id_num = g_ntohs(hdr.id_num);
314   hdr.report_code = g_ntohs(hdr.report_code);
315   hdr.ha_mode = g_ntohs(hdr.ha_mode);
316   hdr.ha_time_unit = g_ntohs(hdr.ha_time_unit);
317  
318   proto_tree_add_uint(tree, hf_id_num, tvb, offset, sizeof(hdr.id_num), hdr.id_num);
319   offset += sizeof(hdr.id_num);
320
321   proto_tree_add_text(tree, tvb, offset, sizeof(hdr.report_code), "Report Code: %s",report_code2str(hdr.report_code));
322   offset += sizeof(hdr.report_code);
323
324   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));
325   offset += sizeof(hdr.ha_mode);
326
327   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);
328   offset += sizeof(hdr.ha_time_unit);
329   
330   rep_mode = is_report_ifs(hdr.report_code);
331   if (hdr.report_code & 1) {
332         /* states */
333         nti = proto_tree_add_text(tree, tvb, offset, hdr.id_num * sizeof(guint8), "Machine states");
334         ntree = proto_item_add_subtree(nti, ett_cphap);
335         for(i=0; i < hdr.id_num; i++) {
336                 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)));
337                 offset += sizeof(guint8);
338         }
339   }
340   if (hdr.report_code & 2) {
341         /* interface information */
342         nti = proto_tree_add_text(tree, tvb, offset, sizeof(struct fwhap_if_state_s), "Interface states");
343         ntree = proto_item_add_subtree(nti, ett_cphap);
344         tvb_memcpy(tvb, (guint8 *)&if_hdr, offset, sizeof(if_hdr));
345         proto_tree_add_int(ntree, hf_in_up_num, tvb, offset, sizeof(if_hdr.in_up_num), if_hdr.in_up_num);
346         offset += sizeof(if_hdr.in_up_num);
347         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);
348         offset += sizeof(if_hdr.in_assumed_up_num);
349         proto_tree_add_int(ntree, hf_out_up_num, tvb, offset, sizeof(if_hdr.out_up_num), if_hdr.out_up_num);
350         offset += sizeof(if_hdr.out_up_num);
351         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);
352         offset += sizeof(if_hdr.out_assumed_up_num);
353         
354         for(i=0; i < hdr.id_num; i++) {
355                 proto_tree_add_text(tree, tvb, offset, sizeof(guint8), "Cluster %d: last packet seen %d time units ago", i, tvb_get_guint8(tvb, offset));
356                 offset += sizeof(guint8);
357         }
358   }
359  
360 }
361
362 static void dissect_lb_conf(tvbuff_t * tvb, int offset, proto_tree * tree) {
363   struct lb_conf_hdr hdr;
364   
365   tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
366   hdr.slot_num = g_ntohs(hdr.slot_num);
367   hdr.machine_num = g_ntohs(hdr.machine_num);
368   hdr.seed = g_ntohs(hdr.seed);
369   hdr.hash_list_len = g_ntohs(hdr.hash_list_len);
370
371   proto_tree_add_uint(tree, hf_slot_num, tvb, offset, sizeof(hdr.slot_num), hdr.slot_num);
372   offset += sizeof(hdr.slot_num);
373
374   proto_tree_add_int(tree, hf_machine_num, tvb, offset, sizeof(hdr.machine_num), hdr.machine_num);
375   offset += sizeof(hdr.machine_num);
376
377   proto_tree_add_uint(tree, hf_seed, tvb, offset, sizeof(hdr.seed), hdr.seed);
378   offset += sizeof(hdr.seed);
379
380   proto_tree_add_uint(tree, hf_hash_len, tvb, offset, sizeof(hdr.hash_list_len), hdr.hash_list_len);
381   offset += sizeof(hdr.hash_list_len);
382
383 }
384
385 static void dissect_policy_change(tvbuff_t * tvb, int offset, proto_tree * tree) {
386   guint32 status;
387
388   status = tvb_get_ntohl(tvb, offset);
389
390   proto_tree_add_uint_format(tree, hf_status, tvb, offset, sizeof(status), status, "Status %d (%s)", status, status2str(status));
391   offset += sizeof(guint32);
392 }
393
394 static void dissect_probe(tvbuff_t * tvb, int offset, proto_tree * tree) {
395   guint32 ifn;
396
397   ifn = tvb_get_ntohl(tvb, offset);
398
399   proto_tree_add_uint(tree, hf_ifn, tvb, offset, sizeof(ifn), ifn);
400   offset += sizeof(guint32);
401 }
402
403 static void dissect_conf_reply(tvbuff_t * tvb, int offset, proto_tree * tree) {
404   struct conf_reply_hdr hdr;
405   
406   tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
407   hdr.num_reported_ifs = g_ntohl(hdr.num_reported_ifs);
408   hdr.is_if_trusted = g_ntohs(hdr.is_if_trusted);
409  
410   proto_tree_add_uint(tree, hf_num_reported_ifs, tvb, offset, sizeof(hdr.num_reported_ifs), hdr.num_reported_ifs);
411   offset += sizeof(hdr.num_reported_ifs);
412   proto_tree_add_ether(tree, hf_ethernet_add, tvb, offset, 6, hdr.ethernet_add);
413   offset += 6;
414
415   proto_tree_add_boolean(tree, hdr.is_if_trusted, tvb, offset, sizeof(hdr.is_if_trusted), hdr.is_if_trusted);
416   offset += sizeof(hdr.is_if_trusted);
417
418   proto_tree_add_ipv4(tree, hf_ip, tvb, offset, sizeof(hdr.ip), hdr.ip);
419   offset += 4;
420 }
421
422 int is_report_ifs(guint16 report_code) {
423   if(report_code & 2)
424         return 1;
425   return 0;
426 }
427
428 static const char *
429 report_code2str(guint16 report_code) {
430   int ret;
431   ret = is_report_ifs(report_code);
432   if(!(report_code & 1))
433         return "Machine information NOT present";
434   if(ret == 1)
435         return "Interface information included";
436   return "Unknown report code!";
437 }
438 static const char *
439 ha_magic_num2str(guint16 magic) {
440   if(magic == CPHA_MAGIC)
441         return "correct";
442   return NULL;
443 }
444
445 static const char *
446 version2str(guint16 version) {
447   switch(version) {
448         case 1: return "4.1";
449         case 6: return "NG Feature Pack 2";
450                 break;
451         case 530: return "NG Feature Pack 3";
452   }
453   return NULL;
454 }
455 static const char *
456 opcode2str_short(guint16 opcode) {
457   if(opcode <= NUM_OPCODE_TYPES)
458         return opcode_type_str_short[opcode];
459   return opcode_type_str_short[0];
460 }
461
462 static const char *
463 ha_mode2str(guint16 hamode) {
464   if(hamode <= NUM_HA_MODES)
465         return ha_mode_str[hamode];
466   return "Unknown HA mode";
467 }
468
469 static const char *
470 status2str(guint16 status) {
471   if(status <= NUM_STATUS)
472         return status_str[status];
473   return status_str[0];
474 }
475
476 static const char *
477 state2str(guint8 state) {
478   if(state <= NUM_STATES)
479         return state_str[state];
480   return state_str[0];
481 }
482
483
484 static const char *
485 opcode2str_long(guint16 opcode) {
486   if(opcode <= NUM_OPCODE_TYPES)
487         return opcode_type_str_long[opcode];
488   return opcode_type_str_long[0];
489 }
490
491 void
492 proto_register_cpha(void)
493 {
494   static hf_register_info hf[] = {
495     { &hf_magic_number,
496     { "CPHAP Magic Number", "cphap.magic_number", FT_UINT16, BASE_HEX, NULL, 0x0, "CPHAP Magic Number", HFILL}},
497     { &hf_cpha_protocol_ver,
498     { "Protocol Version", "cphap.version", FT_UINT16, BASE_DEC, NULL, 0x0, "CPHAP Version", HFILL}},
499     { &hf_cluster_number,
500     { "Cluster Number", "cphap.cluster_number", FT_UINT16, BASE_DEC, NULL, 0x0, "Cluster Number", HFILL}},
501     { &hf_opcode,
502     { "OpCode", "cphap.opcode", FT_UINT16, BASE_DEC, NULL, 0x0, "OpCode", HFILL}},
503     { &hf_src_if_num,
504     { "Source Interface", "cphap.src_if", FT_UINT16, BASE_DEC, NULL, 0x0, "Source Interface", HFILL}},
505     { &hf_random_id,
506     { "Random ID", "cphap.random_id", FT_UINT16, BASE_DEC, NULL, 0x0, "Random ID", HFILL}},
507     { &hf_src_machine_id,
508     { "Source Machine ID", "cphap.src_id", FT_UINT16, BASE_DEC, NULL, 0x0, "Source Machine ID", HFILL}},
509     { &hf_dst_machine_id,
510     { "Destination Machine ID", "cphap.dst_id", FT_UINT16, BASE_DEC, NULL, 0x0, "Destination Machine ID", HFILL}},
511     { &hf_policy_id,
512     { "Policy ID", "cphap.policy_id", FT_UINT16, BASE_DEC, NULL, 0x0, "Policy ID", HFILL}},
513     { &hf_filler,
514     { "Filler", "cphap.filler", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
515     { &hf_id_num,
516     { "Number of IDs reported", "cphap.id_num", FT_UINT16, BASE_DEC, NULL, 0x0, "Number of IDs reported", HFILL}},
517     { &hf_report_code,
518     { "Report code", "cphap.id_num", FT_UINT16, BASE_BIN, NULL, 0x0, "Report Code", HFILL}},
519     { &hf_ha_mode,
520     { "HA mode", "cphap.ha_mode", FT_UINT16, BASE_DEC, NULL, 0x0, "HA Mode", HFILL}},
521     { &hf_ha_time_unit,
522     { "HA Time unit (ms)", "cphap.ha_time_unit", FT_UINT16, BASE_DEC, NULL, 0x0, "HA Time unit", HFILL}},
523     { &hf_num_reported_ifs,
524     { "Reported Interfaces", "cphap.reported_ifs", FT_UINT32, BASE_DEC, NULL, 0x0, "Reported Interfaces", HFILL}},
525     { &hf_ethernet_add,
526     { "Ethernet Address", "cphap.ethernet_addr", FT_ETHER, BASE_HEX, NULL, 0x0, "Ethernet Address", HFILL}},
527     { &hf_is_if_trusted,
528     { "Interface Trusted", "cphap.if_trusted", FT_BOOLEAN, BASE_DEC, NULL, 0x0, "Interface Trusted", HFILL}},
529     { &hf_ip,
530     { "IP Address", "cphap.ip", FT_IPv4, BASE_DEC, NULL, 0x0, "IP Address", HFILL}},
531     { &hf_slot_num,
532     { "Slot Number", "cphap.slot_num", FT_INT16, BASE_DEC, NULL, 0x0, "Slot Number", HFILL}},
533     { &hf_machine_num, 
534     { "Machine Number", "cphap.machine_num", FT_INT16, BASE_DEC, NULL, 0x0, "Machine Number", HFILL}},
535     { &hf_seed,
536     { "Seed", "cphap.seed", FT_UINT32, BASE_DEC, NULL, 0x0, "Seed", HFILL}},
537     { &hf_hash_len,
538     { "Hash list length", "cphap.hash_len", FT_INT32, BASE_DEC, NULL, 0x0, "Hash list length", HFILL}},
539     { &hf_in_up_num,
540     { "Interfaces up in the Inbound", "cphap.in_up", FT_INT8, BASE_DEC, NULL, 0x0, "Interfaces up in the Inbound", HFILL}},
541     { &hf_in_assumed_up_num,
542     { "Interfaces assumed up in the Inbound", "cphap.in_assume_up", FT_INT8, BASE_DEC, NULL, 0x0, "", HFILL}},  
543     { &hf_out_up_num,
544     { "Interfaces up in the Outbound", "cphap.out_up", FT_INT8, BASE_DEC, NULL, 0x0, "", HFILL}},
545     { &hf_out_assumed_up_num, 
546     { "Interfaces assumed up in the Outbound", "cphap.out_assume_up", FT_INT8, BASE_DEC, NULL, 0x0, "", HFILL}},
547     { &hf_status,
548     { "Status", "cphap.status", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
549     { &hf_ifn, 
550     { "Interface Number", "cpha.ifn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
551   };
552   static gint *ett[] = {
553     &ett_cphap,
554   };
555   
556   proto_cphap = proto_register_protocol("Check Point High Availability Protocol",
557                                                "CPHA", "cpha");
558   proto_register_field_array(proto_cphap, hf, array_length(hf));
559   proto_register_subtree_array(ett, array_length(ett)); 
560 }
561
562 void
563 proto_reg_handoff_cpha(void)
564 {
565   dissector_handle_t cpha_handle;
566
567   cpha_handle = new_create_dissector_handle(dissect_cpha, proto_cphap);
568   dissector_add("udp.port", UDP_PORT_CPHA, cpha_handle);
569 }