Wireshark-users: Re: [Wireshark-users] Error with wireshark-0.99.5
Date: Sun, 29 Jun 2008 13:26:17 +0200
> Lina wrote:
> Date: Tue, 24 Jun 2008 11:45:49 +0200
> I try to install wireshark-0.99.5, following those instructions:
> http://hipserver.mct.phantomworks.org/wireshark.html
> (Paragraph patch instructions). In fact, I want to use the wireshark
> supporting HIP packets.
> make gives me the following errors:
> gcc: getopt.o: No such file or directory
> gcc: strerror.o: No such file or directory
> gcc: strcasecmp.o: No such file or directory
> gcc: strncasecmp.o: No such file or directory
> gcc: mkstemp.o: No such file or directory
> gcc: strptime.o: No such file or directory
> make[2]: *** [wireshark] Error 1
> 
> I tried many things, aclocal,autoconf, make clean but still the same error
with make and make install.

Hi Lina

I downloaded wireshark-0.99.5.tar.bz2 (ftp://ftp.uni-kl.de/pub/wireshark/src/all-versions)
and wireshark-0.99.5-hip-base05.patch (http://hipserver.mct.phantomworks.org/wireshark.html).

I modified this patch by replacing "ethereal-0.99.0" by "wireshark-0.99.5"
(see the attachment).
I have patched wireshark-0.99.5 and build Wireshark on PCLinuxOS2008.
It seems to work fine, but I don't have a capture file to test it.
Do you have a sample HIP capture file?

Grtz
Joan

       


#
# HIP protocol patch for wireshark-0.99.5
# 3/06 draft-ietf-hip-base-05
#      draft-ietf-hip-esp-02
#      draft-ietf-hip-mm-03
#      draft-ietf-hip-registration-01
#      draft-ietf-hip-rvs-04
#
# Authors:	<thomas.r.henderson@xxxxxxxxxx>
#		<jeffrey.m.ahrenholz@xxxxxxxxxx>
#
*** wireshark-0.99.5/epan/dissectors/Makefile.in	2006-04-24 09:21:23.000000000 -0700
--- wireshark-0.99.5-hip/epan/dissectors/Makefile.in	2006-05-01 09:11:13.000000000 -0700
***************
*** 209,213 ****
  	packet-h248_annex_e.lo packet-h248_q1950.lo packet-h261.lo \
  	packet-h263.lo packet-h450.lo packet-hci_h4.lo \
! 	packet-hclnfsd.lo packet-homeplug.lo packet-hpext.lo \
  	packet-hpsw.lo packet-hsrp.lo packet-http.lo \
  	packet-hyperscsi.lo packet-iapp.lo packet-iax2.lo packet-ib.lo \
--- 209,213 ----
  	packet-h248_annex_e.lo packet-h248_q1950.lo packet-h261.lo \
  	packet-h263.lo packet-h450.lo packet-hci_h4.lo \
! 	packet-hclnfsd.lo packet-homeplug.lo packet-hip.lo packet-hpext.lo \
  	packet-hpsw.lo packet-hsrp.lo packet-http.lo \
  	packet-hyperscsi.lo packet-iapp.lo packet-iax2.lo packet-ib.lo \
***************
*** 859,862 ****
--- 859,863 ----
  	packet-h450.c	\
  	packet-hclnfsd.c	\
+ 	packet-hip.c	\
  	packet-hpext.c	\
  	packet-hpsw.c	\
***************
*** 1849,1852 ****
--- 1850,1854 ----
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet-h450.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet-hclnfsd.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet-hip.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet-hpext.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet-hpsw.Plo@am__quote@
*** wireshark-0.99.5/epan/dissectors/Makefile.common	2006-04-17 07:46:42.000000000 -0700
--- wireshark-0.99.5-hip/epan/dissectors/Makefile.common	2006-05-01 09:10:00.000000000 -0700
***************
*** 328,331 ****
--- 328,332 ----
  	packet-h450.c	\
  	packet-hclnfsd.c	\
+ 	packet-hip.c	\
  	packet-hpext.c	\
  	packet-hpsw.c	\
*** wireshark-0.99.5/epan/dissectors/register.c	2006-04-21 14:57:37.000000000 -0700
--- wireshark-0.99.5-hip/epan/dissectors/register.c	2006-05-01 09:10:00.000000000 -0700
***************
*** 247,250 ****
--- 247,251 ----
    {extern void proto_register_h450 (void); proto_register_h450 ();}
    {extern void proto_register_hclnfsd (void); proto_register_hclnfsd ();}
+   {extern void proto_register_hip (void); proto_register_hip ();}
    {extern void proto_register_hpext (void); proto_register_hpext ();}
    {extern void proto_register_hpsw (void); proto_register_hpsw ();}
***************
*** 869,872 ****
--- 870,874 ----
    {extern void proto_reg_handoff_h4501 (void); proto_reg_handoff_h4501 ();}
    {extern void proto_reg_handoff_hclnfsd (void); proto_reg_handoff_hclnfsd ();}
+   {extern void proto_reg_handoff_hip (void); proto_reg_handoff_hip ();}
    {extern void proto_reg_handoff_hpext (void); proto_reg_handoff_hpext ();}
    {extern void proto_reg_handoff_hpsw (void); proto_reg_handoff_hpsw ();}
*** wireshark-0.99.5/epan/ipproto.h	2006-04-17 07:46:53.000000000 -0700
--- wireshark-0.99.5-hip/epan/ipproto.h	2006-05-01 09:10:00.000000000 -0700
***************
*** 185,188 ****
--- 185,189 ----
  #define IP_PROTO_AX4000		173		/* AX/4000 Testblock - non IANA */
  #define IP_PROTO_NCS_HEARTBEAT  224             /* Novell NCS Heartbeat - http://support.novell.com/cgi-bin/search/searchtid.cgi?/10071158.htm */
+ #define IP_PROTO_HIP		253		/* Host Identity Protocol */
  
  extern const char *ipprotostr(int proto);
*** wireshark-0.99.5/epan/prefs.c	2006-04-17 07:46:53.000000000 -0700
--- wireshark-0.99.5-hip/epan/prefs.c	2006-05-01 09:10:00.000000000 -0700
***************
*** 1993,1996 ****
--- 1993,2000 ----
          if (strcmp(dotp, "udp_summary_in_tree") == 0)
            pref = find_preference(module, "summary_in_tree");
+       } else if (strcmp(module->name, "hip") == 0) {
+         /* Handle old names for HIP preferences. */
+         if (strcmp(dotp, "hip_summary_in_tree") == 0)
+           pref = find_preference(module, "summary_in_tree");
        } else if (strcmp(module->name, "ndps") == 0) {
          /* Handle old names for NDPS preferences. */
*** wireshark-0.99.5/epan/dissectors/packet-hip.c	1969-12-31 16:00:00.000000000 -0800
--- wireshark-0.99.5-hip/epan/dissectors/packet-hip.c	2006-05-01 09:10:00.000000000 -0700
***************
*** 0 ****
--- 1,1235 ----
+ /* packet-hip.c
+  * Routines for HIP packet disassembly
+  *
+  * 03/2006 draft-ietf-hip-base-05, -esp-02, -mm-03, -registration-01, -rvs-04
+  * 07/2005 draft-ietf-hip-base-03, -esp-00, and -mm-02
+  * 03/2005 draft-ietf-hip-base-01
+  * 11/2004 RSA and draft-ietf-hip-mm-00
+  * 09/2004 draft-nikander-hip-mm-02
+  * 07/2004 draft-ietf-hip-base-00
+  * 02/2004
+  * 03/2003
+  *
+  * Jeff Ahrenholz <jeffrey.m.ahrenholz@xxxxxxxxxx>
+  * Thomas Henderson <thomas.r.henderson@xxxxxxxxxx>
+  * 
+  * Packet dissector for Host Identity Protocol (HIP) packets.
+  * This tool displays the TLV structure, verifies checksums,
+  * and shows NULL encrypted parameters, but will not verify 
+  * signatures or decode encrypted parameters.
+  *
+  * $Id: wireshark-0.99.5-hip-base05.patch,v 1.1 2006/05/16 21:37:14 tom_henderson Exp $
+  *
+  * Ethereal - Network traffic analyzer
+  * By Gerald Combs <gerald@xxxxxxxxxxxx>
+  * Copyright 1998 Gerald Combs
+  * 
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+  * as published by the Free Software Foundation; either version 2
+  * of the License, or (at your option) any later version.
+  * 
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  * 
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  */
+  
+ #ifdef HAVE_CONFIG_H
+ # include "config.h"
+ #endif
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ 
+ #include <glib.h>
+ #include <epan/packet.h>
+ #include <epan/addr_resolv.h>
+ #include "ipproto.h"
+ #include "in_cksum.h"
+ #include "prefs.h"
+ 
+ 
+ #include "packet-ip.h"
+ #include <epan/conversation.h>
+ 
+ static int proto_hip = -1;
+ static int hf_hip_proto = -1;
+ static int hf_hip_hdr_len = -1;
+ static int hf_hip_packet_type = -1;
+ static int hf_hip_version = -1;
+ static int hf_hip_res = -1;
+ static int hf_hip_controls = -1;
+ static int hf_hip_controls_cert = -1;
+ static int hf_hip_controls_anon = -1;
+ static int hf_hip_checksum = -1;
+ static int hf_hip_hit_sndr = -1;
+ static int hf_hip_hit_rcvr = -1;
+ 
+ static int hf_hip_type = -1;
+ static int hf_hip_tlv_ei_res = -1;
+ static int hf_hip_tlv_ei_keyidx = -1;
+ static int hf_hip_tlv_ei_oldspi = -1;
+ static int hf_hip_tlv_ei_newspi = -1;
+ static int hf_hip_tlv_r1_res = -1;
+ static int hf_hip_tlv_r1count = -1;
+ static int hf_hip_tlv_puzzle_k = -1;
+ static int hf_hip_tlv_puzzle_life = -1;
+ static int hf_hip_tlv_puzzle_o = -1;
+ static int hf_hip_tlv_puzzle_i = -1;
+ static int hf_hip_tlv_puzzle_j = -1;
+ static int hf_hip_tlv_seq_updid = -1;
+ static int hf_hip_tlv_ack_updid = -1;
+ static int hf_hip_tlv_dh_group_id = -1;
+ static int hf_hip_tlv_dh_pub = -1;
+ static int hf_hip_tlv_trans_id = -1;
+ static int hf_hip_tlv_esp_reserved = -1;
+ static int hf_hip_tlv_host_id_len = -1;
+ static int hf_hip_tlv_host_di_type = -1;
+ static int hf_hip_tlv_host_di_len = -1;
+ static int hf_hip_tlv_host_id_hdr = -1;
+ static int hf_hip_tlv_host_id_hdr_flags = -1;
+ static int hf_hip_tlv_host_id_hdr_proto = -1;
+ static int hf_hip_tlv_host_id_hdr_alg = -1;
+ static int hf_hip_tlv_host_id_t = -1;
+ static int hf_hip_tlv_host_id_q = -1;
+ static int hf_hip_tlv_host_id_p = -1;
+ static int hf_hip_tlv_host_id_g = -1;
+ static int hf_hip_tlv_host_id_y = -1;
+ static int hf_hip_tlv_host_id_e_len = -1;
+ static int hf_hip_tlv_host_id_e = -1;
+ static int hf_hip_tlv_host_id_n = -1;
+ static int hf_hip_tlv_cert_count = -1;
+ static int hf_hip_tlv_cert_id = -1;
+ static int hf_hip_tlv_cert_type = -1;
+ static int hf_hip_tlv_certificate = -1;
+ static int hf_hip_tlv_notify_res = -1;
+ static int hf_hip_tlv_notify_type = -1;
+ static int hf_hip_tlv_notify_data = -1;
+ static int hf_hip_tlv_opaque_data = -1;
+ static int hf_hip_tlv_reg_ltmin = -1;
+ static int hf_hip_tlv_reg_ltmax = -1;
+ static int hf_hip_tlv_reg_lt = -1;
+ static int hf_hip_tlv_reg_type = -1;
+ static int hf_hip_tlv_reg_failtype = -1;
+ static int hf_hip_tlv_hmac = -1;
+ static int hf_hip_tlv_sig_alg = -1;
+ static int hf_hip_tlv_sig = -1;
+ static int hf_hip_tlv_id = -1;
+ static int hf_hip_tlv_enc_reserved = -1;
+ static int hf_hip_tlv_enc_iv = -1;
+ static int hf_hip_tlv_locator_traffic_type = -1;
+ static int hf_hip_tlv_locator_type = -1;
+ static int hf_hip_tlv_locator_len = -1;
+ static int hf_hip_tlv_locator_reserved = -1;
+ static int hf_hip_tlv_locator_lifetime = -1;
+ static int hip_transform = 0;
+ 
+ static gint ett_hip = -1;
+ static gint ett_hip_controls = -1;
+ static gint ett_hip_tlv = -1;
+ static gint ett_hip_tlv_data = -1;
+ static gint ett_hip_tlv_host_id_hdr = -1;
+ 
+ /* Place HIP summary in protocol tree */
+ static gboolean hip_summary_in_tree = TRUE;
+ 
+ /* This minimal structure used to get at the Type field*/
+ struct newhip {
+         guint16 nextpluslen;        /* Next header, plus length */
+         guint8 hiptype;        /* Type (what we are after) */
+         guint8 hipreserved;        /* Reserved (what we are after) */
+         /*variable size*/               /* (IV and) Payload data */
+ };
+ 
+ /* 128-bit Host Identity Tag */
+ #define HIT_BITSIZE 128
+ typedef unsigned char hip_hit [HIT_BITSIZE/8];
+ 
+ #define HI_ALG_DSA 3
+ #define HI_ALG_RSA 5
+ 
+ /* HIP packet types */
+ typedef enum {
+ 	HIP_I1=1,
+ 	HIP_R1,
+ 	HIP_I2,
+ 	HIP_R2,
+ 	CER,	/* 5 - removed from draft-ietf-hip-base-03 */
+ 	BOS=11,	/* 11 - removed from draft-ietf-hip-base-01 */
+ 	UPDATE=16, /* 16 */
+ 	NOTIFY=17, /* 17 */
+ 	CLOSE=18,  /* 18 */
+ 	CLOSE_ACK=19, /* 19 */
+ } HIP_PACKETS;
+ 
+ /* HIP TLV parameters */
+ /* 03/2006 draft-ietf-hip-base-05, -esp-02, -mm-03, -registration-01, -rvs-04 */
+ #define PARAM_ESP_INFO			65
+ #define PARAM_R1_COUNTER		128
+ #define PARAM_LOCATOR			193
+ #define PARAM_PUZZLE			257
+ #define PARAM_SOLUTION			321
+ #define PARAM_SEQ			385
+ #define PARAM_ACK			449
+ #define PARAM_DIFFIE_HELLMAN		513
+ #define PARAM_HIP_TRANSFORM		577
+ #define PARAM_ENCRYPTED			641
+ #define PARAM_HOST_ID			705
+ #define PARAM_CERT			768
+ #define PARAM_NOTIFY			832
+ #define PARAM_ECHO_REQUEST		897
+ #define PARAM_REG_INFO			930
+ #define PARAM_REG_REQUEST		932
+ #define PARAM_REG_RESPONSE		934
+ #define PARAM_REG_FAILED		936
+ #define PARAM_ECHO_RESPONSE		961
+ #define PARAM_ESP_TRANSFORM		4095
+ #define PARAM_TRANSFORM_LOW		2048 /* defines range for transforms */
+ #define PARAM_TRANSFORM_HIGH		4095
+ #define PARAM_HMAC			61505
+ #define PARAM_HMAC_2			61569
+ #define PARAM_HIP_SIGNATURE_2		61633
+ #define PARAM_HIP_SIGNATURE		61697
+ #define PARAM_ECHO_REQUEST_NOSIG	63661
+ #define PARAM_ECHO_RESPONSE_NOSIG	63425
+ #define PARAM_FROM			65498
+ #define PARAM_RVS_HMAC			65500
+ #define PARAM_VIA_RVS			65502
+ #define PARAM_CRITICAL_BIT		0x0001
+ 
+ #define HIP_CONTROL_C_MASK	0x0002
+ #define HIP_CONTROL_A_MASK	0x0001
+ 
+ #define HI_HDR_FLAGS_MASK	0xFFFF0000
+ #define HI_HDR_PROTO_MASK	0x0000FF00
+ #define HI_HDR_ALG_MASK		0x000000FF
+ 
+ const value_string hi_hdr_flags_vals[] = {
+ 	{ 0x0200, "key is associated with a user" },
+ 	{ 0x0201, "zone key" },
+ 	{ 0x0202, "key is associated with non-zone entity" },
+ 	{ 0x0, "Other" },
+ };
+ 
+ const value_string hi_hdr_proto_vals[] = {
+ 	{ 0x01, "key is used for TLS" },
+ 	{ 0x02, "key is used for email" },
+ 	{ 0x03, "key is used for DNS security" },
+ 	{ 0x04, "key is used for Oakley/IPSEC" },
+ 	{ 0xFF, "key is valid for any protocol" },
+ 	{ 0x0, NULL },
+ };
+ 
+ const value_string hi_hdr_alg_vals[] = {
+ 	{ 0x00, "reserved" },
+ 	{ 0x01, "RSA/MD5" },
+ 	{ 0x02, "Diffie-Hellman" },
+ 	{ 0x03, "DSA" },
+ 	{ 0x04, "elliptic curve crypto" },
+ 	{ 0x05, "RSA" },
+ 	{ 0xFF, "reserved" },
+ };
+ 
+ const value_string notify_vals[] = {
+ 	{ 1, "Unsupported critical parameter type" },
+ 	{ 7, "Invalid syntax" },
+ 	{ 14, "No Diffie-Hellman proposal chosen" },
+ 	{ 15, "Invalid Diffie-Hellman chosen" },
+ 	{ 16, "No HIP proposal chosen" },
+ 	{ 17, "Invalid HIP transform chosen" },
+ 	{ 18, "No ESP proposal chosen" },
+ 	{ 19, "Invalid ESP transform chosen" },
+ 	{ 24, "Authentication failed" },
+ 	{ 26, "Checksum failed" },
+ 	{ 28, "HMAC failed" },
+ 	{ 32, "Encryption failed" },
+ 	{ 40, "Invalid HIT" },
+ 	{ 42, "Blocked by policy" },
+ 	{ 44, "Server busy please retry" },
+ 	{ 46, "I2 acknowledgement" },
+ 	{ 0x0, NULL },
+ };
+ 
+ typedef struct _hiphdr {
+     guint8 proto;        /* payload protocol            */
+     guint8 hdr_len;      /* header length               */
+     guint8 packet_type;  /* packet type                 */
+     guint8 res:4,version:4; /* version, reserved        */
+     guint16 checksum;    /* checksum                    */
+     guint16 control;     /* control                     */
+     hip_hit hit_sndr;    /* Sender's Host Identity Tag  */
+     hip_hit hit_rcvr;    /* Receiver's Host Identity Tag*/
+     /* HIP parameters ...  */
+ } hiphdr;
+ 
+ typedef struct _tlv_head
+ {
+     guint16 type;
+     guint16 length;
+ } tlv_head;
+ 
+ 
+ /* functions */
+ char * hip_param(int n);
+ char *dh_group_id_label(int groupid);
+ char *transform_id_label(int transform);
+ char *sig_alg_label(int alg);
+ int dissect_hip_tlv(tvbuff_t *tvb, int offset, proto_item *ti, int type, int tlv_len);
+ 
+ static dissector_handle_t data_handle;
+ 
+ /**** end defs from hip.h ****/
+ 
+ /*
+  * Dissect the HIP packet 
+  */
+ static void
+ dissect_hip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+ {
+     proto_tree *hip_tree, *hip_tlv_tree=NULL;
+     proto_item *ti, *ti_tlv;
+     hiphdr hiph;
+     tlv_head tlv;
+     int length, offset = 0;
+     guint16 control_h, checksum_h, computed_checksum;
+     guint16 tlv_type_h, tlv_length_h; /* For storing in host order */
+     vec_t cksum_vec[4];
+     guint32 phdr[2];
+ 
+     /*
+      * load the top pane info. This should be overwritten by
+      * the next protocol in the stack
+      */
+     if (check_col(pinfo->cinfo, COL_PROTOCOL))
+         col_set_str(pinfo->cinfo, COL_PROTOCOL, "HIP");
+     if (check_col(pinfo->cinfo, COL_INFO))
+         col_clear(pinfo->cinfo, COL_INFO);
+ 
+     /* Convert control and checksum to host order */
+ 
+     tvb_memcpy(tvb, (guint8 *)&hiph, 0, sizeof(hiphdr));
+     control_h = g_ntohs(hiph.control);
+     checksum_h = g_ntohs(hiph.checksum);
+ 
+     if (check_col(pinfo->cinfo, COL_INFO)) {
+         switch (hiph.packet_type) {
+             case HIP_I1:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP I1 (HIP Initiator Packet)");
+                 break;
+             case HIP_R1:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP R1 (HIP Responder Packet)");
+                 break;
+             case HIP_I2:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP I2 (Second HIP Initiator Packet)");
+                 break;
+             case HIP_R2:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP R2 (Second HIP Responder Packet)");
+                 break;
+             case UPDATE:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP UPDATE (HIP Update Packet)");
+                 break;
+             case CER:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP CER (HIP Certificate Packet)");
+                 break;
+             case BOS:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP BOS (HIP Bootstrap Packet)");
+                 break;
+             case NOTIFY:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP NOTIFY (HIP Notification Packet)");
+                 break;
+             case CLOSE:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP CLOSE (HIP Close Packet)");
+                 break;
+             case CLOSE_ACK:
+                 col_add_fstr(pinfo->cinfo, COL_INFO,
+ 			"HIP CLOSE_ACK (HIP Close Acknowledgement Packet)");
+                 break;
+             default:
+                 col_add_fstr(pinfo->cinfo, COL_INFO, "HIP Unknown type");
+                 break;
+         }
+     }
+ 
+     /*
+      * populate a tree in the second pane with the status of the link layer
+      * (ie none)
+      */
+     if(tree) {
+ 	if (hip_summary_in_tree) {
+             ti = proto_tree_add_protocol_format(tree, proto_hip, tvb, 0, -1, "Host Identity Protocol");
+ 	} else {
+             ti = proto_tree_add_item(tree, proto_hip, tvb, 0, -1, FALSE);
+         }
+ 
+         hip_tree = proto_item_add_subtree(ti, ett_hip);
+ 	proto_tree_add_uint(hip_tree, hf_hip_proto, tvb, offset, 1, hiph.proto);
+ 	proto_tree_add_uint(hip_tree, hf_hip_hdr_len, tvb, offset+1, 1, hiph.hdr_len);
+ 	proto_tree_add_uint(hip_tree, hf_hip_packet_type, tvb, offset+2, 1, hiph.packet_type);
+ 	proto_tree_add_uint_format(hip_tree, hf_hip_version, tvb, offset+3, 1, hiph.version,
+ 		"Version: %u, Reserved: %u", hiph.version, hiph.res);
+ 	ti = proto_tree_add_uint(hip_tree, hf_hip_controls, tvb, offset+4, 2, control_h);
+ 	if (ti) { /* HIP Controls subtree*/
+ 		ti = proto_item_add_subtree(ti, ett_hip_controls);
+ 		proto_tree_add_boolean(ti, hf_hip_controls_cert, tvb, offset+5,1, control_h);
+ 		proto_tree_add_boolean(ti, hf_hip_controls_anon, tvb, offset+5,1, control_h);
+ 	}
+ 	
+ 	
+ 	/* Checksum - this is the same algorithm from UDP, ICMPv6 */
+ 	if (!pinfo->fragmented) {
+ 	    /* IPv4 or IPv6 addresses */
+ 	    cksum_vec[0].ptr = pinfo->src.data;
+ 	    cksum_vec[0].len = pinfo->src.len;
+ 	    cksum_vec[1].ptr = pinfo->dst.data;
+ 	    cksum_vec[1].len = pinfo->dst.len;
+ 	    /* the rest of the pseudo-header */
+ 	    if (pinfo->src.type == AT_IPv6) {
+ 		cksum_vec[2].ptr = (const guint8 *)&phdr;
+ 		phdr[0] = g_htonl(tvb_reported_length(tvb));
+ 		phdr[1] = g_htonl(IP_PROTO_HIP);
+ 		cksum_vec[2].len = 8;
+ 	    } else {
+ 		cksum_vec[2].ptr = (const guint8 *)&phdr;
+ 		phdr[0] = g_htonl((IP_PROTO_HIP<<16)+tvb_reported_length(tvb));
+ 		cksum_vec[2].len = 4;
+ 	    }
+ 	    /* pointer to the HIP header (packet data) */
+ 	    cksum_vec[3].len = tvb_reported_length(tvb);
+ 	    cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, cksum_vec[3].len);
+ 	    computed_checksum = in_cksum(cksum_vec, 4);
+ 	    if (computed_checksum == 0) {
+ 		proto_tree_add_uint_format(hip_tree, hf_hip_checksum, tvb, 
+ 			offset+6, 2, checksum_h, "Checksum: 0x%04x (correct)",
+ 			checksum_h);
+ 	    } else {
+ 		proto_tree_add_uint_format(hip_tree, hf_hip_checksum, tvb,
+ 			offset+6, 2, checksum_h,
+ 			"Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ 			checksum_h,
+ 			in_cksum_shouldbe(checksum_h, computed_checksum));
+ 	    }
+ 	} else {
+ 		proto_tree_add_uint_format(hip_tree, hf_hip_checksum, tvb,
+ 			offset+6, 2, checksum_h,"Checksum: 0x%04x (unverified)",
+ 			checksum_h);
+ 	}
+ 	offset += 8;
+ 	proto_tree_add_bytes(hip_tree, hf_hip_hit_sndr, tvb, offset, sizeof(hip_hit), hiph.hit_sndr);
+ 	offset += sizeof(hip_hit);
+ 	proto_tree_add_bytes(hip_tree, hf_hip_hit_rcvr, tvb, offset, sizeof(hip_hit), hiph.hit_rcvr);
+ 	offset += sizeof(hip_hit);
+ 	
+ 	length = (hiph.hdr_len+1)*8;
+ 	/* Begin TLV parsing */
+ 	if (offset < length) {
+ 	    ti_tlv = proto_tree_add_text(hip_tree, tvb, offset, tvb_length(tvb), "HIP Parameters");
+ 	    hip_tlv_tree = proto_item_add_subtree(ti_tlv, ett_hip_tlv);
+ 	}
+ 	/* Parse type and length in TLV */
+ 	while (offset < length)
+ 	{
+             tvb_memcpy(tvb, (guint8 *)&tlv, offset, sizeof(tlv_head));
+ 	    tlv_type_h = g_ntohs(tlv.type);
+ 	    tlv_length_h = g_ntohs(tlv.length);
+ 	    ti_tlv = proto_tree_add_uint_format(hip_tlv_tree, hf_hip_type, tvb,
+ 		offset, 4+tlv_length_h, tlv.type, "%s (type=%u, length=%u)",
+ 		hip_param(tlv_type_h), tlv_type_h, tlv_length_h);
+ 	    
+ 	    /* Parse value */
+ 	    dissect_hip_tlv(tvb, offset, ti_tlv, tlv_type_h, tlv_length_h);
+ 
+ 	    offset += 11 + tlv_length_h - (tlv_length_h + 3) % 8;
+ 	}
+ 	
+     }
+ }
+ 
+ void
+ proto_register_hip(void)
+ {
+ /* Most of this stuff is unused */
+ 	module_t *hip_module;
+ 	static hf_register_info hf[] = {
+ 	        { &hf_hip_proto,
+ 		{ "Payload Protocol",   "hip.proto", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_hdr_len,
+ 		{ "Header Length",      "hip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_packet_type,
+ 		{ "Packet Type",        "hip.packet_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_version,
+ 		{ "Version",            "hip.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_res,
+ 		{ "Reserved",           "hip.res", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_controls,
+ 		{ "HIP Controls",            "hip.controls", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_controls_cert,
+ 		{ "Certificate (One or more CER packets follows)",            "hip.controls.c", FT_BOOLEAN, 16, NULL, HIP_CONTROL_C_MASK, "", HFILL }},
+ 		
+ 	        { &hf_hip_controls_anon,
+ 		{ "Anonymous (Sender's HI is anonymous)",            "hip.controls.a", FT_BOOLEAN, 16, NULL, HIP_CONTROL_A_MASK, "", HFILL }},
+ 		
+ 	        { &hf_hip_checksum,
+ 		{ "Checksum",           "hip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_hit_sndr,
+ 		{ "Sender's HIT",       "hip.hit_sndr", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_hit_rcvr,
+ 		{ "Receiver's HIT",     "hip.hit_rcvr", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 
+ 		{ &hf_hip_type,
+ 		{ "Type",               "hip.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_r1_res,
+ 		{ "Reserved",                "hip.tlv.r1_res", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_r1count,
+ 		{ "R1 Counter",                "hip.tlv.r1count", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_puzzle_k,
+ 		{ "Puzzle Difficulty K","hip.tlv_puzzle_k", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_puzzle_life,
+ 		{ "Puzzle Lifetime","hip.tlv_puzzle_life", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_puzzle_o,
+ 		{ "Opaque Data","hip.tlv_puzzle_o", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_puzzle_i,
+ 		{ "Puzzle Random I",    "hip.tlv.puzzle_i", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_puzzle_j,
+ 		{ "Puzzle Solution J",    "hip.tlv_puzzle_j", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_ei_res,
+ 		{ "Reserved", "hip.tlv_ei_res", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_ei_keyidx,
+ 		{ "Keymat Index", "hip.tlv_ei_keyidx", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_ei_oldspi,
+ 		{ "Old SPI", "hip.tlv_ei_oldspi", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_ei_newspi,
+ 		{ "New SPI", "hip.tlv_ei_newspi", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_seq_updid,
+ 		{ "Update ID", "hip.tlv_seq_updid", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 	        { &hf_hip_tlv_ack_updid,
+ 		{ "ACKed Peer Update ID", "hip.tlv_ack_updid", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_dh_group_id,
+ 		{ "Group ID",           "hip.tlv.dh_group_id", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_dh_pub,
+ 		{ "Public Value",       "hip.tlv.dh_pub", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_trans_id,
+ 		{ "Transform ID",       "hip.tlv.trans_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_esp_reserved,
+ 		{ "Reserved",       "hip.tlv.esp_reserved", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_len,
+ 		{ "Host Identity Length","hip.tlv.host_id_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_di_type,
+ 		{ "Domain Identifier Type","hip.tlv.host_di_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_di_len,
+ 		{ "Domain Identifier Length","hip.tlv.host_di_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_hdr,
+ 		{ "Host Identity flags","hip.tlv.host_id_hdr", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_hdr_flags,
+ 		{ "Flags","hip.tlv.host_id_hdr_flags", FT_UINT32, BASE_HEX, VALS(hi_hdr_flags_vals), HI_HDR_FLAGS_MASK, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_hdr_proto,
+ 		{ "Protocol","hip.tlv.host_id_hdr_flags", FT_UINT32, BASE_HEX, VALS(hi_hdr_proto_vals), HI_HDR_PROTO_MASK, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_hdr_alg,
+ 		{ "Algorithm","hip.tlv.host_id_hdr_alg", FT_UINT32, BASE_HEX, VALS(hi_hdr_alg_vals), HI_HDR_ALG_MASK, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_t,
+ 		{ "Host Identity T","hip.tlv.host_id_t", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_q,
+ 		{ "Host Identity Q","hip.tlv.host_id_q", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_p,
+ 		{ "Host Identity P","hip.tlv.host_id_p", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 
+                 { &hf_hip_tlv_host_id_g,
+ 		{ "Host Identity G","hip.tlv.host_id_g", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 
+                 { &hf_hip_tlv_host_id_y,
+ 		{ "Host Identity Y (public value)", "hip.tlv.host_id_y", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_e_len,
+ 		{ "RSA Host Identity e_len (exponent length)", 
+ 		  "hip.tlv.host_id_e_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_e,
+ 		{ "RSA Host Identity e (exponent)", "hip.tlv.host_id_e", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_host_id_n,
+ 		{ "RSA Host Identity n (public modulus)", "hip.tlv.host_id_n", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_cert_count,
+ 		{ "Cert count","hip.tlv.cert_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_cert_id,
+ 		{ "Cert ID","hip.tlv.cert_id", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_cert_type,
+ 		{ "Cert type","hip.tlv.cert_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_certificate,
+ 		{ "Certificate","hip.tlv.certificate", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_notify_res,
+ 		{ "Reserved","hip.tlv.notify_res", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_notify_type,
+ 		{ "Notify Message Type","hip.tlv.notify_type", FT_UINT16, BASE_DEC, VALS(notify_vals), 0xFFFF, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_notify_data,
+ 		{ "Notification Data","hip.tlv.notify_data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_opaque_data,
+ 		{ "Opaque Data","hip.tlv.opaque_data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_reg_ltmin,
+ 		{ "Minimum Registration Lifetime","hip.tlv.reg_ltmin", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_reg_ltmax,
+ 		{ "Maximum Registration Lifetime","hip.tlv.reg_ltmax", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_reg_lt,
+ 		{ "Registration Lifetime","hip.tlv.reg_lt", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_reg_type,
+ 		{ "Registration Type","hip.tlv.reg_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_reg_failtype,
+ 		{ "Registration Failure Type","hip.tlv.reg_failtype", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+ 		{ &hf_hip_tlv_hmac,
+ 		{ "HMAC","hip.tlv.hmac", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_sig_alg,
+ 		{ "Signature Algorithm","hip.tlv.sig_alg", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_sig,
+ 		{ "Signature",          "hip.tlv.sig", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_id,
+ 		{ "ID",                 "hip.tlv.id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 		
+                 { &hf_hip_tlv_enc_reserved,
+ 		{ "Reserved",                 "hip.tlv.enc_reserved", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 
+                 { &hf_hip_tlv_enc_iv,
+ 		{ "IV",                 "hip.tlv.enc_iv", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 
+                 { &hf_hip_tlv_locator_traffic_type,
+ 		{ "Traffic Type",                 "hip.tlv.locator_traffic_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 
+                 { &hf_hip_tlv_locator_type,
+ 		{ "Locator Type",                 "hip.tlv.locator_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 
+                 { &hf_hip_tlv_locator_len,
+ 		{ "Locator Length",                 "hip.tlv.locator_len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ 
+                 { &hf_hip_tlv_locator_reserved,
+ 		{ "Reserved | P bit",                 "hip.tlv.locator_reserved", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 
+                 { &hf_hip_tlv_locator_lifetime,
+ 		{ "Locator Lifetime",                 "hip.tlv.locator_lifetime", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ 
+ 	};
+ 	static gint *ett[] = {
+ 		&ett_hip,
+ 		&ett_hip_controls,
+ 		&ett_hip_tlv,
+ 		&ett_hip_tlv_data,
+ 		&ett_hip_tlv_host_id_hdr,
+ 	};
+ 
+ 	proto_hip = proto_register_protocol("Host Identity Protocol",
+ 	    "HIP", "hip");
+ 
+ 	proto_register_field_array(proto_hip, hf, array_length(hf));
+ 	proto_register_subtree_array(ett, array_length(ett));
+ 
+ 	/* Register configuration preferences */
+         hip_module = prefs_register_protocol(proto_hip, NULL);
+         prefs_register_bool_preference(hip_module, "summary_in_tree",
+         "Show HIP summary in protocol tree",
+         "Whether the HIP summary line should be shown in the protocol tree",
+         &hip_summary_in_tree);
+ }
+ 
+ void
+ proto_reg_handoff_hip(void)
+ {
+ 	dissector_handle_t hip_handle;
+ 
+ 	hip_handle = create_dissector_handle(dissect_hip, proto_hip);
+ 	dissector_add("ip.proto", IP_PROTO_HIP, hip_handle);
+ 	data_handle = find_dissector("data");
+ }
+ 
+ char * hip_param(int n)
+ {
+     static char s[24];
+     
+     switch (n)
+     {
+ 	//case 0: /* sometimes extra padding */
+ 	//    return NULL;
+ 	//    break;
+ 	case PARAM_ESP_INFO:
+ 	    sprintf(s, "ESP INFO");
+ 	    break;
+ 	case PARAM_R1_COUNTER:
+ 	    sprintf(s, "R1 COUNTER");
+ 	    break;
+ 	case PARAM_LOCATOR:
+ 	    sprintf(s, "LOCATOR");
+ 	    break;
+ 	case PARAM_PUZZLE:
+ 	    sprintf(s, "PUZZLE");
+ 	    break;
+ 	case PARAM_SOLUTION:
+ 	    sprintf(s, "SOLUTION");
+ 	    break;
+ 	case PARAM_SEQ:
+ 	    sprintf(s, "SEQ");
+ 	    break;
+ 	case PARAM_ACK:
+ 	    sprintf(s, "ACK");
+ 	    break;
+ 	case PARAM_DIFFIE_HELLMAN:
+ 	    sprintf(s, "DIFFIE_HELLMAN");
+ 	    break;
+ 	case PARAM_HIP_TRANSFORM:
+ 	    sprintf(s, "HIP_TRANSFORM");
+ 	    break;
+ 	case PARAM_ENCRYPTED:
+ 	    sprintf(s, "ENCRYPTED");
+ 	    break;
+ 	case PARAM_HOST_ID:
+ 	    sprintf(s, "HOST_ID");
+ 	    break;
+ 	case PARAM_CERT:
+ 	    sprintf(s, "CERT");
+ 	    break;
+ 	case PARAM_NOTIFY:
+ 	    sprintf(s, "NOTIFY");
+ 	    break;
+ 	case PARAM_ECHO_REQUEST:
+ 	    sprintf(s, "ECHO_REQUEST");
+ 	    break;
+ 	case PARAM_ECHO_RESPONSE:
+ 	    sprintf(s, "ECHO_RESPONSE");
+ 	    break;
+ 	case PARAM_ESP_TRANSFORM:
+ 	    sprintf(s, "ESP_TRANSFORM");
+ 	    break;
+ 	case PARAM_HMAC:
+ 	    sprintf(s, "HMAC");
+ 	    break;
+ 	case PARAM_HMAC_2:
+ 	    sprintf(s, "HMAC_2");
+ 	    break;
+ 	case PARAM_HIP_SIGNATURE_2:
+ 	    sprintf(s, "HIP_SIGNATURE_2");
+ 	    break;
+ 	case PARAM_HIP_SIGNATURE:
+ 	    sprintf(s, "HIP_SIGNATURE");
+ 	    break;
+ 	case PARAM_ECHO_REQUEST_NOSIG:
+ 	    sprintf(s, "ECHO_REQUEST (No sig.)");
+ 	    break;
+ 	case PARAM_ECHO_RESPONSE_NOSIG:
+ 	    sprintf(s, "ECHO_RESPONSE (No sig.)");
+ 	    break;
+ 	default:
+ 	    sprintf(s, "?UNKNOWN?");
+ 	    break;
+     }
+ 
+     return s;
+ }
+ 
+ char *dh_group_id_label(int groupid)
+ {
+     static char s[26];
+     switch(groupid)
+     {
+ 	case 0:
+ 	    sprintf(s, "Reserved");
+ 	    break;
+ 	case 1:
+ 	    sprintf(s, "384-bit group");
+ 	    break;
+ 	case 2:
+ 	    sprintf(s, "OAKLEY well-known group 1");
+ 	    break;
+ 	case 3:
+ 	    sprintf(s, "1536-bit MODP group");
+ 	    break;
+ 	case 4:
+ 	    sprintf(s, "3072-bit MODP group");
+ 	    break;
+ 	case 5:
+ 	    sprintf(s, "6144-bit MODP group");
+ 	    break;
+ 	case 6:
+ 	    sprintf(s, "8192-bit MODP group");
+ 	    break;
+ 	default:
+ 	    sprintf(s, "UNKNOWN?");
+ 	    break;
+     }
+     return s;
+ 	
+ }
+ 	    
+ char *transform_id_label(int transform)
+ {
+     static char s[32];
+     switch (transform)
+     {
+ 	case 0:
+ 	    sprintf(s, "Reserved");
+ 	    break;
+ 	case 1:
+ 	    sprintf(s, "AES-CBC with HMAC-SHA1");
+ 	    break;
+ 	case 2:
+ 	    sprintf(s, "3DES-CBC with HMAC-SHA1");
+ 	    break;
+ 	case 3:
+ 	    sprintf(s, "3DES-CBC with HMAC-MD5");
+ 	    break;
+ 	case 4:
+ 	    sprintf(s, "BLOWFISH-CBC with HMAC-SHA1");
+ 	    break;
+ 	case 5:
+ 	    sprintf(s, "NULL with HMAC-SHA1");
+ 	    break;
+ 	case 6:
+ 	    sprintf(s, "NULL with HMAC-MD5");
+ 	    break;
+ 	default:
+ 	    sprintf(s, "UNKNOWN?");
+ 	    break;
+ 
+     }
+     return s;
+ }
+ 
+ char *sig_alg_label(int alg)
+ {
+     static char s[10];
+     switch (alg)
+     {
+ 	case 0:
+ 	    sprintf(s, "Reserved");
+ 	    break;
+ 	case HI_ALG_DSA:
+ 	    sprintf(s, "DSA");
+ 	    break;
+ 	case HI_ALG_RSA:
+ 	    sprintf(s, "RSA");
+ 	    break;
+ 	default:
+ 	    sprintf(s, "UNKNOWN?");
+ 	    break;
+ 
+     }
+     return s;
+ }
+ 
+ 	    
+ int dissect_hip_tlv(tvbuff_t *tvb, int offset, proto_item *ti, int type, int tlv_len)
+ {
+     proto_tree *t=NULL;
+     proto_item *ti_tlv;
+     guint8 data[512];
+     guint8 n, algorithm, reg_type;
+     guint16 trans, hi_len, di_len, di_type, e_len;
+     guint32 reserved, hi_hdr;
+     int newoffset, newlen, hi_t;
+     
+     switch (type)
+     {
+ 	case PARAM_ESP_INFO:
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_ei_res, tvb, offset+4, 2,
+ 				tvb_get_ntohs(tvb, offset+4));
+ 	    proto_tree_add_uint(t, hf_hip_tlv_ei_keyidx, tvb, offset+6, 2,
+ 				tvb_get_ntohs(tvb, offset+6));
+ 	    proto_tree_add_uint(t, hf_hip_tlv_ei_oldspi, tvb, offset+8, 4,
+ 				tvb_get_ntohl(tvb, offset+8));
+ 	    proto_tree_add_uint(t, hf_hip_tlv_ei_newspi, tvb, offset+12, 4,
+ 				tvb_get_ntohl(tvb, offset+12));
+ 	    break;
+ 	case PARAM_R1_COUNTER:
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_r1_res, tvb, offset+4, 4,
+ 				tvb_get_ntohl(tvb, offset+4));
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+8, 8);
+ 	    proto_tree_add_bytes(t, hf_hip_tlv_r1count, tvb, offset+8, 8, data);
+ 	    break;
+ 	case PARAM_LOCATOR:
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    tlv_len -= 4;
+ 	    newoffset = offset + 4;
+ 	    while (tlv_len > 0) {
+ 	    	proto_tree_add_uint(t, hf_hip_tlv_locator_traffic_type, tvb, 
+ 				newoffset, 1, tvb_get_guint8(tvb, newoffset));
+ 		newoffset++;
+ 	    	proto_tree_add_uint(t, hf_hip_tlv_locator_type, tvb, 
+ 				newoffset, 1, tvb_get_guint8(tvb, newoffset));
+ 		newoffset++;
+ 	    	proto_tree_add_uint(t, hf_hip_tlv_locator_len, tvb, 
+ 				newoffset, 1, tvb_get_guint8(tvb, newoffset));
+ 		newoffset++;
+ 		reserved = tvb_get_guint8(tvb, newoffset);
+ 	        proto_tree_add_uint_format(t, hf_hip_tlv_locator_reserved, tvb, 
+ 			newoffset, 1, reserved,	"Reserved: 0x%x %s", reserved,
+ 			(reserved >> 31) ? "(Preferred)" : "");
+ 		newoffset++;
+ 		proto_tree_add_uint(t, hf_hip_tlv_locator_lifetime, tvb,
+ 				newoffset, 4, tvb_get_ntohl(tvb, newoffset));
+ 		newoffset += 4;
+ 		proto_tree_add_text(t, tvb, newoffset, 16, "Address: %s",
+ 			ip6_to_str((const struct e_in6_addr*)
+ 				tvb_get_ptr(tvb, newoffset, 16)));
+ 		newoffset += 16;
+ 		tlv_len -= 32;
+             }
+ 	    break;
+ 	case PARAM_PUZZLE:
+ 	case PARAM_SOLUTION:
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_puzzle_k, tvb, offset+4, 1,
+ 				tvb_get_guint8(tvb, offset+4));
+ 	    proto_tree_add_uint(t, hf_hip_tlv_puzzle_life, tvb, offset+5, 1,
+ 				tvb_get_guint8(tvb, offset+5));
+ 	    proto_tree_add_uint(t, hf_hip_tlv_puzzle_o, tvb,offset+6, 2,
+ 			    tvb_get_ntohs(tvb, offset+6));
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+8, 8);
+ 	    proto_tree_add_bytes(t, hf_hip_tlv_puzzle_i, tvb,offset+8, 8, data);
+ 	    if (type == PARAM_SOLUTION) { /* solution also contains J */
+ 		tvb_memcpy(tvb, (guint8*)data, offset+16, 8);
+ 		proto_tree_add_bytes(t, hf_hip_tlv_puzzle_j, tvb, offset+16, 8,
+ 			data);
+ 	    }
+ 	    break;
+ 	case PARAM_SEQ: /* SEQ */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_seq_updid, tvb, offset+4, 4,
+ 				tvb_get_ntohl(tvb, offset+4));
+ 	    break;
+ 	case PARAM_ACK: /* ACK */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    newoffset = offset + 4;
+ 	    while (tlv_len > 0) {
+ 		    proto_tree_add_uint(t, hf_hip_tlv_ack_updid, tvb, newoffset, 				    4, tvb_get_ntohl(tvb, newoffset));
+ 		    newoffset += 4;
+ 		    tlv_len -= 4;
+ 	    }
+ 	    break;
+ 	case PARAM_DIFFIE_HELLMAN: /* DIFFIE_HELLMAN */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    n = tvb_get_guint8(tvb, offset+4);
+ 	    proto_tree_add_uint_format(t, hf_hip_tlv_dh_group_id, tvb, offset+4,
+ 			1, n, "%u (%s)", n, dh_group_id_label(n));
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+5, tlv_len-1);
+ 	    proto_tree_add_bytes(t, hf_hip_tlv_dh_pub, tvb, offset+5, tlv_len-1,
+ 				data);
+ 	    break;
+ 	case PARAM_ESP_TRANSFORM: /* ESP_TRANSFORM */
+ 	case PARAM_HIP_TRANSFORM: /* HIP_TRANSFORM */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    /* ESP transform may have E bit*/
+ 	    if (type == PARAM_ESP_TRANSFORM) {
+ 		proto_tree_add_uint(t, hf_hip_tlv_esp_reserved, tvb,
+ 			offset+4, 2, tvb_get_ntohs(tvb, offset+4));
+ 		newoffset = offset + 6;
+ 		tlv_len -= 2;
+ 	    } else {
+ 	    	newoffset = offset + 4;
+ 		/* check for NULL as only HIP transform */
+ 		if (tlv_len == 2)
+ 			hip_transform = tvb_get_ntohs(tvb, newoffset);
+ 		else
+ 			hip_transform = 0;
+ 	    }
+ 	    while (tlv_len > 0) {
+ 		trans = tvb_get_ntohs(tvb, newoffset);
+ 	        proto_tree_add_uint_format(t, hf_hip_tlv_trans_id, tvb, 
+ 			newoffset, 2, trans, "%u (%s)", trans,
+ 			transform_id_label(trans));
+ 		tlv_len -= 2; /* two bytes per transform id */
+ 		newoffset += 2;
+             }
+ 	    break;
+ 	case PARAM_ENCRYPTED: /* ENCRYPTED */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_enc_reserved, tvb, offset+4, 4,
+ 				tvb_get_ntohl(tvb, offset+4));
+ 	    if (hip_transform == 5) { /* null encryption, no IV */
+ 		offset += 8;
+ 		t = proto_item_add_subtree(t, ett_hip_tlv_data);
+ 	    } else { /* encrypted data */
+ 		tvb_memcpy(tvb, (guint8*)data, offset+8, 8);
+ 		proto_tree_add_bytes(t, hf_hip_tlv_enc_iv,tvb,offset+8,8,data);
+ 		proto_tree_add_text(t, tvb, offset+16, tlv_len-12, 
+ 			"Encrypted Data (%u bytes)", tlv_len-12);
+ 		break;
+ 	    }
+ 	case PARAM_HOST_ID: /* HOST_ID */
+ 	    if (type != PARAM_ENCRYPTED)
+ 	    	t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    /* hi_length, fqdn_length */
+ 	    hi_len = tvb_get_ntohs(tvb, offset+4);
+ 	    di_len = tvb_get_ntohs(tvb, offset+6);
+ 	    di_type = (di_len >> 12) & 0x000F;	/* get 4 bits for DI type */
+ 	    di_len = di_len & 0x0FFF;		/* 12 bits for DI length */
+ 	    proto_tree_add_uint(t, hf_hip_tlv_host_id_len, tvb, offset+4, 2,
+ 				hi_len);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_host_di_type, tvb, offset+6, 1,
+ 				di_type);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_host_di_len, tvb, offset+6, 2,
+ 				di_len);
+ 	    /* hi_hdr - first 4 bytes are 0200ff03 (RFC 2535)
+ 	     *   flags     2  octets
+ 	     *   protocol  1  octet
+ 	     *   algorithm 1  octet (DSA or RSA)
+ 	     */
+ 	    hi_hdr = tvb_get_ntohl(tvb, offset+8);
+ 	    ti_tlv = proto_tree_add_uint(t, hf_hip_tlv_host_id_hdr, tvb, offset+8, 4, hi_hdr);
+ 	    if (ti_tlv) {
+ 		ti_tlv = proto_item_add_subtree(ti_tlv,ett_hip_tlv_host_id_hdr);
+ 		proto_tree_add_uint(ti_tlv, hf_hip_tlv_host_id_hdr_flags, tvb, offset+8,2, hi_hdr);
+ 		proto_tree_add_uint(ti_tlv, hf_hip_tlv_host_id_hdr_proto, tvb, offset+10,1, hi_hdr);
+ 		proto_tree_add_uint(ti_tlv, hf_hip_tlv_host_id_hdr_alg, tvb, offset+11,1, hi_hdr);
+ 	    }
+ 	    algorithm = tvb_get_guint8(tvb, offset+11);
+ 	    switch (algorithm) {
+ 	    case HI_ALG_DSA:
+ 	    /* DSA
+ 	     *   T         1  octet
+ 	     *   Q         20  octets
+ 	     *   P         64 + T*8  octets
+ 	     *   G         64 + T*8  octets
+ 	     *   Y         64 + T*8  octets
+ 	     */
+ 	    	/* hi_t */
+ 		proto_tree_add_uint(t, hf_hip_tlv_host_id_t, tvb, offset+12, 1,
+ 				    tvb_get_guint8(tvb, offset+12));
+ 		hi_t = tvb_get_guint8(tvb, offset+12);
+ 		tvb_memcpy(tvb, (guint8*)data, offset+13, 20);
+ 		proto_tree_add_bytes(t, hf_hip_tlv_host_id_q, tvb, offset+13, 
+ 				     20, data);
+ 		newoffset = offset + 33;
+ 		if (hi_t > 56) /* max 4096 bits */
+ 		    break;
+ 		newlen = 64 + (hi_t * 8);
+ 		tvb_memcpy(tvb, (guint8*)data, newoffset, newlen);
+ 		proto_tree_add_bytes(t, hf_hip_tlv_host_id_p, tvb, newoffset,
+ 				newlen, data);
+ 		newoffset += newlen;
+ 		tvb_memcpy(tvb, (guint8*)data, newoffset, newlen);
+ 		proto_tree_add_bytes(t, hf_hip_tlv_host_id_g, tvb, newoffset,
+ 				newlen, data);
+ 		newoffset += newlen;
+ 		tvb_memcpy(tvb, (guint8*)data, newoffset, newlen);
+ 		proto_tree_add_bytes(t, hf_hip_tlv_host_id_y, tvb, newoffset,
+ 				newlen, data);
+ 		break;
+ 	    case HI_ALG_RSA:
+ 	    /* RSA
+ 	     * e_len	1 or 3 octets
+ 	     * e 	specified by e_len
+ 	     * n	variable length public modulus
+ 	     */
+ 		e_len = tvb_get_guint8(tvb, offset+12);
+ 		newoffset = offset+13;
+ 		hi_len -= 5; /* subtract RDATA + e_len */
+ 		if (e_len == 0) { /* e_len is 0 followed by 16-bit value */
+ 			e_len = tvb_get_ntohs(tvb, offset+13);
+ 			newoffset += 2;
+ 			hi_len -= 2;
+ 		}
+ 		if (e_len > 512) { /* per, RFC 3110 < 4096 bits */
+ 			proto_tree_add_text(t, tvb, offset+13, 2,
+ 					"<< e_len too large >>");
+ 			break;
+ 		}
+ 	    	proto_tree_add_uint(t, hf_hip_tlv_host_id_e_len, tvb, offset+12,
+ 				    (e_len > 255) ? 3:1, e_len);
+ 		proto_tree_add_bytes(t, hf_hip_tlv_host_id_e, tvb, newoffset,
+ 				     e_len, tvb_get_ptr(tvb, newoffset, e_len));
+ 		newoffset += e_len;
+ 		hi_len -= e_len;
+ 		if ((hi_len > 512) || (hi_len < 0)) {
+ 			proto_tree_add_text(t, tvb, newoffset, 1,
+ 					"<< Invalid HI length >>");
+ 			break;
+ 		}
+ 		/* RSA public modulus n */
+ 	    	proto_tree_add_bytes(t, hf_hip_tlv_host_id_n, tvb, newoffset,
+ 				     hi_len, tvb_get_ptr(tvb,newoffset,hi_len));
+ 	    break;
+ 	    default:
+ 	        proto_tree_add_text(t, tvb, offset+11, 1,
+ 				"Unknown algorithm type (%d).\n", algorithm);
+ 
+ 	        break;
+ 	    }
+ 	    /* FQDN */
+ 	    if (di_type == 0)
+ 		break;
+ 	    if (di_len > sizeof(data))
+ 		di_len = sizeof(data) - 1;
+ 	    memset(data,0,sizeof(data)); /* this null-terminates the string */
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+16+hi_len, di_len);
+ 	    if (di_type == 1) {
+ 	    	proto_tree_add_text(t, tvb, offset+16+hi_len, di_len,
+ 					"FQDN: %s", data);
+ 	    } else if (di_type == 2) {
+ 	    	proto_tree_add_text(t, tvb, offset+16+hi_len, di_len,
+ 					"NAI: %s", data);
+ 	    }
+ 	    break;
+ 	case PARAM_CERT: /* CERT */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_cert_count, tvb, offset+4, 1,
+ 				tvb_get_guint8(tvb, offset+4));
+ 	    proto_tree_add_uint(t, hf_hip_tlv_cert_id, tvb, offset+5, 1,
+ 				tvb_get_guint8(tvb, offset+5));
+ 	    proto_tree_add_uint(t, hf_hip_tlv_cert_type, tvb, offset+6, 1,
+ 				tvb_get_guint8(tvb, offset+6));
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+7, tlv_len-3);
+ 	    proto_tree_add_bytes(t, hf_hip_tlv_certificate, tvb, offset+7,
+ 				tlv_len-3, data);
+ 	    break;
+ 	case PARAM_NOTIFY: /* NOTIFY */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    proto_tree_add_uint(t, hf_hip_tlv_notify_res, tvb, offset+4, 2,
+ 				tvb_get_ntohs(tvb, offset+4));
+ 	    proto_tree_add_uint(t, hf_hip_tlv_notify_type, tvb, offset+6, 2,
+ 				tvb_get_ntohs(tvb, offset+6));
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+8, tlv_len-4);
+ 	    proto_tree_add_bytes(t, hf_hip_tlv_notify_data, tvb, offset+8,
+ 				tlv_len-4, data);
+ 	    
+ 	    break;
+ 	case PARAM_ECHO_REQUEST: /* ECHO REQUEST */
+ 	case PARAM_ECHO_RESPONSE: /* ECHO RESPONSE */
+ 	case PARAM_ECHO_REQUEST_NOSIG: /* ECHO REQUEST */
+ 	case PARAM_ECHO_RESPONSE_NOSIG: /* ECHO RESPONSE */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+4, tlv_len);
+ 	    proto_tree_add_bytes(t, hf_hip_tlv_opaque_data, tvb, offset+4,
+ 				tlv_len, data);
+ 	    break;
+ 	case PARAM_REG_INFO:
+ 	case PARAM_REG_REQUEST:
+ 	case PARAM_REG_RESPONSE:
+ 	case PARAM_REG_FAILED:
+ 	    /* min lt, max lt | lifetime | failuretype */
+ 	    if (type == PARAM_REG_INFO) { /* min lt, max lt */
+ 		proto_tree_add_uint(t, hf_hip_tlv_reg_ltmin, tvb, offset+4,
+ 				1, tvb_get_guint8(tvb, offset+4));
+ 		proto_tree_add_uint(t, hf_hip_tlv_reg_ltmax, tvb, offset+5,
+ 				1, tvb_get_guint8(tvb, offset+5));
+ 		newoffset = 6;
+ 	    } else if (type == PARAM_REG_FAILED) { /* failure type */
+ 		proto_tree_add_uint(t, hf_hip_tlv_reg_failtype, tvb, offset+4,
+ 				1, tvb_get_guint8(tvb, offset+4));
+ 		newoffset = 5;
+ 	    } else { /* lifetime */
+ 		proto_tree_add_uint(t, hf_hip_tlv_reg_lt, tvb, offset+4,
+ 				1, tvb_get_guint8(tvb, offset+4));
+ 		newoffset = 5;
+ 	    }
+ 	    /* reg type 1 ... n, padding */
+ 	    while (tlv_len > 0) {
+ 		reg_type = tvb_get_guint8(tvb, newoffset);
+ 		proto_tree_add_uint(t, hf_hip_tlv_reg_type, tvb, newoffset, 1, 
+ 				reg_type);
+ 		tlv_len--; /* one byte per registration type */
+ 		newoffset++;
+ 	    }
+ 	    break;
+ 	case PARAM_RVS_HMAC: /* RVS HMAC */
+ 	case PARAM_HMAC: /* HMAC */
+ 	case PARAM_HMAC_2: /* HMAC */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+4, tlv_len);
+ 	    proto_tree_add_bytes(t, hf_hip_tlv_hmac, tvb, offset+4,
+ 				tlv_len,data);
+ 	    break;
+ 	case PARAM_HIP_SIGNATURE_2: /* HIP_SIGNATURE_2 */
+ 	case PARAM_HIP_SIGNATURE: /* HIP_SIGNATURE */
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    n = tvb_get_guint8(tvb, offset+4);
+ 	    proto_tree_add_uint_format(t, hf_hip_tlv_sig_alg, tvb, offset+4, 1,
+ 				n, "%u (%s)", n, sig_alg_label(n));
+ 	    tvb_memcpy(tvb, (guint8*)data, offset+5, tlv_len-1);
+ 	    proto_tree_add_bytes(t, hf_hip_tlv_sig, tvb, offset+5, tlv_len-1,
+ 				data);
+ 	    break;
+ 	case PARAM_FROM:
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    proto_tree_add_text(t, tvb, offset+4, 16, "Address: %s",
+ 			ip6_to_str((const struct e_in6_addr*)
+ 				tvb_get_ptr(tvb, offset+4, 16)));
+ 	    break;
+ 	case PARAM_VIA_RVS:
+ 	    t = proto_item_add_subtree(ti, ett_hip_tlv_data);
+ 	    newoffset = offset + 4;
+ 	    while (tlv_len > 0) {
+ 		proto_tree_add_text(t, tvb, newoffset, 16, "RVS Address: %s",
+ 			ip6_to_str((const struct e_in6_addr*)
+ 				tvb_get_ptr(tvb, newoffset, 16)));
+ 		tlv_len -= 16;
+ 		newoffset += 16;
+             }
+ 	    break;
+ 	default:
+ 	    break;
+     }
+     return (0);
+ }
+