done:
[obnox/wireshark/wip.git] / epan / dissectors / packet-isakmp.c
1 /* packet-isakmp.c
2  * Routines for the Internet Security Association and Key Management Protocol
3  * (ISAKMP) (RFC 2408) and the Internet IP Security Domain of Interpretation
4  * for ISAKMP (RFC 2407)
5  * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
6  *
7  * Added routines for the Internet Key Exchange (IKEv2) Protocol
8  * (draft-ietf-ipsec-ikev2-17.txt)
9  * Shoichi Sakane <sakane@tanu.org>
10  *
11  * Added routines for RFC3947 Negotiation of NAT-Traversal in the IKE
12  *   ronnie sahlberg
13  *
14  * $Id$
15  *
16  * Ethereal - Network traffic analyzer
17  * By Gerald Combs <gerald@ethereal.com>
18  * Copyright 1998 Gerald Combs
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <stdio.h>
40 #include <string.h>
41
42 #include <glib.h>
43
44 #include <epan/packet.h>
45 #include <epan/ipproto.h>
46 #include <epan/dissectors/packet-x509if.h>
47 #include <epan/dissectors/packet-isakmp.h>
48
49 #define isakmp_min(a, b)  ((a<b) ? a : b)
50
51 #define ARLEN(a) (sizeof(a)/sizeof(a[0]))
52
53 static int proto_isakmp = -1;
54 static int hf_ike_certificate_authority = -1;
55 static int hf_ike_v2_certificate_authority = -1;
56 static int hf_ike_nat_keepalive = -1;
57
58 static gint ett_isakmp = -1;
59 static gint ett_isakmp_flags = -1;
60 static gint ett_isakmp_payload = -1;
61
62 /* IKE port number assigned by IANA */
63 #define UDP_PORT_ISAKMP 500
64 #define TCP_PORT_ISAKMP 500
65
66 /*
67  * Identifier Type 
68  *   RFC2407 for IKEv1
69  *   draft-ietf-ipsec-ikev2-17.txt for IKEv2
70  */
71 #define IKE_ID_IPV4_ADDR                1
72 #define IKE_ID_FQDN                     2
73 #define IKE_ID_USER_FQDN                3
74 #define IKE_ID_IPV4_ADDR_SUBNET         4
75 #define IKE_ID_IPV6_ADDR                5
76 #define IKE_ID_IPV6_ADDR_SUBNET         6
77 #define IKE_ID_IPV4_ADDR_RANGE          7
78 #define IKE_ID_IPV6_ADDR_RANGE          8
79 #define IKE_ID_DER_ASN1_DN              9
80 #define IKE_ID_DER_ASN1_GN              10
81 #define IKE_ID_KEY_ID                   11
82
83 /*
84  * Traffic Selector Type
85  *   Not in use for IKEv1
86  */
87 #define IKEV2_TS_IPV4_ADDR_RANGE        7
88 #define IKEV2_TS_IPV6_ADDR_RANGE        8
89
90 static const value_string vs_proto[] = {
91   { 0,  "RESERVED" },
92   { 1,  "ISAKMP" },
93   { 2,  "IPSEC_AH" },
94   { 3,  "IPSEC_ESP" },
95   { 4,  "IPCOMP" },
96   { 0,  NULL },
97 };
98
99 struct isakmp_hdr {
100   guint8        icookie[8];
101   guint8        rcookie[8];
102   guint8        next_payload;
103   guint8        version;
104   guint8        exch_type;
105   guint8        flags;
106 #define E_FLAG          0x01
107 #define C_FLAG          0x02
108 #define A_FLAG          0x04
109 #define I_FLAG          0x08
110 #define V_FLAG          0x10
111 #define R_FLAG          0x20
112   guint32       message_id;
113   guint32       length;
114 };
115
116 static proto_tree *dissect_payload_header(tvbuff_t *, int, int, int, guint8,
117     guint8 *, guint16 *, proto_tree *);
118
119 static void dissect_sa(tvbuff_t *, int, int, proto_tree *,
120     packet_info *, int, int);
121 static void dissect_proposal(tvbuff_t *, int, int, proto_tree *,
122     packet_info *, int, int);
123 static void dissect_transform(tvbuff_t *, int, int, proto_tree *,
124     packet_info *, int, int);
125 static void dissect_transform2(tvbuff_t *, int, int, proto_tree *,
126     packet_info *, int, int);
127 static void dissect_key_exch(tvbuff_t *, int, int, proto_tree *,
128     packet_info *, int, int);
129 static void dissect_id(tvbuff_t *, int, int, proto_tree *,
130     packet_info *, int, int);
131 static void dissect_cert(tvbuff_t *, int, int, proto_tree *,
132     packet_info *, int, int);
133 static void dissect_certreq_v1(tvbuff_t *, int, int, proto_tree *,
134     packet_info *, int, int);
135 static void dissect_certreq_v2(tvbuff_t *, int, int, proto_tree *,
136     packet_info *, int, int);
137 static void dissect_hash(tvbuff_t *, int, int, proto_tree *,
138     packet_info *, int, int);
139 static void dissect_auth(tvbuff_t *, int, int, proto_tree *,
140     packet_info *, int, int);
141 static void dissect_sig(tvbuff_t *, int, int, proto_tree *,
142     packet_info *, int, int);
143 static void dissect_nonce(tvbuff_t *, int, int, proto_tree *,
144     packet_info *, int, int);
145 static void dissect_notif(tvbuff_t *, int, int, proto_tree *,
146     packet_info *, int, int);
147 static void dissect_delete(tvbuff_t *, int, int, proto_tree *,
148     packet_info *, int, int);
149 static void dissect_vid(tvbuff_t *, int, int, proto_tree *,
150     packet_info *, int, int);
151 static void dissect_config(tvbuff_t *, int, int, proto_tree *,
152     packet_info *, int, int);
153 static void dissect_nat_discovery(tvbuff_t *, int, int, proto_tree *,
154     packet_info *, int, int);
155 static void dissect_nat_original_address(tvbuff_t *, int, int, proto_tree *,
156     packet_info *, int, int);
157 static void dissect_ts(tvbuff_t *, int, int, proto_tree *,
158     packet_info *, int, int);
159 static void dissect_enc(tvbuff_t *, int, int, proto_tree *,
160     packet_info *, int, int);
161 static void dissect_eap(tvbuff_t *, int, int, proto_tree *,
162     packet_info *, int, int);
163
164 static void
165 dissect_payloads(tvbuff_t *tvb, proto_tree *tree, int isakmp_version,
166                  guint8 initial_payload, int offset, int length,
167                  packet_info *pinfo);
168
169
170 static const char *payloadtype2str(int, guint8);
171 static const char *exchtype2str(int, guint8);
172 static const char *doitype2str(guint32);
173 static const char *msgtype2str(int, guint16);
174 static const char *situation2str(guint32);
175 static const char *v1_attrval2str(int, guint16, guint32);
176 static const char *v2_attrval2str(guint16, guint32);
177 static const char *cfgtype2str(int, guint8);
178 static const char *cfgattr2str(int, guint16);
179 static const char *id2str(int, guint8);
180 static const char *v2_tstype2str(guint8);
181 static const char *v2_auth2str(guint8);
182 static const char *certtype2str(int, guint8);
183
184 static gboolean get_num(tvbuff_t *, int, guint16, guint32 *);
185
186 #define LOAD_TYPE_NONE          0       /* payload type for None */
187 #define LOAD_TYPE_PROPOSAL      2       /* payload type for Proposal */
188 #define LOAD_TYPE_TRANSFORM     3       /* payload type for Transform */
189
190 struct payload_func {
191   guint8 type;
192   const char *  str;
193   void (*func)(tvbuff_t *, int, int, proto_tree *, packet_info *, int, int);
194 };
195
196 static struct payload_func v1_plfunc[] = {
197   {  0, "NONE",                 NULL              },
198   {  1, "Security Association", dissect_sa        },
199   {  2, "Proposal",             dissect_proposal  },
200   {  3, "Transform",            dissect_transform },
201   {  4, "Key Exchange",         dissect_key_exch  },
202   {  5, "Identification",       dissect_id        },
203   {  6, "Certificate",          dissect_cert      },
204   {  7, "Certificate Request",  dissect_certreq_v1},
205   {  8, "Hash",                 dissect_hash      },
206   {  9, "Signature",            dissect_sig       },
207   { 10, "Nonce",                dissect_nonce     },
208   { 11, "Notification",         dissect_notif     },
209   { 12, "Delete",               dissect_delete    },
210   { 13, "Vendor ID",            dissect_vid       },
211   { 14, "Attrib",               dissect_config    },
212   { 15, "NAT-Discovery",        dissect_nat_discovery }, /* draft-ietf-ipsec-nat-t-ike-04 */
213   { 16, "NAT-Original Address", dissect_nat_original_address }, /* draft-ietf-ipsec-nat-t-ike */
214   { 20, "NAT-D (RFC 3947)",     dissect_nat_discovery },
215   { 21, "NAT-OA (RFC 3947)",    dissect_nat_original_address },
216   { 130, "NAT-D (draft-ietf-ipsec-nat-t-ike-01 to 03)",         dissect_nat_discovery },
217   { 131, "NAT-OA (draft-ietf-ipsec-nat-t-ike-01 to 04)",        dissect_nat_original_address },
218 };
219
220 static struct payload_func v2_plfunc[] = {
221   {  2, "Proposal",             dissect_proposal  },
222   {  3, "Transform",            dissect_transform2 },
223   { 33, "Security Association", dissect_sa        },
224   { 34, "Key Exchange",         dissect_key_exch  },
225   { 35, "Identification - I",   dissect_id        },
226   { 36, "Identification - R",   dissect_id        },
227   { 37, "Certificate",          dissect_cert      },
228   { 38, "Certificate Request",  dissect_certreq_v2},
229   { 39, "Authentication",       dissect_auth      },
230   { 40, "Nonce",                dissect_nonce     },
231   { 41, "Notification",         dissect_notif     },
232   { 42, "Delete",               dissect_delete    },
233   { 43, "Vendor ID",            dissect_vid       },
234   { 44, "Traffic Selector - I", dissect_ts       },
235   { 45, "Traffic Selector - R", dissect_ts       },
236   { 46, "Encrypted",            dissect_enc       },
237   { 47, "Configuration",        dissect_config    },
238   { 48, "Extensible Authentication",    dissect_eap       },
239 };
240
241 static struct payload_func * getpayload_func(guint8, int);
242
243 #define VID_LEN 16
244 #define VID_MS_LEN 20
245 static const guint8 VID_MS_W2K_WXP[VID_MS_LEN] = {0x1E, 0x2B, 0x51, 0x69, 0x5, 0x99, 0x1C, 0x7D, 0x7C, 0x96, 0xFC, 0xBF, 0xB5, 0x87, 0xE4, 0x61, 0x0, 0x0, 0x0, 0x2}; /* according to http://www.microsoft.com/technet/treeview/default.asp?url=/technet/columns/cableguy/cg0602.asp */
246
247 #define VID_CP_LEN 20
248 static const guint8 VID_CP[VID_CP_LEN] = {0xF4, 0xED, 0x19, 0xE0, 0xC1, 0x14, 0xEB, 0x51, 0x6F, 0xAA, 0xAC, 0x0E, 0xE3, 0x7D, 0xAF, 0x28, 0x7, 0xB4, 0x38, 0x1F};
249
250 static const guint8 VID_CYBERGUARD[VID_LEN] = {0x9A, 0xA1, 0xF3, 0xB4, 0x34, 0x72, 0xA4, 0x5D, 0x5F, 0x50, 0x6A, 0xEB, 0x26, 0xC, 0xF2, 0x14};
251
252 static const guint8 VID_draft_ietf_ipsec_nat_t_ike_03[VID_LEN] = {0x7D, 0x94, 0x19, 0xA6, 0x53, 0x10, 0xCA, 0x6F, 0x2C, 0x17, 0x9D, 0x92, 0x15, 0x52, 0x9d, 0x56}; /* according to http://www.ietf.org/internet-drafts/draft-ietf-ipsec-nat-t-ike-03.txt */
253
254 static const guint8 VID_rfc3947[VID_LEN] = {0x4a, 0x13, 0x1c, 0x81, 0x07, 0x03, 0x58, 0x45, 0x5c, 0x57, 0x28, 0xf2, 0x0e, 0x95, 0x45, 0x2f}; /* RFC 3947 Negotiation of NAT-Traversal in the IKE*/
255
256 static const guint8 VID_SSH_IPSEC_EXPRESS_1_1_0[VID_LEN] = {0xfB, 0xF4, 0x76, 0x14, 0x98, 0x40, 0x31, 0xFA, 0x8E, 0x3B, 0xB6, 0x19, 0x80, 0x89, 0xB2, 0x23}; /* Ssh Communications Security IPSEC Express version 1.1.0 */
257
258 static const guint8 VID_SSH_IPSEC_EXPRESS_1_1_1[VID_LEN] = {0x19, 0x52, 0xDC, 0x91, 0xAC, 0x20, 0xF6, 0x46, 0xFB, 0x01, 0xCF, 0x42, 0xA3, 0x3A, 0xEE, 0x30}; /* Ssh Communications Security IPSEC Express version 1.1.1 */
259    
260 static const guint8 VID_SSH_IPSEC_EXPRESS_1_1_2[VID_LEN] = {0xE8, 0xBF, 0xFA, 0x64, 0x3E, 0x5C, 0x8F, 0x2C, 0xD1, 0x0F, 0xDA, 0x73, 0x70, 0xB6, 0xEB, 0xE5}; /* Ssh Communications Security IPSEC Express version 1.1.2 */
261
262 static const guint8 VID_SSH_IPSEC_EXPRESS_1_2_1[VID_LEN] = {0xC1, 0x11, 0x1B, 0x2D, 0xEE, 0x8C, 0xBC, 0x3D, 0x62, 0x05, 0x73, 0xEC, 0x57, 0xAA, 0xB9, 0xCB}; /* Ssh Communications Security IPSEC Express version 1.2.1 */
263
264 static const guint8 VID_SSH_IPSEC_EXPRESS_1_2_2[VID_LEN] = {0x09, 0xEC, 0x27, 0xBF, 0xBC, 0x09, 0xC7, 0x58, 0x23, 0xCF, 0xEC, 0xBF, 0xFE, 0x56, 0x5A, 0x2E}; /* Ssh Communications Security IPSEC Express version 1.2.2 */
265    
266 static const guint8 VID_SSH_IPSEC_EXPRESS_2_0_0[VID_LEN] = {0x7F, 0x21, 0xA5, 0x96, 0xE4, 0xE3, 0x18, 0xF0, 0xB2, 0xF4, 0x94, 0x4C, 0x23, 0x84, 0xCB, 0x84};  /* SSH Communications Security IPSEC Express version 2.0.0 */
267    
268 static const guint8 VID_SSH_IPSEC_EXPRESS_2_1_0[VID_LEN] = {0x28, 0x36, 0xD1, 0xFD, 0x28, 0x07, 0xBC, 0x9E, 0x5A, 0xE3, 0x07, 0x86, 0x32, 0x04, 0x51, 0xEC}; /* SSH Communications Security IPSEC Express version 2.1.0 */
269    
270 static const guint8 VID_SSH_IPSEC_EXPRESS_2_1_1[VID_LEN] = {0xA6, 0x8D, 0xE7, 0x56, 0xA9, 0xC5, 0x22, 0x9B, 0xAE, 0x66, 0x49, 0x80, 0x40, 0x95, 0x1A, 0xD5}; /* SSH Communications Security IPSEC Express version 2.1.1 */
271
272 static const guint8 VID_SSH_IPSEC_EXPRESS_2_1_2[VID_LEN] = {0x3F, 0x23, 0x72, 0x86, 0x7E, 0x23, 0x7C, 0x1C, 0xD8, 0x25, 0x0A, 0x75, 0x55, 0x9C, 0xAE, 0x20}; /* SSH Communications Security IPSEC Express version 2.1.2 */
273
274 static const guint8 VID_SSH_IPSEC_EXPRESS_3_0_0[VID_LEN] = {0x0E, 0x58, 0xD5, 0x77, 0x4D, 0xF6, 0x02, 0x00, 0x7D, 0x0B, 0x02, 0x44, 0x36, 0x60, 0xF7, 0xEB}; /* SSH Communications Security IPSEC Express version 3.0.0 */
275
276 static const guint8 VID_SSH_IPSEC_EXPRESS_3_0_1[VID_LEN] = {0xF5, 0xCE, 0x31, 0xEB, 0xC2, 0x10, 0xF4, 0x43, 0x50, 0xCF, 0x71, 0x26, 0x5B, 0x57, 0x38, 0x0F}; /* SSH Communications Security IPSEC Express version 3.0.1 */
277
278 static const guint8 VID_SSH_IPSEC_EXPRESS_4_0_0[VID_LEN] = {0xF6, 0x42, 0x60, 0xAF, 0x2E, 0x27, 0x42, 0xDA, 0xDD, 0xD5, 0x69, 0x87, 0x06, 0x8A, 0x99, 0xA0}; /* SSH Communications Security IPSEC Express version 4.0.0 */
279
280 static const guint8 VID_SSH_IPSEC_EXPRESS_4_0_1[VID_LEN] = {0x7A, 0x54, 0xD3, 0xBD, 0xB3, 0xB1, 0xE6, 0xD9, 0x23, 0x89, 0x20, 0x64, 0xBE, 0x2D, 0x98, 0x1C}; /* SSH Communications Security IPSEC Express version 4.0.1 */
281
282 static const guint8 VID_SSH_IPSEC_EXPRESS_4_1_0[VID_LEN] = {0x9A, 0xA1, 0xF3, 0xB4, 0x34, 0x72, 0xA4, 0x5D, 0x5F, 0x50, 0x6A, 0xEB, 0x26, 0x0C, 0xF2, 0x14}; /* SSH Communications Security IPSEC Express version 4.1.0 */
283
284 static const guint8 VID_SSH_IPSEC_EXPRESS_4_1_1[VID_LEN] = {0x89, 0xF7, 0xB7, 0x60, 0xD8, 0x6B, 0x01, 0x2A, 0xCF, 0x26, 0x33, 0x82, 0x39, 0x4D, 0x96, 0x2F}; /* SSH Communications Security IPSEC Express version 4.1.1 */
285
286 static const guint8 VID_SSH_IPSEC_EXPRESS_5_0[VID_LEN] = {0xB0, 0x37, 0xA2, 0x1A, 0xCE, 0xCC, 0xB5, 0x57, 0x0F, 0x60, 0x25, 0x46, 0xF9, 0x7B, 0xDE, 0x8C}; /* SSH Communications Security IPSEC Express version 5.0 */
287
288 static const guint8 VID_SSH_IPSEC_EXPRESS_5_0_0[VID_LEN] = {0x2B, 0x2D, 0xAD, 0x97, 0xC4, 0xD1, 0x40, 0x93, 0x00, 0x53, 0x28, 0x7F, 0x99, 0x68, 0x50, 0xB0}; /* SSH Communications Security IPSEC Express version 5.0.0 */
289
290 static const guint8 VID_SSH_IPSEC_EXPRESS_5_1_0[VID_LEN] = {0x45, 0xE1, 0x7F, 0x3A, 0xBE, 0x93, 0x94, 0x4C, 0xB2, 0x02, 0x91, 0x0C, 0x59, 0xEF, 0x80, 0x6B}; /* SSH Communications Security IPSEC Express version 5.1.0 */
291
292 static const guint8 VID_SSH_IPSEC_EXPRESS_5_1_1[VID_LEN] = {0x59, 0x25, 0x85, 0x9F, 0x73, 0x77, 0xED, 0x78, 0x16, 0xD2, 0xFB, 0x81, 0xC0, 0x1F, 0xA5, 0x51}; /* SSH Communications Security IPSEC Express version 5.1.1 */
293
294 static const guint8 VID_SSH_SENTINEL[VID_LEN] = {0x05, 0x41, 0x82, 0xA0, 0x7C, 0x7A, 0xE2, 0x06, 0xF9, 0xD2, 0xCF, 0x9D, 0x24, 0x32, 0xC4, 0x82}; /* SSH Sentinel */
295
296 static const guint8 VID_SSH_SENTINEL_1_1[VID_LEN] = {0xB9, 0x16, 0x23, 0xE6, 0x93, 0xCA, 0x18, 0xA5, 0x4C, 0x6A, 0x27, 0x78, 0x55, 0x23, 0x05, 0xE8}; /* SSH Sentinel 1.1 */
297
298 static const guint8 VID_SSH_SENTINEL_1_2[VID_LEN] = {0x54, 0x30, 0x88, 0x8D, 0xE0, 0x1A, 0x31, 0xA6, 0xFA, 0x8F, 0x60, 0x22, 0x4E, 0x44, 0x99, 0x58}; /* SSH Sentinel 1.2 */
299
300 static const guint8 VID_SSH_SENTINEL_1_3[VID_LEN] = {0x7E, 0xE5, 0xCB, 0x85, 0xF7, 0x1C, 0xE2, 0x59, 0xC9, 0x4A, 0x5C, 0x73, 0x1E, 0xE4, 0xE7, 0x52}; /* SSH Sentinel 1.3 */
301
302 static const guint8 VID_SSH_QUICKSEC_0_9_0[VID_LEN] = {0x37, 0xEB, 0xA0, 0xC4, 0x13, 0x61, 0x84, 0xE7, 0xDA, 0xF8, 0x56, 0x2A, 0x77, 0x06, 0x0B, 0x4A}; /* SSH Communications Security QuickSec 0.9.0 */
303
304 static const guint8 VID_SSH_QUICKSEC_1_1_0[VID_LEN] = {0x5D, 0x72, 0x92, 0x5E, 0x55, 0x94, 0x8A, 0x96, 0x61, 0xA7, 0xFC, 0x48, 0xFD, 0xEC, 0x7F, 0xF9}; /* SSH Communications Security QuickSec 1.1.0 */
305
306 static const guint8 VID_SSH_QUICKSEC_1_1_1[VID_LEN] = {0x77, 0x7F, 0xBF, 0x4C, 0x5A, 0xF6, 0xD1, 0xCD, 0xD4, 0xB8, 0x95, 0xA0, 0x5B, 0xF8, 0x25, 0x94}; /* SSH Communications Security QuickSec 1.1.1 */
307
308 static const guint8 VID_SSH_QUICKSEC_1_1_2[VID_LEN] = {0x2C, 0xDF, 0x08, 0xE7, 0x12, 0xED, 0xE8, 0xA5, 0x97, 0x87, 0x61, 0x26, 0x7C, 0xD1, 0x9B, 0x91}; /* SSH Communications Security QuickSec 1.1.2 */
309
310 static const guint8 VID_SSH_QUICKSEC_1_1_3[VID_LEN] = {0x59, 0xE4, 0x54, 0xA8, 0xC2, 0xCF, 0x02, 0xA3, 0x49, 0x59, 0x12, 0x1F, 0x18, 0x90, 0xBC, 0x87}; /* SSH Communications Security QuickSec 1.1.3 */
311
312 static const guint8 VID_draft_huttunen_ipsec_esp_in_udp_01[VID_LEN] = {0x50, 0x76, 0x0F, 0x62, 0x4C, 0x63, 0xE5, 0xC5, 0x3E, 0xEA, 0x38, 0x6C, 0x68, 0x5C, 0xA0, 0x83}; /* draft-huttunen-ipsec-esp-in-udp-01.txt */
313
314 static const guint8 VID_draft_stenberg_ipsec_nat_traversal_01[VID_LEN] = {0x27, 0xBA, 0xB5, 0xDC, 0x01, 0xEA, 0x07, 0x60, 0xEA, 0x4E, 0x31, 0x90, 0xAC, 0x27, 0xC0, 0xD0}; /* draft-stenberg-ipsec-nat-traversal-01 */
315
316 static const guint8 VID_draft_stenberg_ipsec_nat_traversal_02[VID_LEN]= {0x61, 0x05, 0xC4, 0x22, 0xE7, 0x68, 0x47, 0xE4, 0x3F, 0x96, 0x84, 0x80, 0x12, 0x92, 0xAE, 0xCD}; /* draft-stenberg-ipsec-nat-traversal-02 */
317
318 static const guint8 VID_draft_ietf_ipsec_nat_t_ike_00[VID_LEN]= {0x44, 0x85, 0x15, 0x2D, 0x18, 0xB6, 0xBB, 0xCD, 0x0B, 0xE8, 0xA8, 0x46, 0x95, 0x79, 0xDD, 0xCC}; /* draft-ietf-ipsec-nat-t-ike-00 */
319
320 static const guint8 VID_draft_ietf_ipsec_nat_t_ike_02a[VID_LEN]= {0xCD, 0x60, 0x46, 0x43, 0x35, 0xDF, 0x21, 0xF8, 0x7C, 0xFD, 0xB2, 0xFC, 0x68, 0xB6, 0xA4, 0x48}; /* draft-ietf-ipsec-nat-t-ike-02 */
321
322 static const guint8 VID_draft_ietf_ipsec_nat_t_ike_02b[VID_LEN]= {0x90, 0xCB, 0x80, 0x91, 0x3E, 0xBB, 0x69, 0x6E, 0x08, 0x63, 0x81, 0xB5, 0xEC, 0x42, 0x7B, 0x1F}; /* draft-ietf-ipsec-nat-t-ike-02 */
323
324 static const guint8 VID_draft_beaulieu_ike_xauth_02[VID_LEN]= {0x09, 0x00, 0x26, 0x89, 0xDF, 0xD6, 0xB7, 0x12, 0x80, 0xA2, 0x24, 0xDE, 0xC3, 0x3B, 0x81, 0xE5}; /* draft-beaulieu-ike-xauth-02.txt */
325
326
327 static const guint8 VID_rfc3706_dpd[VID_LEN]= {0xAF, 0xCA,0xD7, 0x13, 0x68, 0xA1, 0xF1, 0xC9, 0x6B, 0x86, 0x96, 0xFC, 0x77, 0x57, 0x01, 0x00}; /* RFC 3706 */
328
329 static const guint8 VID_IKE_CHALLENGE_RESPONSE_1[VID_LEN]= {0xBA, 0x29, 0x04, 0x99, 0xC2, 0x4E, 0x84, 0xE5, 0x3A, 0x1D, 0x83, 0xA0, 0x5E, 0x5F, 0x00, 0xC9}; /* IKE Challenge/Response for Authenticated Cryptographic Keys */
330
331 static const guint8 VID_IKE_CHALLENGE_RESPONSE_2[VID_LEN]= {0x0D, 0x33, 0x61, 0x1A, 0x5D, 0x52, 0x1B, 0x5E, 0x3C, 0x9C, 0x03, 0xD2, 0xFC, 0x10, 0x7E, 0x12}; /* IKE Challenge/Response for Authenticated Cryptographic Keys */
332
333 static const guint8 VID_IKE_CHALLENGE_RESPONSE_REV_1[VID_LEN]= {0xAD, 0x32, 0x51, 0x04, 0x2C, 0xDC, 0x46, 0x52, 0xC9, 0xE0, 0x73, 0x4C, 0xE5, 0xDE, 0x4C, 0x7D}; /* IKE Challenge/Response for Authenticated Cryptographic Keys (Revised) */
334
335 static const guint8 VID_IKE_CHALLENGE_RESPONSE_REV_2[VID_LEN]= {0x01, 0x3F, 0x11, 0x82, 0x3F, 0x96, 0x6F, 0xA9, 0x19, 0x00, 0xF0, 0x24, 0xBA, 0x66, 0xA8, 0x6B}; /* IKE Challenge/Response for Authenticated Cryptographic Keys (Revised) */
336
337 static const guint8 VID_MS_L2TP_IPSEC_VPN_CLIENT[VID_LEN]= {0x40, 0x48, 0xB7, 0xD5, 0x6E, 0xBC, 0xE8, 0x85, 0x25, 0xE7, 0xDE, 0x7F, 0x00, 0xD6, 0xC2, 0xD3}; /* Microsoft L2TP/IPSec VPN Client */
338
339 static const guint8 VID_GSS_API_1[VID_LEN]= {0xB4, 0x6D, 0x89, 0x14, 0xF3, 0xAA, 0xA3, 0xF2, 0xFE, 0xDE, 0xB7, 0xC7, 0xDB, 0x29, 0x43, 0xCA}; /* A GSS-API Authentication Method for IKE */
340
341 static const guint8 VID_GSS_API_2[VID_LEN]= {0xAD, 0x2C, 0x0D, 0xD0, 0xB9, 0xC3, 0x20, 0x83, 0xCC, 0xBA, 0x25, 0xB8, 0x86, 0x1E, 0xC4, 0x55}; /* A GSS-API Authentication Method for IKE */
342
343 static const guint8 VID_GSSAPI[VID_LEN]= {0x62, 0x1B, 0x04, 0xBB, 0x09, 0x88, 0x2A, 0xC1, 0xE1, 0x59, 0x35, 0xFE, 0xFA, 0x24, 0xAE, 0xEE}; /* GSSAPI */
344
345 static const guint8 VID_MS_NT5_ISAKMPOAKLEY[VID_LEN]= {0x1E, 0x2B, 0x51, 0x69, 0x05, 0x99, 0x1C, 0x7D, 0x7C, 0x96, 0xFC, 0xBF, 0xB5, 0x87, 0xE4, 0x61}; /* MS NT5 ISAKMPOAKLEY */
346
347 static const guint8 VID_CISCO_UNITY[VID_LEN]= {0x12, 0xF5, 0xF2, 0x8C, 0x45, 0x71, 0x68, 0xA9, 0x70, 0x2D, 0x9F, 0xE2, 0x74, 0xCC, 0x02, 0xD4}; /* CISCO-UNITY */
348
349 #define VID_LEN_8 8
350 static const guint8 VID_draft_ietf_ipsec_antireplay_00[VID_LEN_8]= {0x32, 0x5D, 0xF2, 0x9A, 0x23, 0x19, 0xF2, 0xDD}; /* draft-ietf-ipsec-antireplay-00.txt */
351
352 static const guint8 VID_draft_ietf_ipsec_heartbeats_00[VID_LEN_8]= {0x8D, 0xB7, 0xA4, 0x18, 0x11, 0x22, 0x16, 0x60}; /* draft-ietf-ipsec-heartbeats-00.txt */
353
354 /* 
355 *  Seen in Netscreen. Suppose to be ASCII HeartBeat_Notify - but I don't know the rest yet. I suspect it then proceeds with
356 *  8k10, which means every 8K (?), and version 1.0 of the protocol (?). I won't add it to the code, until I know what it really
357 *  means. ykaul-at-bezeqint.net
358 */
359 static const guint8 VID_HeartBeat_Notify[VID_LEN] = {0x48, 0x65, 0x61, 0x72, 0x74, 0x42, 0x65, 0x61, 0x74, 0x5f, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79}; 
360
361 void
362 isakmp_dissect_payloads(tvbuff_t *tvb, proto_tree *tree, int isakmp_version,
363                         guint8 initial_payload, int offset, int length,
364                         packet_info *pinfo)
365 {
366   dissect_payloads(tvb, tree, isakmp_version, initial_payload, offset, length,
367                    pinfo);
368 }
369
370 static void
371 dissect_payloads(tvbuff_t *tvb, proto_tree *tree, int isakmp_version,
372                  guint8 initial_payload, int offset, int length, packet_info *pinfo)
373 {
374   guint8 payload, next_payload;
375   guint16               payload_length;
376   proto_tree *          ntree;
377   struct payload_func * f;
378
379   for (payload = initial_payload; length > 0; payload = next_payload) {
380     if (payload == LOAD_TYPE_NONE) {
381       /*
382        * What?  There's more stuff in this chunk of data, but the
383        * previous payload had a "next payload" type of None?
384        */
385       proto_tree_add_text(tree, tvb, offset, length,
386                           "Extra data: %s",
387                           tvb_bytes_to_str(tvb, offset, length));
388       break;
389     }
390     ntree = dissect_payload_header(tvb, offset, length, isakmp_version,
391       payload, &next_payload, &payload_length, tree);
392     if (ntree == NULL)
393       break;
394     if (payload_length >= 4) {  /* XXX = > 4? */
395       tvb_ensure_bytes_exist(tvb, offset + 4, payload_length - 4);
396       if ((f = getpayload_func(payload, isakmp_version)) != NULL && f->func != NULL)
397         (*f->func)(tvb, offset + 4, payload_length - 4, ntree, pinfo,
398                    isakmp_version, -1);
399       else {
400         proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4,
401                             "Payload");
402       }
403     }
404     else if (payload_length > length) {
405         proto_tree_add_text(ntree, tvb, 0, 0,
406             "Payload (bogus, length is %u, greater than remaining length %d",
407             payload_length, length);
408         return;
409     }
410     else {
411         proto_tree_add_text(ntree, tvb, 0, 0,
412             "Payload (bogus, length is %u, must be at least 4)",
413             payload_length);
414         payload_length = 4;
415     }
416     offset += payload_length;
417     length -= payload_length;
418   }
419 }
420
421 static struct payload_func *
422 getpayload_func(guint8 payload, int isakmp_version)
423 {
424   struct payload_func *f = 0;
425   int i, len;
426
427   if (isakmp_version == 1) {
428     f = v1_plfunc;
429     len = ARLEN(v1_plfunc);
430   } else if (isakmp_version == 2) {
431     f = v2_plfunc;
432     len = ARLEN(v2_plfunc);
433   } else
434     return NULL;
435   for (i = 0; i < len; i++) {
436     if (f[i].type == payload)
437       return &f[i];
438   }
439   return NULL;
440 }
441
442 static void
443 dissect_isakmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
444 {
445   int                   offset = 0, len;
446   struct isakmp_hdr     hdr;
447   proto_item *          ti;
448   proto_tree *          isakmp_tree = NULL;
449   int                   isakmp_version;
450
451   if (check_col(pinfo->cinfo, COL_PROTOCOL))
452     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISAKMP");
453   if (check_col(pinfo->cinfo, COL_INFO))
454     col_clear(pinfo->cinfo, COL_INFO);
455
456   if (tree) {
457     ti = proto_tree_add_item(tree, proto_isakmp, tvb, offset, -1, FALSE);
458     isakmp_tree = proto_item_add_subtree(ti, ett_isakmp);
459   }
460
461   /* RFC3948 2.3 NAT Keepalive packet:
462    * 1 byte payload with the value 0xff.
463    */
464   if( (tvb_length(tvb)==1) && (tvb_get_guint8(tvb, offset)==0xff) ){
465     if (check_col(pinfo->cinfo, COL_INFO)){
466       col_add_str(pinfo->cinfo, COL_INFO, "NAT Keepalive");
467     }
468     proto_tree_add_item(isakmp_tree, hf_ike_nat_keepalive, tvb, offset, 1, FALSE);
469     return;
470   }
471
472   hdr.length = tvb_get_ntohl(tvb, offset + sizeof(hdr) - sizeof(hdr.length));
473   hdr.exch_type = tvb_get_guint8(tvb, sizeof(hdr.icookie) + sizeof(hdr.rcookie) + sizeof(hdr.next_payload) + sizeof(hdr.version));
474   hdr.version = tvb_get_guint8(tvb, sizeof(hdr.icookie) + sizeof(hdr.rcookie) + sizeof(hdr.next_payload));
475   isakmp_version = hi_nibble(hdr.version);      /* save the version */
476   if (check_col(pinfo->cinfo, COL_INFO))
477     col_add_str(pinfo->cinfo, COL_INFO,
478                 exchtype2str(isakmp_version, hdr.exch_type));
479
480   if (tree) {
481     tvb_memcpy(tvb, (guint8 *)&hdr.icookie, offset, sizeof(hdr.icookie));
482     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.icookie),
483                         "Initiator cookie: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.icookie)));
484     offset += sizeof(hdr.icookie);
485
486     tvb_memcpy(tvb, (guint8 *)&hdr.rcookie, offset, sizeof(hdr.rcookie));
487     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.rcookie),
488                         "Responder cookie: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.rcookie)));
489     offset += sizeof(hdr.rcookie);
490
491     hdr.next_payload = tvb_get_guint8(tvb, offset);
492     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.next_payload),
493                         "Next payload: %s (%u)",
494                         payloadtype2str(isakmp_version, hdr.next_payload),
495                         hdr.next_payload);
496     offset += sizeof(hdr.next_payload);
497
498     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.version),
499                         "Version: %u.%u",
500                         hi_nibble(hdr.version), lo_nibble(hdr.version));
501     offset += sizeof(hdr.version);
502
503     hdr.exch_type = tvb_get_guint8(tvb, offset);
504     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.exch_type),
505                         "Exchange type: %s (%u)",
506                         exchtype2str(isakmp_version, hdr.exch_type),
507                         hdr.exch_type);
508     offset += sizeof(hdr.exch_type);
509
510     {
511       proto_item *      fti;
512       proto_tree *      ftree;
513
514       hdr.flags = tvb_get_guint8(tvb, offset);
515       fti   = proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.flags), "Flags");
516       ftree = proto_item_add_subtree(fti, ett_isakmp_flags);
517
518       if (isakmp_version == 1) {
519         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
520                           decode_boolean_bitfield(hdr.flags, E_FLAG, sizeof(hdr.flags)*8,
521                                                   "Encrypted", "Not encrypted"));
522         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
523                           decode_boolean_bitfield(hdr.flags, C_FLAG, sizeof(hdr.flags)*8,
524                                                   "Commit", "No commit"));
525         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
526                           decode_boolean_bitfield(hdr.flags, A_FLAG, sizeof(hdr.flags)*8,
527                                                   "Authentication", "No authentication"));
528       } else if (isakmp_version == 2) {
529         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
530                           decode_boolean_bitfield(hdr.flags, I_FLAG, sizeof(hdr.flags)*8,
531                                                   "Initiator", "Responder"));
532         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
533                           decode_boolean_bitfield(hdr.flags, V_FLAG, sizeof(hdr.flags)*8,
534                                                   "A higher version enabled", ""));
535         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
536                           decode_boolean_bitfield(hdr.flags, R_FLAG, sizeof(hdr.flags)*8,
537                                                   "Response", "Request"));
538       }
539       offset += sizeof(hdr.flags);
540     }
541
542     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.message_id),
543         "Message ID: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.message_id)));
544     offset += sizeof(hdr.message_id);
545
546     if (hdr.length < sizeof(hdr)) {
547         proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.length),
548                             "Length: (bogus, length is %u, should be at least %lu)",
549                             hdr.length, (unsigned long)sizeof(hdr));
550         return;
551     }
552
553     len = hdr.length - sizeof(hdr);
554
555     if (len < 0) {
556         proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.length),
557                             "Length: (bogus, length is %u, which is too large)",
558                             hdr.length);
559         return;
560     }
561
562     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.length),
563                         "Length: %u", hdr.length);
564     offset += sizeof(hdr.length);
565
566     if (hdr.flags & E_FLAG) {
567       if (len && isakmp_tree) {
568         proto_tree_add_text(isakmp_tree, tvb, offset, len,
569                         "Encrypted payload (%d byte%s)",
570                         len, plurality(len, "", "s"));
571       }
572     } else
573       dissect_payloads(tvb, isakmp_tree, isakmp_version, hdr.next_payload,
574                        offset, len, pinfo);
575   }
576 }
577
578 static proto_tree *
579 dissect_payload_header(tvbuff_t *tvb, int offset, int length,
580     int isakmp_version, guint8 payload, guint8 *next_payload_p,
581     guint16 *payload_length_p, proto_tree *tree)
582 {
583   guint8                next_payload;
584   guint16               payload_length;
585   proto_item *          ti;
586   proto_tree *          ntree;
587
588   if (length < 4) {
589     proto_tree_add_text(tree, tvb, offset, length,
590           "Not enough room in payload for all transforms");
591     return NULL;
592   }
593   next_payload = tvb_get_guint8(tvb, offset);
594   payload_length = tvb_get_ntohs(tvb, offset + 2);
595
596   ti = proto_tree_add_text(tree, tvb, offset, payload_length,
597             "%s payload", payloadtype2str(isakmp_version, payload));
598   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
599
600   proto_tree_add_text(ntree, tvb, offset, 1,
601                       "Next payload: %s (%u)",
602                       payloadtype2str(isakmp_version, next_payload),
603                       next_payload);
604   if (isakmp_version == 2) {
605     proto_tree_add_text(ntree, tvb, offset + 1, 1, "%s",
606                 decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 1), 0x80,
607                 8, "Critical", "Not critical"));
608   }
609   proto_tree_add_text(ntree, tvb, offset + 2, 2, "Length: %u", payload_length);
610
611   *next_payload_p = next_payload;
612   *payload_length_p = payload_length;
613   return ntree;
614 }
615
616 static void
617 dissect_sa(tvbuff_t *tvb, int offset, int length, proto_tree *tree, 
618     packet_info *pinfo, int isakmp_version, int unused _U_)
619 {
620   guint32               doi;
621   guint32               situation;
622
623   if (length < 4) {
624     proto_tree_add_text(tree, tvb, offset, length,
625                         "DOI %s (length is %u, should be >= 4)",
626                         tvb_bytes_to_str(tvb, offset, length), length);
627     return;
628   }
629   if (isakmp_version == 1) {
630     doi = tvb_get_ntohl(tvb, offset);
631     proto_tree_add_text(tree, tvb, offset, 4,
632                       "Domain of interpretation: %s (%u)",
633                       doitype2str(doi), doi);
634     offset += 4;
635     length -= 4;
636
637     if (doi == 1) {
638       /* IPSEC */
639       if (length < 4) {
640         proto_tree_add_text(tree, tvb, offset, length,
641                           "Situation: %s (length is %u, should be >= 4)",
642                           tvb_bytes_to_str(tvb, offset, length), length);
643         return;
644       }
645       situation = tvb_get_ntohl(tvb, offset);
646       proto_tree_add_text(tree, tvb, offset, 4,
647                         "Situation: %s (%u)",
648                         situation2str(situation), situation);
649       offset += 4;
650       length -= 4;
651
652       dissect_payloads(tvb, tree, isakmp_version, LOAD_TYPE_PROPOSAL, offset,
653                        length, pinfo);
654     } else {
655       /* Unknown */
656       proto_tree_add_text(tree, tvb, offset, length,
657                         "Situation: %s",
658                         tvb_bytes_to_str(tvb, offset, length));
659     }
660   } else if (isakmp_version == 2) {
661     dissect_payloads(tvb, tree, isakmp_version, LOAD_TYPE_PROPOSAL, offset,
662                      length, pinfo);
663   }
664 }
665
666 static void
667 dissect_proposal(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
668     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
669 {
670   guint8                protocol_id;
671   guint8                spi_size;
672   guint8                num_transforms;
673   guint8                next_payload;
674   guint16               payload_length;
675   proto_tree *          ntree;
676   guint8                proposal_num;
677
678   proposal_num = tvb_get_guint8(tvb, offset);
679
680   proto_item_append_text(tree, " # %d",proposal_num);
681   proto_tree_add_text(tree, tvb, offset, 1,
682                       "Proposal number: %u", proposal_num);
683   offset += 1;
684   length -= 1;
685
686   protocol_id = tvb_get_guint8(tvb, offset);
687   proto_tree_add_text(tree, tvb, offset, 1,
688                       "Protocol ID: %s (%u)",
689                       val_to_str(protocol_id, vs_proto, "UNKNOWN-PROTO-TYPE"), protocol_id);
690   offset += 1;
691   length -= 1;
692
693   spi_size = tvb_get_guint8(tvb, offset);
694   proto_tree_add_text(tree, tvb, offset, 1,
695                       "SPI size: %u", spi_size);
696   offset += 1;
697   length -= 1;
698
699   num_transforms = tvb_get_guint8(tvb, offset);
700   proto_tree_add_text(tree, tvb, offset, 1,
701                       "Number of transforms: %u", num_transforms);
702   offset += 1;
703   length -= 1;
704
705   if (spi_size) {
706     proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: 0x%s",
707                         tvb_bytes_to_str(tvb, offset, spi_size));
708     offset += spi_size;
709     length -= spi_size;
710   }
711
712   while (num_transforms > 0) {
713     ntree = dissect_payload_header(tvb, offset, length, isakmp_version,
714       LOAD_TYPE_TRANSFORM, &next_payload, &payload_length, tree);
715     if (ntree == NULL)
716       break;
717     if (length < payload_length) {
718       proto_tree_add_text(tree, tvb, offset + 4, length,
719           "Not enough room in payload for all transforms");
720       break;
721     }
722     if (payload_length >= 4) {
723       if (isakmp_version == 1)
724         dissect_transform(tvb, offset + 4, payload_length - 4, ntree,
725                         pinfo, isakmp_version, protocol_id);
726       else if (isakmp_version == 2)
727         dissect_transform2(tvb, offset + 4, payload_length - 4, ntree,
728                         pinfo, isakmp_version, protocol_id);
729     }
730     else
731       proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4, "Payload");
732     offset += payload_length;
733     length -= payload_length;
734     num_transforms--;
735   }
736 }
737
738 static void
739 dissect_transform(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
740     packet_info *pinfo _U_, int isakmp_version _U_, int protocol_id)
741 {
742   static const value_string vs_v1_attr[] = {
743     { 1,        "Encryption-Algorithm" },
744     { 2,        "Hash-Algorithm" },
745     { 3,        "Authentication-Method" },
746     { 4,        "Group-Description" },
747     { 5,        "Group-Type" },
748     { 6,        "Group-Prime" },
749     { 7,        "Group-Generator-One" },
750     { 8,        "Group-Generator-Two" },
751     { 9,        "Group-Curve-A" },
752     { 10,       "Group-Curve-B" },
753     { 11,       "Life-Type" },
754     { 12,       "Life-Duration" },
755     { 13,       "PRF" },
756     { 14,       "Key-Length" },
757     { 15,       "Field-Size" },
758     { 16,       "Group-Order" },
759     { 0,        NULL },
760   };
761
762   static const value_string vs_v2_sttr[] = {
763     { 1,        "SA-Life-Type" },
764     { 2,        "SA-Life-Duration" },
765     { 3,        "Group-Description" },
766     { 4,        "Encapsulation-Mode" },
767     { 5,        "Authentication-Algorithm" },
768     { 6,        "Key-Length" },
769     { 7,        "Key-Rounds" },
770     { 8,        "Compress-Dictinary-Size" },
771     { 9,        "Compress-Private-Algorithm" },
772     { 10,       "ECN Tunnel" },
773     { 0,        NULL },
774   };
775
776   static const value_string vs_v1_trans_isakmp[] = {
777     { 0,        "RESERVED" },
778     { 1,        "KEY_IKE" },
779     { 0,        NULL },
780   };
781
782   static const value_string vs_v1_trans_ah[] = {
783     { 0,        "RESERVED" },
784     { 1,        "RESERVED" },
785     { 2,        "MD5" },
786     { 3,        "SHA" },
787     { 4,        "DES" },
788     { 5,        "SHA2-256" },
789     { 6,        "SHA2-384" },
790     { 7,        "SHA2-512" },
791     { 0,        NULL },
792   };
793
794   static const value_string vs_v1_trans_esp[] = {
795     { 0,        "RESERVED" },
796     { 1,        "DES-IV64" },
797     { 2,        "DES" },
798     { 3,        "3DES" },
799     { 4,        "RC5" },
800     { 5,        "IDEA" },
801     { 6,        "CAST" },
802     { 7,        "BLOWFISH" },
803     { 8,        "3IDEA" },
804     { 9,        "DES-IV32" },
805     { 10,       "RC4" },
806     { 11,       "NULL" },
807     { 12,       "AES" },
808     { 0,        NULL },
809   };
810
811   static const value_string vs_v1_trans_ipcomp[] = {
812     { 0,        "RESERVED" },
813     { 1,        "OUI" },
814     { 2,        "DEFLATE" },
815     { 3,        "LZS" },
816     { 4,        "LZJH" },
817     { 0,        NULL },
818   };
819
820   guint8                transform_id;
821   guint8                transform_num;
822
823   transform_num = tvb_get_guint8(tvb, offset);
824   proto_item_append_text(tree," # %d",transform_num);
825   proto_tree_add_text(tree, tvb, offset, 1,
826                       "Transform number: %u", transform_num);
827   offset += 1;
828   length -= 1;
829
830   transform_id = tvb_get_guint8(tvb, offset);
831   switch (protocol_id) {
832   default:
833     proto_tree_add_text(tree, tvb, offset, 1,
834                         "Transform ID: %u", transform_id);
835     break;
836   case 1:       /* ISAKMP */
837     proto_tree_add_text(tree, tvb, offset, 1,
838                         "Transform ID: %s (%u)",
839                         val_to_str(transform_id, vs_v1_trans_isakmp, "UNKNOWN-TRANS-TYPE"), transform_id);
840     break;
841   case 2:       /* AH */
842     proto_tree_add_text(tree, tvb, offset, 1,
843                         "Transform ID: %s (%u)",
844                         val_to_str(transform_id, vs_v1_trans_ah, "UNKNOWN-AH-TRANS-TYPE"), transform_id);
845     break;
846   case 3:       /* ESP */
847     proto_tree_add_text(tree, tvb, offset, 1,
848                         "Transform ID: %s (%u)",
849                         val_to_str(transform_id, vs_v1_trans_esp, "UNKNOWN-ESP-TRANS-TYPE"), transform_id);
850     break;
851   case 4:       /* IPCOMP */
852     proto_tree_add_text(tree, tvb, offset, 1,
853                         "Transform ID: %s (%u)",
854                         val_to_str(transform_id, vs_v1_trans_ipcomp, "UNKNOWN-IPCOMP-TRANS-TYPE"), transform_id);
855     break;
856   }
857   offset += 3;
858   length -= 3;
859
860   while (length>0) {
861     const char *str;
862     int ike_phase1 = 0;
863     guint16 aft     = tvb_get_ntohs(tvb, offset);
864     guint16 type    = aft & 0x7fff;
865     guint16 len;
866     guint32 val;
867     guint pack_len;
868
869     if (protocol_id == 1 && transform_id == 1) {
870       ike_phase1 = 1;
871       str = val_to_str(type, vs_v1_attr, "UNKNOWN-ATTRIBUTE-TYPE");
872     }
873     else {
874       str = val_to_str(type, vs_v2_sttr, "UNKNOWN-ATTRIBUTE-TYPE");
875     }
876
877     if (aft & 0x8000) {
878       val = tvb_get_ntohs(tvb, offset + 2);
879       proto_tree_add_text(tree, tvb, offset, 4,
880                           "%s (%u): %s (%u)",
881                           str, type,
882                           v1_attrval2str(ike_phase1, type, val), val);
883       offset += 4;
884       length -= 4;
885     }
886     else {
887       len = tvb_get_ntohs(tvb, offset + 2);
888       pack_len = 4 + len;
889       if (!get_num(tvb, offset + 4, len, &val)) {
890         proto_tree_add_text(tree, tvb, offset, pack_len,
891                             "%s (%u): <too big (%u bytes)>",
892                             str, type, len);
893       } else {
894         proto_tree_add_text(tree, tvb, offset, pack_len,
895                             "%s (%u): %s (%u)",
896                             str, type,
897                             v1_attrval2str(ike_phase1, type, val), val);
898       }
899       offset += pack_len;
900       length -= pack_len;
901     }
902   }
903 }
904
905 /* For Transform Type 1 (Encryption Algorithm), defined Transform IDs */
906 static const char *
907 v2_tid2encstr(guint16 tid)
908 {
909   static const value_string vs_v2_trans_enc[] = {
910     { 0,        "RESERVED" },
911     { 1,        "ENCR_DES_IV64" },
912     { 2,        "ENCR_DES" },
913     { 3,        "ENCR_3DE" },
914     { 4,        "ENCR_RC5" },
915     { 5,        "ENCR_IDEA" },
916     { 6,        "ENCR_CAST" },
917     { 7,        "ENCR_BLOWFISH" },
918     { 8,        "ENCR_3IDEA" },
919     { 9,        "ENCR_DES_IV32" },
920     { 10,       "RESERVED" },
921     { 11,       "ENCR_NULL" },
922     { 12,       "ENCR_AES_CBC" },
923     { 13,       "ENCR_AES_CTR" },
924     { 0,        NULL },
925   };
926
927   return val_to_str(tid, vs_v2_trans_enc, "UNKNOWN-ENC-ALG");
928 }
929
930 /* For Transform Type 2 (Pseudo-random Function), defined Transform IDs */
931 static const char *
932 v2_tid2prfstr(guint16 tid)
933 {
934   static const value_string vs_v2_trans_prf[] = {
935     { 0,        "RESERVED" },
936     { 1,        "PRF_HMAC_MD5" },
937     { 2,        "PRF_HMAC_SHA1" },
938     { 3,        "PRF_HMAC_TIGER" },
939     { 4,        "PRF_AES128_CBC" },
940     { 0,        NULL },
941   };
942   return val_to_str(tid, vs_v2_trans_prf, "UNKNOWN-PRF");
943 }
944
945 /* For Transform Type 3 (Integrity Algorithm), defined Transform IDs */
946 static const char *
947 v2_tid2iastr(guint16 tid)
948 {
949   static const value_string vs_v2_trans_integrity[] = {
950     { 0,        "NONE" },
951     { 1,        "AUTH_HMAC_MD5_96" },
952     { 2,        "AUTH_HMAC_SHA1_96" },
953     { 3,        "AUTH_DES_MAC" },
954     { 4,        "AUTH_KPDK_MD5" },
955     { 5,        "AUTH_AES_XCBC_96" },
956     { 0,        NULL },
957   };
958   return val_to_str(tid, vs_v2_trans_integrity, "UNKNOWN-INTEGRITY-ALG");
959 }
960
961 /* For Transform Type 4 (Diffie-Hellman Group), defined Transform IDs */
962 static const char *
963 v2_tid2dhstr(guint16 tid)
964 {
965   static const value_string vs_v2_trans_dhgroup[] = {
966     {  0,       "NONE" },
967     {  1,       "Group 1 - 768 Bit MODP" },
968     {  2,       "Group 2 - 1024 Bit MODP" },
969     {  3,       "RESERVED" },
970     {  4,       "RESERVED" },
971     {  5,       "group 5 - 1536 Bit MODP" },
972     { 14,       "2048-bit MODP Group" },
973     { 15,       "3072-bit MODP Group" },
974     { 16,       "4096-bit MODP Group" },
975     { 17,       "6144-bit MODP Group" },
976     { 18,       "8192-bit MODP Group" },
977     { 0,        NULL },
978   };
979
980   if ((tid >= 6 && tid <= 13) || (tid >= 19 && tid <= 1023))
981     return "RESERVED TO IANA";
982   if (tid >= 1024)
983     return "PRIVATE USE";
984   return val_to_str(tid, vs_v2_trans_dhgroup, "UNKNOWN-DH-GROUP");
985 }
986
987 /* For Transform Type 5 (Extended Sequence Numbers), defined Transform */
988 static const char *
989 v2_tid2esnstr(guint16 tid)
990 {
991   static const value_string vs_v2_trans_esn[] = {
992     { 0,        "No Extended Sequence Numbers" },
993     { 1,        "Extended Sequence Numbers" },
994     { 0,        NULL },
995   };
996
997   return val_to_str(tid, vs_v2_trans_esn, "UNKNOWN-ESN-TYPE");
998 }
999
1000 static struct {
1001   const gint8 type;
1002   const char *str;
1003   const char *(*func)(guint16);
1004 } v2_tid_func[] = {
1005   { 0,  "RESERVED", NULL, },
1006   { 1,  "Encryption Algorithm (ENCR)", v2_tid2encstr },
1007   { 2,  "Pseudo-random Function (PRF)", v2_tid2prfstr }, 
1008   { 3,  "Integrity Algorithm (INTEG)", v2_tid2iastr },
1009   { 4,  "Diffie-Hellman Group (D-H)", v2_tid2dhstr },
1010   { 5,  "Extended Sequence Numbers (ESN)", v2_tid2esnstr },
1011 };
1012
1013 static const char *
1014 v2_trans2str(guint8 type)
1015 {
1016   if (type < ARLEN(v2_tid_func)) return v2_tid_func[type].str;
1017   if (type < 240) return "RESERVED TO IANA";
1018   return "PRIVATE USE";
1019 }
1020
1021 static const char *
1022 v2_tid2str(guint8 type, guint16 tid)
1023 {
1024   if (type < ARLEN(v2_tid_func) && v2_tid_func[type].func != NULL) {
1025     return (v2_tid_func[type].func)(tid);
1026   }
1027   return "RESERVED";
1028 }
1029
1030 static const char *
1031 v2_aft2str(guint16 aft)
1032 {
1033     if (aft < 14 || (aft > 14 && aft < 18)) return "RESERVED";
1034     if (aft == 14) return "Key Length (in bits)";
1035     if (aft >= 18 && aft < 16384) return "RESERVED TO IANA";
1036     return "PRIVATE USE";
1037 }
1038
1039 static void
1040 dissect_transform2(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1041     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1042 {
1043   guint8 transform_type;
1044   guint16 transform_id;
1045
1046   transform_type = tvb_get_guint8(tvb, offset);
1047   proto_tree_add_text(tree, tvb, offset, 1,
1048     "Transform type: %s (%u)", v2_trans2str(transform_type), transform_type);
1049   offset += 2;
1050   length -= 2;
1051
1052   transform_id = tvb_get_ntohs(tvb, offset);
1053   proto_tree_add_text(tree, tvb, offset, 2,
1054     "Transform ID: %s (%u)", v2_tid2str(transform_type, transform_id),
1055     transform_id);
1056   offset += 2;
1057   length -= 2;
1058
1059   while (length>0) {
1060     const char *str;
1061     guint16 aft     = tvb_get_ntohs(tvb, offset);
1062     guint16 type    = aft & 0x7fff;
1063     guint16 len;
1064     guint32 val;
1065     guint pack_len;
1066
1067     str = v2_aft2str(aft);
1068
1069     if (aft & 0x8000) {
1070       val = tvb_get_ntohs(tvb, offset + 2);
1071       proto_tree_add_text(tree, tvb, offset, 4,
1072                           "%s (%u): %s (%u)",
1073                           str, type,
1074                           v2_attrval2str(type, val), val);
1075       offset += 4;
1076       length -= 4;
1077     }
1078     else {
1079       len = tvb_get_ntohs(tvb, offset + 2);
1080       pack_len = 4 + len;
1081       if (!get_num(tvb, offset + 4, len, &val)) {
1082         proto_tree_add_text(tree, tvb, offset, pack_len,
1083                             "%s (%u): <too big (%u bytes)>",
1084                             str, type, len);
1085       } else {
1086         proto_tree_add_text(tree, tvb, offset, pack_len,
1087                             "%s (%u): %s (%u)",
1088                             str, type,
1089                             v2_attrval2str(type, val), val);
1090       }
1091       offset += pack_len;
1092       length -= pack_len;
1093     }
1094   }
1095 }
1096
1097 static void
1098 dissect_key_exch(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1099     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1100 {
1101   guint16 dhgroup;
1102
1103   if (isakmp_version == 2) {
1104     dhgroup = tvb_get_ntohs(tvb, offset);
1105     proto_tree_add_text(tree, tvb, offset, 2,
1106                       "DH Group #: %u", dhgroup);
1107     offset += 4;
1108     length -= 4;
1109   }
1110
1111   proto_tree_add_text(tree, tvb, offset, length, "Key Exchange Data");
1112 }
1113
1114 static void
1115 dissect_id(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1116     packet_info *pinfo, int isakmp_version, int unused _U_)
1117 {
1118   guint8                id_type;
1119   guint8                protocol_id;
1120   guint16               port;
1121
1122   id_type = tvb_get_guint8(tvb, offset);
1123   proto_tree_add_text(tree, tvb, offset, 1,
1124                       "ID type: %s (%u)",
1125                       id2str(isakmp_version, id_type), id_type);
1126   offset += 1;
1127   length -= 1;
1128
1129   protocol_id = tvb_get_guint8(tvb, offset);
1130   if (protocol_id == 0) {
1131     proto_tree_add_text(tree, tvb, offset, 1,
1132                         "Protocol ID: Unused");
1133   } else {
1134     proto_tree_add_text(tree, tvb, offset, 1,
1135                         "Protocol ID: %s (%u)",
1136                         ipprotostr(protocol_id), protocol_id);
1137   }
1138   offset += 1;
1139   length -= 1;
1140
1141   port = tvb_get_ntohs(tvb, offset);
1142   if (port == 0)
1143     proto_tree_add_text(tree, tvb, offset, 2, "Port: Unused");
1144   else
1145     proto_tree_add_text(tree, tvb, offset, 2, "Port: %u", port);
1146   offset += 2;
1147   length -= 2;
1148
1149   /*
1150    * It shows strings of all types though some of types are not
1151    * supported in IKEv2 specification actually.
1152    */
1153   switch (id_type) {
1154     case IKE_ID_IPV4_ADDR:
1155       proto_tree_add_text(tree, tvb, offset, length,
1156                           "Identification data: %s",
1157                           ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1158       break;
1159     case IKE_ID_FQDN:
1160     case IKE_ID_USER_FQDN:
1161       proto_tree_add_text(tree, tvb, offset, length,
1162                           "Identification data: %.*s", length,
1163                           tvb_get_ptr(tvb, offset, length));
1164       break;
1165     case IKE_ID_IPV4_ADDR_SUBNET:
1166     case IKE_ID_IPV4_ADDR_RANGE:
1167       proto_tree_add_text(tree, tvb, offset, length,
1168                           "Identification data: %s/%s",
1169                           ip_to_str(tvb_get_ptr(tvb, offset, 4)),
1170                           ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
1171       break;
1172     case IKE_ID_IPV6_ADDR:
1173       proto_tree_add_text(tree, tvb, offset, length,
1174                           "Identification data: %s",
1175                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)));
1176       break;
1177     case IKE_ID_IPV6_ADDR_SUBNET:
1178     case IKE_ID_IPV6_ADDR_RANGE:
1179       proto_tree_add_text(tree, tvb, offset, length,
1180                           "Identification data: %s/%s",
1181                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)),
1182                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset+16, 16)));
1183       break;
1184     case IKE_ID_DER_ASN1_DN:
1185       dissect_x509if_Name(FALSE, tvb, offset, pinfo, tree,
1186                           hf_ike_certificate_authority);
1187       break;
1188     default:
1189       proto_tree_add_text(tree, tvb, offset, length, "Identification Data");
1190       break;
1191   }
1192 }
1193
1194 static void
1195 dissect_cert(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1196     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1197 {
1198   guint8                cert_enc;
1199
1200   cert_enc = tvb_get_guint8(tvb, offset);
1201   proto_tree_add_text(tree, tvb, offset, 1,
1202                       "Certificate encoding: %u - %s",
1203                       cert_enc, certtype2str(isakmp_version, cert_enc));
1204   offset += 1;
1205   length -= 1;
1206
1207   proto_tree_add_text(tree, tvb, offset, length, "Certificate Data");
1208 }
1209
1210 static void
1211 dissect_certreq_v1(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1212     packet_info *pinfo, int isakmp_version, int unused _U_)
1213 {
1214   guint8                cert_type;
1215
1216   cert_type = tvb_get_guint8(tvb, offset);
1217   proto_tree_add_text(tree, tvb, offset, 1,
1218                       "Certificate type: %u - %s",
1219                       cert_type, certtype2str(isakmp_version, cert_type));
1220   offset += 1;
1221   length -= 1;
1222
1223   if (length) {
1224     if (cert_type == 4){
1225       dissect_x509if_Name(FALSE, tvb, offset, pinfo, tree, hf_ike_certificate_authority);
1226     } else {
1227       proto_tree_add_text(tree, tvb, offset, length, "Certificate Authority");
1228     }
1229   }
1230   else
1231     proto_tree_add_text(tree, tvb, offset, length, "Certificate Authority (empty)");
1232 }
1233
1234 static void
1235 dissect_certreq_v2(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1236     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1237 {
1238   guint8                cert_type;
1239
1240   cert_type = tvb_get_guint8(tvb, offset);
1241   proto_tree_add_text(tree, tvb, offset, 1,
1242                       "Certificate type: %u - %s",
1243                       cert_type, certtype2str(isakmp_version, cert_type));
1244   offset += 1;
1245   length -= 1;
1246
1247   /* this is a list of 20 byte SHA-1 hashes */
1248   while (length > 0) {
1249     proto_tree_add_item(tree, hf_ike_v2_certificate_authority, tvb, offset, 20, FALSE);
1250     length-=20;
1251   }
1252 }
1253
1254 static void
1255 dissect_hash(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1256     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1257 {
1258   proto_tree_add_text(tree, tvb, offset, length, "Hash Data");
1259 }
1260
1261 static void
1262 dissect_auth(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1263     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1264 {
1265   guint8 auth;
1266
1267   auth = tvb_get_guint8(tvb, offset);
1268   proto_tree_add_text(tree, tvb, offset, 1,
1269                       "Auth Method: %s (%u)", v2_auth2str(auth), auth);
1270   offset += 4;
1271   length -= 4;
1272
1273   proto_tree_add_text(tree, tvb, offset, length, "Authentication Data");
1274 }
1275
1276 static void
1277 dissect_sig(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1278     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1279 {
1280   proto_tree_add_text(tree, tvb, offset, length, "Signature Data");
1281 }
1282
1283 static void
1284 dissect_nonce(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1285     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1286 {
1287   proto_tree_add_text(tree, tvb, offset, length, "Nonce Data");
1288 }
1289
1290 static const char *
1291 v2_ipcomptype2str(guint8 type)
1292 {
1293   static const value_string vs_v2_ipcomptype[] = {
1294     { 0,        "RESERVED" },
1295     { 1,        "IPCOMP_OUI" },
1296     { 2,        "IPCOMP_DEFLATE" },
1297     { 3,        "IPCOMP_LZS" },
1298     { 4,        "IPCOMP_LZJH" },
1299     { 0,        NULL },
1300   };
1301
1302   if (type >= 5 && type <= 240)
1303     return "RESERVED TO IANA";
1304   if (type >= 241)
1305     return "PRIVATE USE";
1306   return val_to_str(type, vs_v2_ipcomptype, "UNKNOWN-IPCOMP-TYPE");
1307 }
1308
1309 static void
1310 dissect_notif(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1311     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1312 {
1313   guint32               doi;
1314   guint8                protocol_id;
1315   guint8                spi_size;
1316   guint16               msgtype;
1317   guint8                ipcomptype;
1318
1319   if (isakmp_version == 1) {
1320     doi = tvb_get_ntohl(tvb, offset);
1321     proto_tree_add_text(tree, tvb, offset, 4,
1322                       "Domain of Interpretation: %s (%u)",
1323                       doitype2str(doi), doi);
1324     offset += 4;
1325     length -= 4;
1326   }
1327
1328   protocol_id = tvb_get_guint8(tvb, offset);
1329   proto_tree_add_text(tree, tvb, offset, 1,
1330                       "Protocol ID: %s (%u)",
1331                       val_to_str(protocol_id, vs_proto, "UNKNOWN-PROTO-TYPE"), protocol_id);
1332   offset += 1;
1333   length -= 1;
1334
1335   spi_size = tvb_get_guint8(tvb, offset);
1336   proto_tree_add_text(tree, tvb, offset, 1,
1337                       "SPI size: %u", spi_size);
1338   offset += 1;
1339   length -= 1;
1340
1341   msgtype = tvb_get_ntohs(tvb, offset);
1342   proto_tree_add_text(tree, tvb, offset, 2,
1343                       "Message type: %s (%u)",
1344                       msgtype2str(isakmp_version, msgtype), msgtype);
1345   offset += 2;
1346   length -= 2;
1347
1348   if (spi_size) {
1349     proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: 0x%s",
1350                         tvb_bytes_to_str(tvb, offset, spi_size));
1351     offset += spi_size;
1352     length -= spi_size;
1353   }
1354
1355   if (length > 0) {
1356     proto_tree_add_text(tree, tvb, offset, length, "Notification Data");
1357
1358     /* notification data */
1359     if (isakmp_version == 2 && msgtype == 16387) {
1360       /* IPCOMP_SUPPORTED */
1361       proto_tree_add_text(tree, tvb, offset, 2,
1362                         "IPComp CPI (%u)", tvb_get_ntohs(tvb, offset));
1363       ipcomptype = tvb_get_guint8(tvb, offset + 2);
1364       proto_tree_add_text(tree, tvb, offset + 2, 1,
1365                         "Transform ID: %s (%u)",
1366                         v2_ipcomptype2str(ipcomptype), ipcomptype);
1367       offset += 3;
1368       length -= 3;
1369     }
1370   }
1371 }
1372
1373 static void
1374 dissect_delete(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1375     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1376 {
1377   guint32               doi;
1378   guint8                protocol_id;
1379   guint8                spi_size;
1380   guint16               num_spis;
1381   guint16               i;
1382
1383   if (isakmp_version == 1) {
1384     doi = tvb_get_ntohl(tvb, offset);
1385     proto_tree_add_text(tree, tvb, offset, 4,
1386                         "Domain of Interpretation: %s (%u)",
1387                         doitype2str(doi), doi);
1388     offset += 4;
1389     length -= 4;
1390   }
1391
1392   protocol_id = tvb_get_guint8(tvb, offset);
1393   proto_tree_add_text(tree, tvb, offset, 1,
1394                       "Protocol ID: %s (%u)",
1395                       val_to_str(protocol_id, vs_proto, "UNKNOWN-PROTO-TYPE"), protocol_id);
1396   offset += 1;
1397   length -= 1;
1398
1399   spi_size = tvb_get_guint8(tvb, offset);
1400   proto_tree_add_text(tree, tvb, offset, 1,
1401                       "SPI size: %u", spi_size);
1402   offset += 1;
1403   length -= 1;
1404
1405   num_spis = tvb_get_ntohs(tvb, offset);
1406   proto_tree_add_text(tree, tvb, offset, 2,
1407                       "Number of SPIs: %u", num_spis);
1408   offset += 2;
1409   length -= 2;
1410
1411   for (i = 0; i < num_spis; ++i) {
1412     if (length < spi_size) {
1413       proto_tree_add_text(tree, tvb, offset, length,
1414           "Not enough room in payload for all SPI's");
1415       break;
1416     }
1417     proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: 0x%s",
1418                         tvb_bytes_to_str(tvb, offset, spi_size));
1419     offset += spi_size;
1420     length -= spi_size;
1421   }
1422 }
1423
1424 static void
1425 dissect_vid(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1426     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1427 {
1428   guint32 CPproduct, CPversion;
1429   const guint8 * pVID;
1430   proto_item * pt;
1431   proto_tree * ntree;
1432   pVID = tvb_get_ptr(tvb, offset, length);
1433   pt = proto_tree_add_text(tree, tvb, offset, length, "Vendor ID: ");
1434   if (memcmp(pVID, VID_MS_W2K_WXP, isakmp_min(VID_MS_LEN, length)) == 0)
1435         proto_item_append_text(pt, "Microsoft Win2K/WinXP");
1436   else
1437   if (memcmp(pVID, VID_CP, isakmp_min(VID_CP_LEN, length)) == 0)
1438   {
1439         proto_item_append_text(pt, "Check Point");
1440         offset += VID_CP_LEN;
1441         CPproduct = tvb_get_ntohl(tvb, offset);
1442         ntree = proto_item_add_subtree(pt, ett_isakmp_payload);
1443         pt = proto_tree_add_text(ntree, tvb, offset, sizeof(CPproduct), "Check Point Product: ");
1444         switch (CPproduct) {
1445                 case 1: proto_item_append_text(pt, "VPN-1");
1446                         break;
1447                 case 2: proto_item_append_text(pt, "SecuRemote/SecureClient");
1448                         break;
1449                 default: proto_item_append_text(pt, "Unknown CP product!");
1450                         break;
1451         }
1452         offset += sizeof(CPproduct);
1453         CPversion = tvb_get_ntohl(tvb, offset);
1454         pt = proto_tree_add_text(ntree, tvb, offset, sizeof(CPversion), "Version: ");
1455         switch (CPversion) {
1456                 case 2: proto_item_append_text(pt, "4.1");
1457                         break;
1458                 case 3: proto_item_append_text(pt, "4.1 SP-1");
1459                         break;
1460                 case 4002: proto_item_append_text(pt, "4.1 (SP-2 or above)");
1461                         break;
1462                 case 5000: proto_item_append_text(pt, "NG");
1463                         break;
1464                 case 5001: proto_item_append_text(pt, "NG Feature Pack 1");
1465                         break;
1466                 case 5002: proto_item_append_text(pt, "NG Feature Pack 2");
1467                         break;
1468                 case 5003: proto_item_append_text(pt, "NG Feature Pack 3");
1469                         break;
1470                 case 5004: proto_item_append_text(pt, "NG with Application Intelligence");
1471                         break;
1472                 case 5005: proto_item_append_text(pt, "NG with Application Intelligence R55");
1473                         break;
1474                 default: proto_item_append_text(pt, " Unknown CP version!");
1475                         break;
1476         }
1477         offset += sizeof(CPversion);
1478         proto_tree_add_text(ntree, tvb, offset, length - VID_CP_LEN - sizeof(CPproduct) - sizeof(CPversion),"Check Point Vendor ID parameters"); 
1479   }
1480   else
1481   if (memcmp(pVID, VID_CYBERGUARD, isakmp_min(VID_LEN, length)) == 0)
1482         proto_item_append_text(pt, "Cyber Guard");
1483   else
1484   if (memcmp(pVID,  VID_draft_ietf_ipsec_nat_t_ike_03, isakmp_min(VID_LEN, length)) == 0)
1485         proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-03");
1486   else
1487   if (memcmp(pVID,  VID_rfc3947, isakmp_min(VID_LEN, length)) == 0)
1488         proto_item_append_text(pt, "RFC 3947 Negotiation of NAT-Traversal in the IKE");
1489   else
1490   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_1_0, isakmp_min(VID_LEN, length)) == 0)
1491         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.0");
1492   else
1493   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_1_1, isakmp_min(VID_LEN, length)) == 0)
1494         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.1");
1495   else
1496   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_1_2, isakmp_min(VID_LEN, length)) == 0)
1497         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.2");
1498   else
1499   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_2_1, isakmp_min(VID_LEN, length)) == 0)
1500         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.2.1");
1501   else
1502   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_2_2, isakmp_min(VID_LEN, length)) == 0)
1503         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.2.2");
1504   else
1505   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_2_0_0, isakmp_min(VID_LEN, length)) == 0)
1506         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.0.0");
1507   else
1508   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_2_1_0, isakmp_min(VID_LEN, length)) == 0)
1509         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.0");
1510   else
1511   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_2_1_1, isakmp_min(VID_LEN, length)) == 0)
1512         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.1");
1513   else
1514   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_2_1_2, isakmp_min(VID_LEN, length)) == 0)
1515         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.2");
1516   else
1517   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_3_0_0, isakmp_min(VID_LEN, length)) == 0)
1518         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 3.0.0");
1519   else
1520   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_3_0_1, isakmp_min(VID_LEN, length)) == 0)
1521         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 3.0.1");
1522   else
1523   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_4_0_0, isakmp_min(VID_LEN, length)) == 0)
1524         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.0.0");
1525   else
1526   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_4_0_1, isakmp_min(VID_LEN, length)) == 0)
1527         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.0.1");
1528   else
1529   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_4_1_0, isakmp_min(VID_LEN, length)) == 0)
1530         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.1.0");
1531   else
1532   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_4_1_1, isakmp_min(VID_LEN, length)) == 0)
1533         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.1.1");
1534   else
1535   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_5_0, isakmp_min(VID_LEN, length)) == 0)
1536         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.0");
1537   else
1538   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_5_0_0, isakmp_min(VID_LEN, length)) == 0)
1539         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.0.0");
1540   else
1541   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_5_1_0, isakmp_min(VID_LEN, length)) == 0)
1542         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.1.0");
1543   else
1544   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_5_1_1, isakmp_min(VID_LEN, length)) == 0)
1545         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.1.1");
1546   else
1547   if (memcmp(pVID,  VID_SSH_SENTINEL, isakmp_min(VID_LEN, length)) == 0)
1548         proto_item_append_text(pt, "SSH Sentinel");
1549   else
1550   if (memcmp(pVID,  VID_SSH_SENTINEL_1_1, isakmp_min(VID_LEN, length)) == 0)
1551         proto_item_append_text(pt, "SSH Sentinel 1.1");
1552   else
1553   if (memcmp(pVID,  VID_SSH_SENTINEL_1_2, isakmp_min(VID_LEN, length)) == 0)
1554         proto_item_append_text(pt, "SSH Sentinel 1.2");
1555   else
1556   if (memcmp(pVID,  VID_SSH_SENTINEL_1_3, isakmp_min(VID_LEN, length)) == 0)
1557         proto_item_append_text(pt, "SSH Sentinel 1.3");
1558   else
1559   if (memcmp(pVID,  VID_SSH_QUICKSEC_0_9_0, isakmp_min(VID_LEN, length)) == 0)
1560         proto_item_append_text(pt, "SSH Communications Security QuickSec 0.9.0");
1561   else
1562   if (memcmp(pVID,  VID_SSH_QUICKSEC_1_1_0, isakmp_min(VID_LEN, length)) == 0)
1563         proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.0");
1564   else
1565   if (memcmp(pVID,  VID_SSH_QUICKSEC_1_1_1, isakmp_min(VID_LEN, length)) == 0)
1566         proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.1");
1567   else
1568   if (memcmp(pVID,  VID_SSH_QUICKSEC_1_1_2, isakmp_min(VID_LEN, length)) == 0)
1569         proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.2");
1570   else
1571   if (memcmp(pVID,  VID_SSH_QUICKSEC_1_1_3, isakmp_min(VID_LEN, length)) == 0)
1572         proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.3");
1573   else
1574   if (memcmp(pVID,  VID_draft_huttunen_ipsec_esp_in_udp_01, isakmp_min(VID_LEN, length)) == 0)
1575         proto_item_append_text(pt, "draft-huttunen-ipsec-esp-in-udp-01.txt");
1576   else
1577   if (memcmp(pVID,  VID_draft_stenberg_ipsec_nat_traversal_01, isakmp_min(VID_LEN, length)) == 0)
1578         proto_item_append_text(pt, "draft-stenberg-ipsec-nat-traversal-01");
1579   else
1580   if (memcmp(pVID,  VID_draft_stenberg_ipsec_nat_traversal_02, isakmp_min(VID_LEN, length)) == 0)
1581         proto_item_append_text(pt, "draft-stenberg-ipsec-nat-traversal-02");
1582   else
1583   if (memcmp(pVID,  VID_draft_ietf_ipsec_nat_t_ike_00, isakmp_min(VID_LEN, length)) == 0)
1584         proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-00");
1585   else
1586   if (memcmp(pVID,  VID_draft_ietf_ipsec_nat_t_ike_02a, isakmp_min(VID_LEN, length)) == 0)
1587         proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-02");
1588   else
1589   if (memcmp(pVID,  VID_draft_ietf_ipsec_nat_t_ike_02b, isakmp_min(VID_LEN, length)) == 0)
1590         proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-02");
1591   else
1592   if (memcmp(pVID,  VID_draft_beaulieu_ike_xauth_02, isakmp_min(VID_LEN, length)) == 0)
1593         proto_item_append_text(pt, "draft-beaulieu-ike-xauth-02.txt");
1594   else
1595   if (memcmp(pVID,  VID_rfc3706_dpd, isakmp_min(VID_LEN, length)) == 0)
1596         proto_item_append_text(pt, "RFC 3706 Detecting Dead IKE Peers (DPD)");
1597   else
1598   if (memcmp(pVID,  VID_IKE_CHALLENGE_RESPONSE_1, isakmp_min(VID_LEN, length)) == 0)
1599         proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys");
1600   else
1601   if (memcmp(pVID,  VID_IKE_CHALLENGE_RESPONSE_2, isakmp_min(VID_LEN, length)) == 0)
1602         proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys");
1603   else
1604   if (memcmp(pVID,  VID_IKE_CHALLENGE_RESPONSE_REV_1, isakmp_min(VID_LEN, length)) == 0)
1605         proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys (Revised)");
1606   else
1607   if (memcmp(pVID,  VID_IKE_CHALLENGE_RESPONSE_REV_2, isakmp_min(VID_LEN, length)) == 0)
1608         proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys (Revised)");
1609   else
1610   if (memcmp(pVID,  VID_MS_L2TP_IPSEC_VPN_CLIENT, isakmp_min(VID_LEN, length)) == 0)
1611         proto_item_append_text(pt, "Microsoft L2TP/IPSec VPN Client");
1612   else
1613   if (memcmp(pVID,  VID_GSS_API_1, isakmp_min(VID_LEN, length)) == 0)
1614         proto_item_append_text(pt, "A GSS-API Authentication Method for IKE");
1615   else
1616   if (memcmp(pVID,  VID_GSS_API_2, isakmp_min(VID_LEN, length)) == 0)
1617         proto_item_append_text(pt, "A GSS-API Authentication Method for IKE");
1618   else
1619   if (memcmp(pVID,  VID_GSSAPI, isakmp_min(VID_LEN, length)) == 0)
1620         proto_item_append_text(pt, "GSSAPI");
1621   else
1622   if (memcmp(pVID,  VID_MS_NT5_ISAKMPOAKLEY, isakmp_min(VID_LEN, length)) == 0)
1623         proto_item_append_text(pt, "MS NT5 ISAKMPOAKLEY");
1624   else
1625   if (memcmp(pVID,  VID_CISCO_UNITY, isakmp_min(VID_LEN, length)) == 0)
1626         proto_item_append_text(pt, "CISCO-UNITY");
1627   else
1628   if (memcmp(pVID,  VID_draft_ietf_ipsec_antireplay_00, isakmp_min(VID_LEN_8, length)) == 0)
1629         proto_item_append_text(pt, "draft-ietf-ipsec-antireplay-00.txt");
1630   else
1631   if (memcmp(pVID,  VID_draft_ietf_ipsec_heartbeats_00, isakmp_min(VID_LEN_8, length)) == 0)
1632         proto_item_append_text(pt, "draft-ietf-ipsec-heartbeats-00.txt");
1633   else
1634         proto_item_append_text(pt, "unknown vendor ID: 0x%s",tvb_bytes_to_str(tvb, offset, length));
1635 }
1636
1637 static void
1638 dissect_config(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1639     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1640 {
1641   guint8                type;
1642
1643   if (isakmp_version == 1) {
1644     type = tvb_get_guint8(tvb, offset);
1645     proto_tree_add_text(tree, tvb, offset, 1,
1646                         "Type %s (%u)",
1647                         cfgtype2str(isakmp_version, type), type);
1648     offset += 2;
1649     length -= 2;
1650
1651     proto_tree_add_text(tree, tvb, offset, 2,
1652                         "Identifier: %u", tvb_get_ntohs(tvb, offset));
1653     offset += 2;
1654     length -= 2;
1655   } else if (isakmp_version == 2) {
1656     type = tvb_get_guint8(tvb, offset);
1657     proto_tree_add_text(tree, tvb, offset, 1,
1658                         "CFG Type %s (%u)",
1659                         cfgtype2str(isakmp_version, type), type);
1660     offset += 4;
1661     length -= 4;
1662   }
1663
1664   while(length>0) {
1665     guint16 aft     = tvb_get_ntohs(tvb, offset);
1666     guint16 type    = aft & 0x7fff;
1667     guint16 len;
1668     guint32 val;
1669     guint pack_len;
1670
1671     if (aft & 0x8000) {
1672       val = tvb_get_ntohs(tvb, offset + 2);
1673       proto_tree_add_text(tree, tvb, offset, 4,
1674                           "%s (%u)",
1675                           cfgattr2str(isakmp_version, type), val);
1676       offset += 4;
1677       length -= 4;
1678     }
1679     else {
1680       len = tvb_get_ntohs(tvb, offset + 2);
1681       pack_len = 4 + len;
1682       if (!get_num(tvb, offset + 4, len, &val)) {
1683         proto_tree_add_text(tree, tvb, offset, pack_len,
1684                             "%s: <too big (%u bytes)>",
1685                             cfgattr2str(isakmp_version, type), len);
1686       } else {
1687         proto_tree_add_text(tree, tvb, offset, 4,
1688                             "%s (%ue)",
1689                             cfgattr2str(isakmp_version, type), val);
1690       }
1691       offset += pack_len;
1692       length -= pack_len;
1693     }
1694   }
1695 }
1696
1697 static void
1698 dissect_nat_discovery(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1699     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1700 {
1701   proto_tree_add_text(tree, tvb, offset, length,
1702                       "Hash of address and port: %s",
1703                       tvb_bytes_to_str(tvb, offset, length));
1704 }
1705
1706 static void
1707 dissect_nat_original_address(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1708     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1709 {
1710   guint8 id_type;
1711   guint32 addr_ipv4;
1712   struct e_in6_addr addr_ipv6;
1713
1714   id_type = tvb_get_guint8(tvb, offset);
1715   proto_tree_add_text(tree, tvb, offset, 1,
1716                       "ID type: %s (%u)",
1717                       id2str(isakmp_version, id_type), id_type);
1718   offset += 1;
1719   length -= 1;
1720
1721   offset += 3;          /* reserved */
1722   length -= 3;
1723
1724   switch (id_type) {
1725
1726   case IKE_ID_IPV4_ADDR:
1727     if (length == 4) {
1728       addr_ipv4 = tvb_get_ipv4(tvb, offset);
1729       proto_tree_add_text(tree, tvb, offset, length,
1730                           "Original address: %s",
1731                           ip_to_str((guint8 *)&addr_ipv4));
1732     } else {
1733       proto_tree_add_text(tree, tvb, offset, length,
1734                           "Original address: bad length, should be 4, is %u",
1735                           length);
1736     }
1737     break;
1738
1739   case IKE_ID_IPV6_ADDR:
1740     if (length == 16) {
1741       tvb_get_ipv6(tvb, offset, &addr_ipv6);
1742       proto_tree_add_text(tree, tvb, offset, length,
1743                           "Original address: %s",
1744                           ip6_to_str(&addr_ipv6));
1745     } else {
1746       proto_tree_add_text(tree, tvb, offset, length,
1747                           "Original address: bad length, should be 16, is %u",
1748                           length);
1749     }
1750     break;
1751
1752   default:
1753     proto_tree_add_text(tree, tvb, offset, length,
1754                         "Original address: bad address type");
1755     break;
1756   }
1757 }
1758
1759 static void
1760 dissect_ts(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1761     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1762 {
1763   guint8        num, tstype, protocol_id, addrlen;
1764   guint16       len, port;
1765
1766   proto_tree_add_text(tree, tvb, offset, length, "Traffic Selector");
1767
1768   num = tvb_get_guint8(tvb, offset);
1769   proto_item_append_text(tree," # %d", num);
1770   proto_tree_add_text(tree, tvb, offset, 1,
1771                       "Number of TSs: %u", num);
1772   offset += 4;
1773   length -= 4;
1774
1775   while (length > 0) {
1776     tstype = tvb_get_guint8(tvb, offset);
1777     proto_tree_add_text(tree, tvb, offset, 1,
1778                       "TS Type: %s (%u)",
1779                       v2_tstype2str(tstype), tstype);
1780     switch (tstype) {
1781     case IKEV2_TS_IPV4_ADDR_RANGE:
1782       addrlen = 4;
1783       break;
1784     case IKEV2_TS_IPV6_ADDR_RANGE:
1785       addrlen = 16;
1786       break;
1787     default:
1788       proto_item_append_text(tree, "unknown TS data (aborted decoding): 0x%s",
1789                         tvb_bytes_to_str(tvb, offset, length));
1790       return;
1791     }
1792
1793     /*
1794      * XXX should the remaining of the length check be done here ?
1795      * it seems other routines don't check the length.
1796      */
1797     if (length < (8 + addrlen * 2)) {
1798       proto_tree_add_text(tree, tvb, offset, length,
1799                           "Length mismatch (%u)", length);
1800       return;
1801     }
1802     offset += 1;
1803     length -= 1;
1804
1805     protocol_id = tvb_get_guint8(tvb, offset);
1806     proto_tree_add_text(tree, tvb, offset, 1,
1807                       "Protocol ID: (%u)", protocol_id);
1808     offset += 1;
1809     length -= 1;
1810
1811     len = tvb_get_ntohs(tvb, offset);
1812     proto_tree_add_text(tree, tvb, offset, 2,
1813                       "Selector Length: %u", len);
1814     offset += 2;
1815     length -= 2;
1816
1817     port = tvb_get_ntohs(tvb, offset);
1818     proto_tree_add_text(tree, tvb, offset, 2,
1819                       "Start Port: (%u)", port);
1820     offset += 2;
1821     length -= 2;
1822
1823     port = tvb_get_ntohs(tvb, offset);
1824     proto_tree_add_text(tree, tvb, offset, 2,
1825                       "End Port: (%u)", port);
1826     offset += 2;
1827     length -= 2;
1828
1829     switch (tstype) {
1830     case IKEV2_TS_IPV4_ADDR_RANGE:
1831         proto_tree_add_text(tree, tvb, offset, length,
1832                           "Starting Address: %s",
1833                           ip_to_str(tvb_get_ptr(tvb, offset, addrlen)));
1834         offset += addrlen;
1835         length -= addrlen;
1836         proto_tree_add_text(tree, tvb, offset, length,
1837                           "Ending Address: %s",
1838                           ip_to_str(tvb_get_ptr(tvb, offset, addrlen)));
1839         offset += addrlen;
1840         length -= addrlen;
1841         break;
1842     case IKEV2_TS_IPV6_ADDR_RANGE:
1843         proto_tree_add_text(tree, tvb, offset, length,
1844                           "Starting Address: %s",
1845                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, addrlen)));
1846         offset += addrlen;
1847         length -= addrlen;
1848         proto_tree_add_text(tree, tvb, offset, length,
1849                           "Ending Address: %s",
1850                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, addrlen)));
1851         offset += addrlen;
1852         length -= addrlen;
1853         break;
1854     }
1855   }
1856 }
1857
1858 static void
1859 dissect_enc(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1860     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1861 {
1862   proto_tree_add_text(tree, tvb, offset, 4, "Initialization Vector: 0x%s",
1863                       tvb_bytes_to_str(tvb, offset, 4));
1864   proto_tree_add_text(tree, tvb, offset + 4, length, "Encrypted Data");
1865 }
1866
1867 static void
1868 dissect_eap(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1869     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1870 {
1871   proto_tree_add_text(tree, tvb, offset, length, "EAP Message");
1872 }
1873
1874 static const char *
1875 payloadtype2str(int isakmp_version, guint8 type)
1876 {
1877   struct payload_func *f;
1878
1879   if ((f = getpayload_func(type, isakmp_version)) != NULL)
1880       return f->str;
1881
1882   if (isakmp_version == 1) {
1883     if (type < 128)
1884       return "RESERVED";
1885     return "Private USE";
1886   } else if (isakmp_version == 2) {
1887     if (type > 127)
1888       return "PRIVATE USE";
1889     if (type > 48)
1890       return "RESERVED TO IANA";
1891     return "RESERVED";
1892   }
1893   return "UNKNOWN-ISAKMP-VERSION";
1894 }
1895
1896 static const char *
1897 exchtype2str(int isakmp_version, guint8 type)
1898 {
1899   static const value_string vs_v1_exchange[] = {
1900     { 0,        "NONE" },
1901     { 1,        "Base" },
1902     { 2,        "Identity Protection (Main Mode)" },
1903     { 3,        "Authentication Only" },
1904     { 4,        "Aggressive" },
1905     { 5,        "Informational" },
1906     { 6,        "Transaction (Config Mode)" },
1907     { 32,       "Quick Mode" },
1908     { 33,       "New Group Mode" },
1909     { 0,        NULL },
1910   };
1911
1912   static const value_string vs_v2_exchange[] = {
1913     { 34,       "IKE_SA_INIT" },
1914     { 35,       "IKE_AUTH " },
1915     { 36,       "CREATE_CHILD_SA" },
1916     { 37,       "INFORMATIONAL" },
1917     { 0,        NULL },
1918   };
1919
1920   if (isakmp_version == 1) {
1921     if (type > 6 && type < 32)
1922       return "ISAKMP Future Use";
1923     if (type > 33 && type < 240)
1924       return "DOI Specific Use";
1925     return val_to_str(type, vs_v1_exchange, "Private Use");
1926   } else if (isakmp_version == 2) {
1927     if (type < 34)
1928       return "RESERVED";
1929     if (type > 37 && type < 240)
1930       return "Reserved for IKEv2+";
1931     return val_to_str(type, vs_v2_exchange, "Reserved for private use");
1932   }
1933   return "UNKNOWN-ISAKMP-VERSION";
1934 }
1935
1936 static const char *
1937 doitype2str(guint32 type)
1938 {
1939   if (type == 1) return "IPSEC";
1940   return "Unknown DOI Type";
1941 }
1942
1943 static const char *
1944 msgtype2str(int isakmp_version, guint16 type)
1945 {
1946   static const value_string vs_v1_notifmsg[] = {
1947     { 0,        "<UNKNOWN>" },
1948     { 1,        "INVALID-PAYLOAD-TYPE" },
1949     { 2,        "DOI-NOT-SUPPORTED" },
1950     { 3,        "SITUATION-NOT-SUPPORTED" },
1951     { 4,        "INVALID-COOKIE" },
1952     { 5,        "INVALID-MAJOR-VERSION" },
1953     { 6,        "INVALID-MINOR-VERSION" },
1954     { 7,        "INVALID-EXCHANGE-TYPE" },
1955     { 8,        "INVALID-FLAGS" },
1956     { 9,        "INVALID-MESSAGE-ID" },
1957     { 10,       "INVALID-PROTOCOL-ID" },
1958     { 11,       "INVALID-SPI" },
1959     { 12,       "INVALID-TRANSFORM-ID" },
1960     { 13,       "ATTRIBUTES-NOT-SUPPORTED" },
1961     { 14,       "NO-PROPOSAL-CHOSEN" },
1962     { 15,       "BAD-PROPOSAL-SYNTAX" },
1963     { 16,       "PAYLOAD-MALFORMED" },
1964     { 17,       "INVALID-KEY-INFORMATION" },
1965     { 18,       "INVALID-ID-INFORMATION" },
1966     { 19,       "INVALID-CERT-ENCODING" },
1967     { 20,       "INVALID-CERTIFICATE" },
1968     { 21,       "CERT-TYPE-UNSUPPORTED" },
1969     { 22,       "INVALID-CERT-AUTHORITY" },
1970     { 23,       "INVALID-HASH-INFORMATION" },
1971     { 24,       "AUTHENTICATION-FAILED" },
1972     { 25,       "INVALID-SIGNATURE" },
1973     { 26,       "ADDRESS-NOTIFICATION" },
1974     { 27,       "NOTIFY-SA-LIFETIME" },
1975     { 28,       "CERTIFICATE-UNAVAILABLE" },
1976     { 29,       "UNSUPPORTED-EXCHANGE-TYPE" },
1977     { 30,       "UNEQUAL-PAYLOAD-LENGTHS" },
1978     { 8192,     "RESERVED" },
1979     { 16384,    "CONNECTED" },
1980     { 24576,    "RESPONDER-LIFETIME" },
1981     { 24577,    "REPLAY-STATUS" },
1982     { 24578,    "INITIAL-CONTACT" },
1983     { 0,        NULL },
1984   };
1985
1986   static const value_string vs_v2_notifmsg[] = {
1987     {     0,    "RESERVED" },
1988     {     4,    "INVALID_IKE_SPI" },
1989     {     5,    "INVALID_MAJOR_VERSION" },
1990     {     7,    "INVALID_SYNTAX" },
1991     {     9,    "INVALID_MESSAGE_ID" },
1992     {    11,    "INVALID_SPI" },
1993     {    14,    "NO_PROPOSAL_CHOSEN" },
1994     {    17,    "INVALID_KE_PAYLOAD" },
1995     {    24,    "AUTHENTICATION_FAILED" },
1996     {    34,    "SINGLE_PAIR_REQUIRED" },
1997     {    35,    "NO_ADDITIONAL_SAS" },
1998     {    36,    "INTERNAL_ADDRESS_FAILURE" },
1999     {    37,    "FAILED_CP_REQUIRED" },
2000     {    38,    "TS_UNACCEPTABLE" },
2001     {    39,    "INVALID_SELECTORS" },
2002     { 16384,    "INITIAL_CONTACT" },
2003     { 16385,    "SET_WINDOW_SIZE" },
2004     { 16386,    "ADDITIONAL_TS_POSSIBLE" },
2005     { 16387,    "IPCOMP_SUPPORTED" },
2006     { 16388,    "NAT_DETECTION_SOURCE_IP" },
2007     { 16389,    "NAT_DETECTION_DESTINATION_IP" },
2008     { 16390,    "COOKIE" },
2009     { 16391,    "USE_TRANSPORT_MODE" },
2010     { 16392,    "HTTP_CERT_LOOKUP_SUPPORTED" },
2011     { 16393,    "REKEY_SA" },
2012     { 16394,    "ESP_TFC_PADDING_NOT_SUPPORTED" },
2013     { 16395,    "NON_FIRST_FRAGMENTS_ALSO" },
2014     { 0,        NULL },
2015   };
2016
2017   if (isakmp_version == 1) {
2018     if (type > 30 && type < 8192)
2019       return "RESERVED (Future Use)";
2020     if (type > 8192 && type < 16384)
2021       return "Private Use";
2022     if (type > 16384 && type < 24576)
2023       return "RESERVED (Future Use) - status";
2024     if (type > 24578 && type < 32768)
2025       return "DOI-specific codes";
2026     if (type > 32767 && type < 40960)
2027       return "Private Use - status";
2028     if (type > 40959 && type < 65535)
2029       return "RESERVED (Future Use) - status (2)";
2030     return val_to_str(type, vs_v1_notifmsg, "UNKNOWN-NOTIFY-MESSAGE-TYPE");
2031   } else if (isakmp_version == 2) {
2032     if (type >= 40 && type <= 8191)
2033       return "RESERVED TO IANA - Error types";
2034     if (type >= 16396 && type <= 40959)
2035       return "RESERVED TO IANA - STATUS TYPES";
2036     if (type >= 8192 && type <= 16383)
2037       return "Private Use - Errors";
2038     if (type >= 40960)
2039       return "Private Use - STATUS TYPES";
2040     return val_to_str(type, vs_v2_notifmsg, "UNKNOWN-NOTIFY-MESSAGE-TYPE");
2041   } 
2042   return "UNKNOWN-ISAKMP-VERSION";
2043 }
2044
2045 static const char *
2046 situation2str(guint32 type)
2047 {
2048
2049 #define SIT_MSG_NUM     1024
2050 #define SIT_IDENTITY    0x01
2051 #define SIT_SECRECY     0x02
2052 #define SIT_INTEGRITY   0x04
2053
2054   static char   msg[SIT_MSG_NUM];
2055   int           n = 0;
2056   const char *  sep = "";
2057   int           ret;
2058
2059   if (type & SIT_IDENTITY) {
2060     ret = g_snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep);
2061     if (ret == -1 || ret >= SIT_MSG_NUM-n) {
2062       /* Truncated. */
2063       return msg;
2064     }
2065     n += ret;
2066     sep = " & ";
2067   }
2068   if (type & SIT_SECRECY) {
2069     if (n >= SIT_MSG_NUM) {
2070       /* No more room. */
2071       return msg;
2072     }
2073     ret = g_snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep);
2074     if (ret == -1 || ret >= SIT_MSG_NUM-n) {
2075       /* Truncated. */
2076       return msg;
2077     }
2078     n += ret;
2079     sep = " & ";
2080   }
2081   if (type & SIT_INTEGRITY) {
2082     if (n >= SIT_MSG_NUM) {
2083       /* No more room. */
2084       return msg;
2085     }
2086     ret = g_snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep);
2087     if (ret == -1 || ret >= SIT_MSG_NUM-n) {
2088       /* Truncated. */
2089       return msg;
2090     }
2091     n += ret;
2092     sep = " & ";
2093   }
2094
2095   return msg;
2096 }
2097
2098 static const char *
2099 v2_attrval2str(guint16 att_type, guint32 value)
2100 {
2101   value = 0;    /* dummy to be less warning in compiling it */
2102   switch (att_type) {
2103   case 14:
2104     return "Key-Length";
2105   default:
2106     return "UNKNOWN-ATTRIBUTE-TYPE";
2107   }
2108 }
2109
2110 static const char *
2111 v1_attrval2str(int ike_p1, guint16 att_type, guint32 value)
2112 {
2113   static const value_string vs_v1_attrval_lttype[] = {
2114     { 0,        "RESERVED" },
2115     { 1,        "Seconds" },
2116     { 2,        "Kilobytes" },
2117     { 0,        NULL },
2118   };
2119
2120   static const value_string vs_v1_attrval_encap[] = {
2121     { 0,        "RESERVED" },
2122     { 1,        "Tunnel" },
2123     { 2,        "Transport" },
2124     { 3,        "UDP-Encapsulated-Tunnel" }, /* http://www.ietf.org/internet-drafts/draft-ietf-ipsec-nat-t-ike-05.txt */
2125     { 4,        "UDP-Encapsulated-Transport" }, /* http://www.ietf.org/internet-drafts/draft-ietf-ipsec-nat-t-ike-05.txt */
2126     { 61440,    "Check Point IPSec UDP Encapsulation" },
2127     { 61443,    "UDP-Encapsulated-Tunnel (draft)" },
2128     { 61444,    "UDP-Encapsulated-Transport (draft)" },
2129     { 0,        NULL },
2130   };
2131
2132   static const value_string vs_v1_attrval_auth[] = {
2133     { 0,        "RESERVED" },
2134     { 1,        "HMAC-MD5" },
2135     { 2,        "HMAC-SHA" },
2136     { 3,        "DES-MAC" },
2137     { 4,        "KPDK" },
2138     { 5,        "HMAC-SHA2-256" },
2139     { 6,        "HMAC-SHA2-384" },
2140     { 7,        "HMAC-SHA2-512" },
2141     { 0,        NULL },
2142   };
2143
2144   static const value_string vs_v1_attrval_enc[] = {
2145     { 0,        "RESERVED" },
2146     { 1,        "DES-CBC" },
2147     { 2,        "IDEA-CBC" },
2148     { 3,        "BLOWFISH-CBC" },
2149     { 4,        "RC5-R16-B64-CBC" },
2150     { 5,        "3DES-CBC" },
2151     { 6,        "CAST-CBC" },
2152     { 7,        "AES-CBC" },
2153     { 0,        NULL },
2154   };
2155
2156   static const value_string vs_v1_attrval_hash[] = {
2157     { 0,        "RESERVED" },
2158     { 1,        "MD5" },
2159     { 2,        "SHA" },
2160     { 3,        "TIGER" },
2161     { 4,        "SHA2-256" },
2162     { 5,        "SHA2-384" },
2163     { 6,        "SHA2-512" },
2164     { 0,        NULL },
2165   };
2166
2167   static const value_string vs_v1_attrval_authmeth[] = {
2168     { 0,        "RESERVED" },
2169     { 1,        "PSK" },
2170     { 2,        "DSS-SIG" },
2171     { 3,        "RSA-SIG" },
2172     { 4,        "RSA-ENC" },
2173     { 5,        "RSA-Revised-ENC" },
2174     { 6,        "Encryption with El-Gamal" },
2175     { 7,        "Revised encryption with El-Gamal" },
2176     { 8,        "ECDSA signatures" },
2177     { 9,        "AES-XCBC-MAC" },
2178     { 64221,    "HybridInitRSA" },
2179     { 64222,    "HybridRespRSA" },
2180     { 64223,    "HybridInitDSS" },
2181     { 64224,    "HybridRespDSS" },
2182     { 65001,    "XAUTHInitPreShared" },
2183     { 65002,    "XAUTHRespPreShared" },
2184     { 65003,    "XAUTHInitDSS" },
2185     { 65004,    "XAUTHRespDSS" },
2186     { 65005,    "XAUTHInitRSA" },
2187     { 65006,    "XAUTHRespRSA" },
2188     { 65007,    "XAUTHInitRSAEncryption" },
2189     { 65008,    "XAUTHRespRSAEncryption" },
2190     { 65009,    "XAUTHInitRSARevisedEncryption" },
2191     { 65010,    "XAUTHRespRSARevisedEncryption" },
2192     { 0,        NULL },
2193   };
2194
2195   static const value_string vs_v1_attrval_grpdesc[] = {
2196     { 0,        "UNDEFINED - 0" },
2197     { 1,        "Default 768-bit MODP group" },
2198     { 2,        "Alternate 1024-bit MODP group" },
2199     { 3,        "EC2N group on GP[2^155] group" },
2200     { 4,        "EC2N group on GP[2^185] group" },
2201     { 5,        "1536 bit MODP group" },
2202     { 6,        "EC2N group over GF[2^163]" },
2203     { 7,        "EC2N group over GF[2^163]" },
2204     { 8,        "EC2N group over GF[2^283]" },
2205     { 9,        "EC2N group over GF[2^283]" },
2206     { 10,       "EC2N group over GF[2^409]" },
2207     { 11,       "EC2N group over GF[2^409]" },
2208     { 12,       "EC2N group over GF[2^571]" },
2209     { 13,       "EC2N group over GF[2^571]" },
2210     { 14,       "2048 bit MODP group" },
2211     { 15,       "3072 bit MODP group" },
2212     { 16,       "4096 bit MODP group" },
2213     { 17,       "6144 bit MODP group" },
2214     { 18,       "8192 bit MODP group" },
2215     { 0,        NULL },
2216   };
2217
2218   static const value_string vs_v1_attrval_grptype[] = {
2219     { 0,        "UNDEFINED - 0" },
2220     { 1,        "MODP" },
2221     { 2,        "ECP" },
2222     { 3,        "EC2N" },
2223     { 0,        NULL },
2224   };
2225
2226   static const value_string vs_v1_attrval_lifetype[] = {
2227     { 0,        "UNDEFINED - 0" },
2228     { 1,        "Seconds" },
2229     { 2,        "Kilobytes" },
2230     { 0,        NULL },
2231   };
2232
2233   if (value == 0) return "RESERVED";
2234
2235   if (!ike_p1) {
2236     switch (att_type) {
2237       case 1:
2238         return val_to_str(value, vs_v1_attrval_lttype, "UNKNOWN-LIFETIME-TYPE");
2239       case 2:
2240         return "Duration-Value";
2241       case 3:
2242         return "Group-Value";
2243       case 4:
2244         return val_to_str(value, vs_v1_attrval_encap, "UNKNOWN-ENCAPSULATION-VALUE");
2245       case 5:
2246         return val_to_str(value, vs_v1_attrval_auth, "UNKNOWN-AUTHENTICATION-VALUE");
2247       case 6:
2248         return "Key-Length";
2249       case 7:
2250         return "Key-Rounds";
2251       case 8:
2252         return "Compress-Dictionary-size";
2253       case 9:
2254         return "Compress Private Algorithm";
2255       default:
2256         return "UNKNOWN-ATTRIBUTE-TYPE";
2257     }
2258   }
2259   else {
2260     switch (att_type) {
2261       case 1:
2262         return val_to_str(value, vs_v1_attrval_enc, "UNKNOWN-ENCRYPTION-ALG");
2263       case 2:
2264         return val_to_str(value, vs_v1_attrval_hash, "UNKNOWN-HASH-ALG");
2265       case 3:
2266         return val_to_str(value, vs_v1_attrval_authmeth, "UNKNOWN-AUTH-METHOD");
2267       case 4:
2268         return val_to_str(value, vs_v1_attrval_grpdesc, "UNKNOWN-GROUP-DESCRIPTION");
2269       case 6:
2270       case 7:
2271       case 8:
2272       case 9:
2273       case 10:
2274       case 16:
2275         return "Group-Value";
2276       case 5:
2277         return val_to_str(value, vs_v1_attrval_grptype, "UNKNOWN-GROUP-TYPE");
2278       case 11:
2279         return val_to_str(value, vs_v1_attrval_lifetype, "UNKNOWN-LIFE-TYPE");
2280       case 12:
2281         return "Duration-Value";
2282       case 13:
2283         return "PRF-Value";
2284       case 14:
2285         return "Key-Length";
2286       case 15:
2287         return "Field-Size";
2288       default:
2289         return "UNKNOWN-ATTRIBUTE-TYPE";
2290     }
2291   }
2292 }
2293
2294 static const char *
2295 cfgtype2str(int isakmp_version, guint8 type)
2296 {
2297   static const value_string vs_v1_cfgtype[] = {
2298     { 0,        "Reserved" },
2299     { 1,        "ISAKMP_CFG_REQUEST" },
2300     { 2,        "ISAKMP_CFG_REPLY" },
2301     { 3,        "ISAKMP_CFG_SET" },
2302     { 4,        "ISAKMP_CFG_ACK" },
2303     { 0,        NULL },
2304   };
2305
2306 #if 0
2307   static const value_string vs_v2_cfgtype[] = {
2308     { 0,        "RESERVED" },
2309     { 1,        "CFG_REQUEST" },
2310     { 2,        "CFG_REPLY" },
2311     { 3,        "CFG_SET" },
2312     { 4,        "CFG_ACK" },
2313     { 0,        NULL },
2314   };
2315 #endif
2316
2317   if (isakmp_version == 1) {
2318     if (type >= 5 && type <= 127)
2319       return "Future use";
2320     if (type >= 128)
2321       return "Private Use";
2322     return val_to_str(type, vs_v1_cfgtype, "UNKNOWN-CFG-TYPE");
2323   } else if (isakmp_version == 2) {
2324     if (type >= 5 && type <= 127)
2325       return "RESERVED TO IANA";
2326     if (type >= 128)
2327       return "PRIVATE USE";
2328     return val_to_str(type, vs_v1_cfgtype, "UNKNOWN-CFG-TYPE");
2329   }
2330   return "UNKNOWN-ISAKMP-VERSION";
2331 }
2332
2333 static const char *
2334 id2str(int isakmp_version, guint8 type)
2335 {
2336   static const value_string vs_ident[] = {
2337     { IKE_ID_IPV4_ADDR,         "IPV4_ADDR" },
2338     { IKE_ID_FQDN,              "FQDN" },
2339     { IKE_ID_USER_FQDN,         "USER_FQDN" },
2340     { IKE_ID_IPV4_ADDR_SUBNET,  "IPV4_ADDR_SUBNET" },
2341     { IKE_ID_IPV6_ADDR,         "IPV6_ADDR" },
2342     { IKE_ID_IPV6_ADDR_SUBNET,  "IPV6_ADDR_SUBNET" },
2343     { IKE_ID_IPV4_ADDR_RANGE,   "IPV4_ADDR_RANGE" },
2344     { IKE_ID_IPV6_ADDR_RANGE,   "IPV6_ADDR_RANGE" },
2345     { IKE_ID_DER_ASN1_DN,       "DER_ASN1_DN" },
2346     { IKE_ID_DER_ASN1_GN,       "DER_ASN1_GN" },
2347     { IKE_ID_KEY_ID,            "KEY_ID" },
2348     { 0,                        NULL },
2349   };
2350
2351   if (isakmp_version == 1) {
2352     if (type == 0)
2353       return "RESERVED";
2354     return val_to_str(type, vs_ident, "UNKNOWN-ID-TYPE");
2355   } else if (isakmp_version == 2) {
2356     if (type == 4 || (type >= 6 && type <=8) || (type >= 12 && type <= 200))
2357       return "Reserved to IANA";
2358     if (type >= 201)
2359       return "Reserved for private use";
2360     if (type == IKE_ID_USER_FQDN)
2361       return "RFC822_ADDR";
2362     return val_to_str(type, vs_ident, "UNKNOWN-ID-TYPE");
2363   }
2364   return "UNKNOWN-ISAKMP-VERSION";
2365 }
2366
2367 static const char *
2368 v2_tstype2str(guint8 type)
2369 {
2370   static const value_string vs_v2_tstype[] = {
2371     { IKEV2_TS_IPV4_ADDR_RANGE, "TS_IPV4_ADDR_RANGE" },
2372     { IKEV2_TS_IPV6_ADDR_RANGE, "TS_IPV6_ADDR_RANGE" },
2373     { 0,        NULL },
2374   };
2375
2376   if (type <= 6)
2377     return "RESERVED";
2378   if (type >= 9 && type <= 240)
2379     return "RESERVED TO IANA";
2380   if (type >= 241)
2381     return "PRIVATE USE";
2382   return val_to_str(type, vs_v2_tstype, "UNKNOWN-TS-TYPE");
2383 }
2384
2385 static const char *
2386 v2_auth2str(guint8 type)
2387 {
2388   static const value_string vs_v2_authmeth[] = {
2389     { 0,        "RESERVED TO IANA" },
2390     { 1,        "RSA Digital Signature" },
2391     { 2,        "Shared Key Message Integrity Code" },
2392     { 3,        "DSS Digital Signature" },
2393     { 0,        NULL },
2394   };
2395
2396   if (type >= 4 && type <= 200)
2397     return "RESERVED TO IANA";
2398   if (type >= 201)
2399     return "PRIVATE USE";
2400   return val_to_str(type, vs_v2_authmeth, "UNKNOWN-AUTHMETHOD-TYPE");
2401 }
2402
2403 static const char *
2404 cfgattr2str(int isakmp_version, guint16 ident)
2405 {
2406   static const value_string vs_v1_cfgattr[] = {
2407     { 0,        "RESERVED" },
2408     { 1,        "INTERNAL_IP4_ADDRESS" },
2409     { 2,        "INTERNAL_IP4_NETMASK" },
2410     { 3,        "INTERNAL_IP4_DNS" },
2411     { 4,        "INTERNAL_IP4_NBNS" },
2412     { 5,        "INTERNAL_ADDRESS_EXPIREY" },
2413     { 6,        "INTERNAL_IP4_DHCP" },
2414     { 7,        "APPLICATION_VERSION" },
2415     { 8,        "INTERNAL_IP6_ADDRESS" },
2416     { 9,        "INTERNAL_IP6_NETMASK" },
2417     { 10,       "INTERNAL_IP6_DNS" },
2418     { 11,       "INTERNAL_IP6_NBNS" },
2419     { 12,       "INTERNAL_IP6_DHCP" },
2420     { 13,       "INTERNAL_IP4_SUBNET" },
2421     { 14,       "SUPPORTED_ATTRIBUTES" },
2422     { 16520,    "XAUTH_TYPE" },
2423     { 16521,    "XAUTH_USER_NAME" },
2424     { 16522,    "XAUTH_USER_PASSWORD" },
2425     { 16523,    "XAUTH_PASSCODE" },
2426     { 16524,    "XAUTH_MESSAGE" },
2427     { 16525,    "XAUTH_CHALLANGE" },
2428     { 16526,    "XAUTH_DOMAIN" },
2429     { 16527,    "XAUTH_STATUS" },
2430     { 16528,    "XAUTH_NEXT_PIN" },
2431     { 16529,    "XAUTH_ANSWER" },
2432     { 0,        NULL },
2433   };
2434
2435   static const value_string vs_v2_cfgattr[] = {
2436     { 0,        "RESERVED" },
2437     { 1,        "INTERNAL_IP4_ADDRESS" },
2438     { 2,        "INTERNAL_IP4_NETMASK" },
2439     { 3,        "INTERNAL_IP4_DNS" },
2440     { 4,        "INTERNAL_IP4_NBNS" },
2441     { 5,        "INTERNAL_ADDRESS_EXPIREY" },
2442     { 6,        "INTERNAL_IP4_DHCP" },
2443     { 7,        "APPLICATION_VERSION" },
2444     { 8,        "INTERNAL_IP6_ADDRESS" },
2445     { 9,        "RESERVED" },
2446     { 10,       "INTERNAL_IP6_DNS" },
2447     { 11,       "INTERNAL_IP6_NBNS" },
2448     { 12,       "INTERNAL_IP6_DHCP" },
2449     { 13,       "INTERNAL_IP4_SUBNET" },
2450     { 14,       "SUPPORTED_ATTRIBUTES" },
2451     { 15,       "INTERNAL_IP6_SUBNET" },
2452     { 0,        NULL },
2453   };
2454
2455   if (isakmp_version == 1) {
2456     if (ident >= 15 && ident <= 16383)
2457       return "Future use";
2458     if (ident >= 16384 && ident <= 16519)
2459       return "PRIVATE USE";
2460     if (ident >= 16530 && ident <= 32767)
2461       return "PRIVATE USE";
2462     return val_to_str(ident, vs_v1_cfgattr, "UNKNOWN-CFG-ATTRIBUTE");
2463   } else if (isakmp_version == 2) {
2464     if (ident >= 16 && ident <= 16383)
2465       return "RESERVED TO IANA";
2466     if (ident >= 16384 && ident <= 32767)
2467       return "PRIVATE USE";
2468     return val_to_str(ident, vs_v2_cfgattr, "UNKNOWN-CFG-ATTRIBUTE");
2469   }
2470   return "UNKNOWN-ISAKMP-VERSION";
2471 }
2472
2473 static const char *
2474 certtype2str(int isakmp_version, guint8 type)
2475 {
2476   static const value_string vs_v1_certtype[] = {
2477     { 0,        "NONE" },
2478     { 1,        "PKCS #7 wrapped X.509 certificate" },
2479     { 2,        "PGP Certificate" },
2480     { 3,        "DNS Signed Key" },
2481     { 4,        "X.509 Certificate - Signature" },
2482     { 5,        "X.509 Certificate - Key Exchange" },
2483     { 6,        "Kerberos Tokens" },
2484     { 7,        "Certificate Revocation List (CRL)" },
2485     { 8,        "Authority Revocation List (ARL)" },
2486     { 9,        "SPKI Certificate" },
2487     { 10,       "X.509 Certificate - Attribute" },
2488     { 0,        NULL },
2489   };
2490
2491   static const value_string vs_v2_certtype[] = {
2492     { 0,        "RESERVED" },
2493     { 1,        "PKCS #7 wrapped X.509 certificate" },
2494     { 2,        "PGP Certificate" },
2495     { 3,        "DNS Signed Key" },
2496     { 4,        "X.509 Certificate - Signature" },
2497     { 5,        "*undefined by any document*" },
2498     { 6,        "Kerberos Tokens" },
2499     { 7,        "Certificate Revocation List (CRL)" },
2500     { 8,        "Authority Revocation List (ARL)" },
2501     { 9,        "SPKI Certificate" },
2502     { 10,       "X.509 Certificate - Attribute" },
2503     { 11,       "Raw RSA Key" },
2504     { 12,       "Hash and URL of X.509 certificate" },
2505     { 13,       "Hash and URL of X.509 bundle" },
2506     { 0,        NULL },
2507   };
2508
2509   if (isakmp_version == 1)
2510     return val_to_str(type, vs_v1_certtype, "RESERVED");
2511   else if (isakmp_version == 2) {
2512     if (type >= 14 && type <= 200)
2513       return "RESERVED to IANA";
2514     if (type >= 201)
2515       return "PRIVATE USE";
2516     return val_to_str(type, vs_v2_certtype, "RESERVED");
2517   }
2518   return "UNKNOWN-ISAKMP-VERSION";
2519 }
2520
2521 static gboolean
2522 get_num(tvbuff_t *tvb, int offset, guint16 len, guint32 *num_p)
2523 {
2524   switch (len) {
2525   case 1:
2526     *num_p = tvb_get_guint8(tvb, offset);
2527     break;
2528   case 2:
2529     *num_p = tvb_get_ntohs(tvb, offset);
2530     break;
2531   case 3:
2532     *num_p = tvb_get_ntoh24(tvb, offset);
2533     break;
2534   case 4:
2535     *num_p = tvb_get_ntohl(tvb, offset);
2536     break;
2537   default:
2538     return FALSE;
2539   }
2540
2541   return TRUE;
2542 }
2543
2544 void
2545 proto_register_isakmp(void)
2546 {
2547   static hf_register_info hf[] = {
2548     { &hf_ike_certificate_authority,
2549       { "Certificate Authority Distinguished Name", "ike.cert_authority_dn", FT_UINT32, BASE_DEC, NULL, 0x0, "Certificate Authority Distinguished Name", HFILL }
2550     },
2551     { &hf_ike_v2_certificate_authority,
2552       { "Certificate Authority", "ike.cert_authority", FT_BYTES, BASE_HEX, NULL, 0x0, "SHA-1 hash of the Certificate Authority", HFILL }
2553     },
2554     { &hf_ike_nat_keepalive,
2555       { "NAT Keepalive", "ike.nat_keepalive", FT_NONE, BASE_HEX, NULL, 0x0, "NAT Keepalive packet", HFILL }
2556     },
2557   };
2558   static gint *ett[] = {
2559     &ett_isakmp,
2560     &ett_isakmp_flags,
2561     &ett_isakmp_payload,
2562   };
2563
2564   proto_isakmp = proto_register_protocol("Internet Security Association and Key Management Protocol",
2565                                                "ISAKMP", "isakmp");
2566   proto_register_field_array(proto_isakmp, hf, array_length(hf));
2567   proto_register_subtree_array(ett, array_length(ett));
2568
2569   register_dissector("isakmp", dissect_isakmp, proto_isakmp);
2570 }
2571
2572 void
2573 proto_reg_handoff_isakmp(void)
2574 {
2575   dissector_handle_t isakmp_handle;
2576
2577   isakmp_handle = find_dissector("isakmp");
2578   dissector_add("udp.port", UDP_PORT_ISAKMP, isakmp_handle);
2579   dissector_add("tcp.port", TCP_PORT_ISAKMP, isakmp_handle);
2580 }