Fix for bug 875. Adding description for groups 19-26.
[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 #ifdef HAVE_LIBNETTLE
45 #ifdef _WIN32
46 #include <hmac.h>
47 #include <des.h>
48 #include <cbc.h>
49 #else
50 #include <nettle/hmac.h>
51 #include <nettle/des.h>
52 #include <nettle/cbc.h>
53 #endif
54 #include <epan/strutil.h>
55 #endif
56
57 #include <epan/packet.h>
58 #include <epan/ipproto.h>
59 #include <epan/dissectors/packet-x509if.h>
60 #include <epan/dissectors/packet-isakmp.h>
61 #include <epan/prefs.h>
62
63 #define isakmp_min(a, b)  ((a<b) ? a : b)
64
65 #define ARLEN(a) (sizeof(a)/sizeof(a[0]))
66
67 static int proto_isakmp = -1;
68 static int hf_ike_certificate_authority = -1;
69 static int hf_ike_v2_certificate_authority = -1;
70 static int hf_ike_nat_keepalive = -1;
71
72 static int hf_isakmp_icookie         = -1;
73 static int hf_isakmp_rcookie         = -1;
74 static int hf_isakmp_nextpayload     = -1;
75 static int hf_isakmp_version         = -1;
76 static int hf_isakmp_exchangetype    = -1;
77 static int hf_isakmp_flags           = -1;
78 static int hf_isakmp_messageid       = -1;
79 static int hf_isakmp_length          = -1;
80 static int hf_isakmp_payloadlen      = -1;
81 static int hf_isakmp_doi             = -1;
82 static int hf_isakmp_sa_situation    = -1;
83 static int hf_isakmp_prop_number     = -1;
84 static int hf_isakmp_spisize         = -1;
85 static int hf_isakmp_prop_transforms = -1;
86 static int hf_isakmp_trans_number    = -1;
87 static int hf_isakmp_trans_id        = -1;
88 static int hf_isakmp_id_type         = -1;
89 static int hf_isakmp_protoid         = -1;
90 static int hf_isakmp_id_port         = -1;
91 static int hf_isakmp_cert_encoding   = -1;
92 static int hf_isakmp_certreq_type    = -1;
93 static int hf_isakmp_notify_msgtype  = -1;
94 static int hf_isakmp_num_spis        = -1;
95
96 static gint ett_isakmp = -1;
97 static gint ett_isakmp_flags = -1;
98 static gint ett_isakmp_payload = -1;
99
100 /* IKE port number assigned by IANA */
101 #define UDP_PORT_ISAKMP 500
102 #define TCP_PORT_ISAKMP 500
103
104 /*
105  * Identifier Type
106  *   RFC2407 for IKEv1
107  *   draft-ietf-ipsec-ikev2-17.txt for IKEv2
108  */
109 #define IKE_ID_IPV4_ADDR                1
110 #define IKE_ID_FQDN                     2
111 #define IKE_ID_USER_FQDN                3
112 #define IKE_ID_IPV4_ADDR_SUBNET         4
113 #define IKE_ID_IPV6_ADDR                5
114 #define IKE_ID_IPV6_ADDR_SUBNET         6
115 #define IKE_ID_IPV4_ADDR_RANGE          7
116 #define IKE_ID_IPV6_ADDR_RANGE          8
117 #define IKE_ID_DER_ASN1_DN              9
118 #define IKE_ID_DER_ASN1_GN              10
119 #define IKE_ID_KEY_ID                   11
120
121 /*
122  * Traffic Selector Type
123  *   Not in use for IKEv1
124  */
125 #define IKEV2_TS_IPV4_ADDR_RANGE        7
126 #define IKEV2_TS_IPV6_ADDR_RANGE        8
127
128 static const value_string vs_proto[] = {
129   { 0,  "RESERVED" },
130   { 1,  "ISAKMP" },
131   { 2,  "IPSEC_AH" },
132   { 3,  "IPSEC_ESP" },
133   { 4,  "IPCOMP" },
134   { 0,  NULL },
135 };
136
137 #define COOKIE_SIZE 8
138
139 typedef struct isakmp_hdr {
140   guint8        next_payload;
141   guint8        version;
142   guint8        exch_type;
143   guint8        flags;
144 #define E_FLAG          0x01
145 #define C_FLAG          0x02
146 #define A_FLAG          0x04
147 #define I_FLAG          0x08
148 #define V_FLAG          0x10
149 #define R_FLAG          0x20
150   guint32       message_id;
151   guint32       length;
152 } isakmp_hdr_t;
153
154 #define ISAKMP_HDR_SIZE (sizeof(struct isakmp_hdr) + (2 * COOKIE_SIZE))
155
156 #define ENC_DES_CBC             1
157 #define ENC_IDEA_CBC            2
158 #define ENC_BLOWFISH_CBC        3
159 #define ENC_RC5_R16_B64_CBC     4
160 #define ENC_3DES_CBC            5
161 #define ENC_CAST_CBC            6
162 #define ENC_AES_CBC             7
163
164 #define HMAC_MD5        1
165 #define HMAC_SHA        2
166 #define HMAC_TIGER      3
167 #define HMAC_SHA2_256   4
168 #define HMAC_SHA2_384   5
169 #define HMAC_SHA2_512   6
170
171 #ifdef HAVE_LIBNETTLE
172
173 #define MAIN_MODE 2
174 #define AGGRESSIVE_MODE 4
175 #define MAX_KEY_SIZE 256
176 #define MAX_DIGEST_SIZE 64
177 #define MAX_OAKLEY_KEY_LEN 32
178
179 typedef struct decrypt_key {
180   guchar        secret[MAX_KEY_SIZE];
181   guint         secret_len;
182 } decrypt_key_t;
183
184 typedef struct iv_data {
185   guchar iv[MAX_DIGEST_SIZE];
186   guint  iv_len;
187   guint32 frame_num;
188 } iv_data_t;
189
190 typedef struct decrypt_data {
191   gboolean       is_psk;
192   address        initiator;
193   guint          encr_alg;
194   guint          hash_alg;
195   guint          group;
196   gchar         *gi;
197   guint          gi_len;
198   gchar         *gr;
199   guint          gr_len;
200   guchar         secret[MAX_KEY_SIZE];
201   guint          secret_len;
202   GList         *iv_list;
203   gchar          last_cbc[MAX_DIGEST_SIZE];
204   guint          last_cbc_len;
205   gchar          last_p1_cbc[MAX_DIGEST_SIZE];
206   guint          last_p1_cbc_len;
207   guint32        last_message_id;
208 } decrypt_data_t;
209
210 static GHashTable *isakmp_hash = NULL;
211 static GMemChunk *isakmp_key_data = NULL;
212 static GMemChunk *isakmp_decrypt_data = NULL;
213 static FILE *logf = NULL;
214 static const char *pluto_log_path = "insert pluto log path here";
215
216 static void
217 scan_pluto_log(void) {
218 #define MAX_PLUTO_LINE 500
219   decrypt_data_t *decr;
220   gchar    line[MAX_PLUTO_LINE];
221   guint8   i_cookie[COOKIE_SIZE], *ic_key;
222   gboolean got_cookie = FALSE;
223   guchar   secret[MAX_KEY_SIZE];
224   guint    secret_len = 0;
225   gchar   *icookie_pfx = "| ICOOKIE: ";
226   gchar   *enc_key_pfx = "| enc key: ";
227   gchar   *pos, *endpos;
228   gint     icpfx_len = strlen(icookie_pfx);
229   gint     ec_len = strlen(enc_key_pfx);
230   gint     i;
231   address  null_addr;
232   unsigned long hexval;
233
234   SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
235
236   if (logf) {
237     while (fgets(line, MAX_PLUTO_LINE, logf)) {
238       if (strncmp(line, icookie_pfx, icpfx_len) == 0) {
239         secret_len = 0;
240         pos = line + icpfx_len;
241         for (i = 0; i < COOKIE_SIZE; i++) {
242           hexval = strtoul(pos, &endpos, 16);
243           if (endpos == pos)
244             break;
245           i_cookie[i] = (guint8) hexval;
246           pos = endpos;
247         }
248         if (i == COOKIE_SIZE)
249           got_cookie = TRUE;
250       } else if (strncmp(line, enc_key_pfx, ec_len) == 0) {
251         pos = line + ec_len;
252         for (; secret_len < MAX_KEY_SIZE; secret_len++) {
253           hexval = strtoul(pos, &endpos, 16);
254           if (endpos == pos)
255             break;
256           secret[secret_len] = (guint8) hexval;
257           pos = endpos;
258         }
259       } else if (got_cookie && secret_len > 1) {
260         decr = (decrypt_data_t*) g_hash_table_lookup(isakmp_hash, i_cookie);
261
262         if (! decr) {
263           ic_key = g_mem_chunk_alloc(isakmp_key_data);
264           memcpy(ic_key, i_cookie, COOKIE_SIZE);
265           decr = g_mem_chunk_alloc(isakmp_decrypt_data);
266           memset(decr, 0, sizeof(decrypt_data_t));
267
268           g_hash_table_insert(isakmp_hash, ic_key, decr);
269         }
270
271         memcpy(decr->secret, secret, secret_len);
272         decr->secret_len = secret_len;
273       }
274     }
275   }
276 }
277
278 static void
279 set_transform_vals(decrypt_data_t *decr, int ike_p1, guint16 type, guint32 val) {
280   if (! ike_p1)
281     return;
282
283   if (decr != NULL) {
284     switch (type) {
285       case 1:
286         decr->encr_alg = val;
287         break;
288       case 2:
289         decr->hash_alg = val;
290         break;
291       case 3:
292         if (val == 1)
293           decr->is_psk = TRUE;
294         break;
295       case 4:
296         decr->group = val;
297         break;
298     }
299   }
300 }
301
302 static tvbuff_t *
303 decrypt_payload(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, const guint8 *buf, guint buf_len, isakmp_hdr_t *hdr) {
304   decrypt_data_t *decr = (decrypt_data_t *) pinfo->private_data;
305   gchar *decrypted_data = NULL;
306   struct md5_ctx m_ctx;
307   struct sha1_ctx s_ctx;
308   struct des3_ctx d3_ctx;
309   struct des_ctx d_ctx;
310   tvbuff_t *encr_tvb;
311   iv_data_t *ivd = NULL;
312   GList *ivl;
313   guchar iv[MAX_DIGEST_SIZE];
314   guint iv_len = 0;
315   guint32 message_id, cbc_block_size, digest_size;
316
317   if (!decr ||
318         decr->is_psk == FALSE ||
319         decr->gi_len == 0 ||
320         decr->gr_len == 0)
321     return NULL;
322
323   switch(decr->encr_alg) {
324     case ENC_3DES_CBC:
325       if (decr->secret_len < DES3_KEY_SIZE) return NULL;
326       cbc_block_size = DES_BLOCK_SIZE;
327       break;
328     case ENC_DES_CBC:
329       if (decr->secret_len < DES_KEY_SIZE) return NULL;
330       cbc_block_size = DES_BLOCK_SIZE;
331       break;
332     default:
333       return NULL;
334       break;
335   }
336
337   switch(decr->hash_alg) {
338     case HMAC_MD5:
339       digest_size = MD5_DIGEST_SIZE;
340       break;
341     case HMAC_SHA:
342       digest_size = SHA1_DIGEST_SIZE;
343       break;
344     default:
345       return NULL;
346       break;
347   }
348
349   for (ivl = g_list_first(decr->iv_list); ivl != NULL; ivl = g_list_next(ivl)) {
350     ivd = (iv_data_t *) ivl->data;
351     if (ivd->frame_num == pinfo->fd->num) {
352       iv_len = ivd->iv_len;
353       memcpy(iv, ivd->iv, iv_len);
354     }
355   }
356
357   /*
358    * Set our initialization vector as follows:
359    * - If the IV list is empty, assume we have the first packet in a phase 1
360    *   exchange.  The IV is built from DH values.
361    * - If our message ID changes, assume we're entering a new mode.  The IV
362    *   is built from the message ID and the last phase 1 CBC.
363    * - Otherwise, use the last CBC.
364    */
365   if (iv_len == 0) {
366     if (decr->iv_list == NULL) {
367       /* First packet */
368       ivd = g_malloc(sizeof(iv_data_t));
369       ivd->frame_num = pinfo->fd->num;
370       ivd->iv_len = digest_size;
371       decr->last_message_id = hdr->message_id;
372       if (decr->hash_alg == HMAC_MD5) {
373         md5_init(&m_ctx);
374         md5_update(&m_ctx, decr->gi_len, decr->gi);
375         md5_update(&m_ctx, decr->gr_len, decr->gr);
376         md5_digest(&m_ctx, MD5_DIGEST_SIZE, ivd->iv);
377       } else {
378         sha1_init(&s_ctx);
379         sha1_update(&s_ctx, decr->gi_len, decr->gi);
380         sha1_update(&s_ctx, decr->gr_len, decr->gr);
381         sha1_digest(&s_ctx, SHA1_DIGEST_SIZE, ivd->iv);
382       }
383       decr->iv_list = g_list_append(decr->iv_list, ivd);
384       iv_len = ivd->iv_len;
385       memcpy(iv, ivd->iv, iv_len);
386     } else if (decr->last_cbc_len >= cbc_block_size) {
387       ivd = g_malloc(sizeof(iv_data_t));
388       ivd->frame_num = pinfo->fd->num;
389       if (hdr->message_id != decr->last_message_id) {
390         if (decr->last_p1_cbc_len == 0) {
391           memcpy(decr->last_p1_cbc, decr->last_cbc, cbc_block_size);
392           decr->last_p1_cbc_len = cbc_block_size;
393         }
394         ivd->iv_len = digest_size;
395         decr->last_message_id = hdr->message_id;
396         message_id = g_htonl(decr->last_message_id);
397         if (decr->hash_alg == HMAC_MD5) {
398           md5_init(&m_ctx);
399           md5_update(&m_ctx, cbc_block_size, decr->last_p1_cbc);
400           md5_update(&m_ctx, sizeof(message_id), (unsigned char *) &message_id);
401           md5_digest(&m_ctx, MD5_DIGEST_SIZE, ivd->iv);
402         } else {
403           sha1_init(&s_ctx);
404           sha1_update(&s_ctx, cbc_block_size, decr->last_p1_cbc);
405           sha1_update(&s_ctx, sizeof(message_id), (unsigned char *) &message_id);
406           sha1_digest(&s_ctx, SHA1_DIGEST_SIZE, ivd->iv);
407         }
408       } else {
409         ivd->iv_len = cbc_block_size;
410         memcpy(ivd->iv, decr->last_cbc, ivd->iv_len);
411       }
412       decr->iv_list = g_list_append(decr->iv_list, ivd);
413       iv_len = ivd->iv_len;
414       memcpy(iv, ivd->iv, iv_len);
415     }
416   }
417
418   if (ivd == NULL) return NULL;
419
420   decrypted_data = g_malloc(buf_len);
421
422   if (decr->encr_alg = ENC_3DES_CBC) {
423     des_fix_parity(decr->secret_len, decr->secret, decr->secret);
424     des3_set_key(&d3_ctx, decr->secret);
425     cbc_decrypt(&d3_ctx, des3_decrypt, DES_BLOCK_SIZE, iv,
426         buf_len, decrypted_data, buf);
427   } else {
428     des_fix_parity(decr->secret_len, decr->secret, decr->secret);
429     des_set_key(&d_ctx, decr->secret);
430     cbc_decrypt(&d_ctx, des_decrypt, DES_BLOCK_SIZE, iv,
431         buf_len, decrypted_data, buf);
432   }
433
434   encr_tvb = tvb_new_real_data(decrypted_data, buf_len, buf_len);
435
436   tvb_set_child_real_data_tvbuff(tvb, encr_tvb);
437
438   /* Add the decrypted data to the data source list. */
439   add_new_data_source(pinfo, encr_tvb, "Decrypted IKE");
440
441   /* Fill in the next IV */
442   if (tvb_length(tvb) > cbc_block_size) {
443     decr->last_cbc_len = cbc_block_size;
444     memcpy(decr->last_cbc, iv, cbc_block_size);
445   } else {
446     decr->last_cbc_len = 0;
447   }
448
449   return encr_tvb;
450 }
451
452 #endif /* HAVE_LIBNETTLE */
453
454 static proto_tree *dissect_payload_header(tvbuff_t *, int, int, int, guint8,
455     guint8 *, guint16 *, proto_tree *);
456
457 static void dissect_sa(tvbuff_t *, int, int, proto_tree *,
458     packet_info *, int, int);
459 static void dissect_proposal(tvbuff_t *, int, int, proto_tree *,
460     packet_info *, int, int);
461 static void dissect_transform(tvbuff_t *, int, int, proto_tree *,
462     packet_info *, int, int);
463 static void dissect_transform2(tvbuff_t *, int, int, proto_tree *,
464     packet_info *, int, int);
465 static void dissect_key_exch(tvbuff_t *, int, int, proto_tree *,
466     packet_info *, int, int);
467 static void dissect_id(tvbuff_t *, int, int, proto_tree *,
468     packet_info *, int, int);
469 static void dissect_cert(tvbuff_t *, int, int, proto_tree *,
470     packet_info *, int, int);
471 static void dissect_certreq_v1(tvbuff_t *, int, int, proto_tree *,
472     packet_info *, int, int);
473 static void dissect_certreq_v2(tvbuff_t *, int, int, proto_tree *,
474     packet_info *, int, int);
475 static void dissect_hash(tvbuff_t *, int, int, proto_tree *,
476     packet_info *, int, int);
477 static void dissect_auth(tvbuff_t *, int, int, proto_tree *,
478     packet_info *, int, int);
479 static void dissect_sig(tvbuff_t *, int, int, proto_tree *,
480     packet_info *, int, int);
481 static void dissect_nonce(tvbuff_t *, int, int, proto_tree *,
482     packet_info *, int, int);
483 static void dissect_notif(tvbuff_t *, int, int, proto_tree *,
484     packet_info *, int, int);
485 static void dissect_delete(tvbuff_t *, int, int, proto_tree *,
486     packet_info *, int, int);
487 static void dissect_vid(tvbuff_t *, int, int, proto_tree *,
488     packet_info *, int, int);
489 static void dissect_config(tvbuff_t *, int, int, proto_tree *,
490     packet_info *, int, int);
491 static void dissect_nat_discovery(tvbuff_t *, int, int, proto_tree *,
492     packet_info *, int, int);
493 static void dissect_nat_original_address(tvbuff_t *, int, int, proto_tree *,
494     packet_info *, int, int);
495 static void dissect_ts(tvbuff_t *, int, int, proto_tree *,
496     packet_info *, int, int);
497 static void dissect_enc(tvbuff_t *, int, int, proto_tree *,
498     packet_info *, int, int);
499 static void dissect_eap(tvbuff_t *, int, int, proto_tree *,
500     packet_info *, int, int);
501
502 static void
503 dissect_payloads(tvbuff_t *tvb, proto_tree *tree, int isakmp_version,
504                  guint8 initial_payload, int offset, int length,
505                  packet_info *pinfo);
506
507
508 static const char *payloadtype2str(int, guint8);
509 static const char *exchtype2str(int, guint8);
510 static const char *doitype2str(guint32);
511 static const char *msgtype2str(int, guint16);
512 static const char *situation2str(guint32);
513 static const char *v1_attrval2str(int, guint16, guint32);
514 static const char *v2_attrval2str(guint16, guint32);
515 static const char *cfgtype2str(int, guint8);
516 static const char *cfgattr2str(int, guint16);
517 static const char *id2str(int, guint8);
518 static const char *v2_tstype2str(guint8);
519 static const char *v2_auth2str(guint8);
520 static const char *certtype2str(int, guint8);
521
522 static gboolean get_num(tvbuff_t *, int, guint16, guint32 *);
523
524 #define LOAD_TYPE_NONE          0       /* payload type for None */
525 #define LOAD_TYPE_PROPOSAL      2       /* payload type for Proposal */
526 #define LOAD_TYPE_TRANSFORM     3       /* payload type for Transform */
527
528 struct payload_func {
529   guint8 type;
530   const char *  str;
531   void (*func)(tvbuff_t *, int, int, proto_tree *, packet_info *, int, int);
532 };
533
534 static struct payload_func v1_plfunc[] = {
535   {  0, "NONE",                 NULL              },
536   {  1, "Security Association", dissect_sa        },
537   {  2, "Proposal",             dissect_proposal  },
538   {  3, "Transform",            dissect_transform },
539   {  4, "Key Exchange",         dissect_key_exch  },
540   {  5, "Identification",       dissect_id        },
541   {  6, "Certificate",          dissect_cert      },
542   {  7, "Certificate Request",  dissect_certreq_v1},
543   {  8, "Hash",                 dissect_hash      },
544   {  9, "Signature",            dissect_sig       },
545   { 10, "Nonce",                dissect_nonce     },
546   { 11, "Notification",         dissect_notif     },
547   { 12, "Delete",               dissect_delete    },
548   { 13, "Vendor ID",            dissect_vid       },
549   { 14, "Attrib",               dissect_config    },
550   { 15, "NAT-Discovery",        dissect_nat_discovery }, /* draft-ietf-ipsec-nat-t-ike-04 */
551   { 16, "NAT-Original Address", dissect_nat_original_address }, /* draft-ietf-ipsec-nat-t-ike */
552   { 20, "NAT-D (RFC 3947)",     dissect_nat_discovery },
553   { 21, "NAT-OA (RFC 3947)",    dissect_nat_original_address },
554   { 130, "NAT-D (draft-ietf-ipsec-nat-t-ike-01 to 03)",         dissect_nat_discovery },
555   { 131, "NAT-OA (draft-ietf-ipsec-nat-t-ike-01 to 04)",        dissect_nat_original_address },
556 };
557
558 static struct payload_func v2_plfunc[] = {
559   {  2, "Proposal",             dissect_proposal  },
560   {  3, "Transform",            dissect_transform2 },
561   { 33, "Security Association", dissect_sa        },
562   { 34, "Key Exchange",         dissect_key_exch  },
563   { 35, "Identification - I",   dissect_id        },
564   { 36, "Identification - R",   dissect_id        },
565   { 37, "Certificate",          dissect_cert      },
566   { 38, "Certificate Request",  dissect_certreq_v2},
567   { 39, "Authentication",       dissect_auth      },
568   { 40, "Nonce",                dissect_nonce     },
569   { 41, "Notification",         dissect_notif     },
570   { 42, "Delete",               dissect_delete    },
571   { 43, "Vendor ID",            dissect_vid       },
572   { 44, "Traffic Selector - I", dissect_ts       },
573   { 45, "Traffic Selector - R", dissect_ts       },
574   { 46, "Encrypted",            dissect_enc       },
575   { 47, "Configuration",        dissect_config    },
576   { 48, "Extensible Authentication",    dissect_eap       },
577 };
578
579 static struct payload_func * getpayload_func(guint8, int);
580
581 #define VID_LEN 16
582 #define VID_MS_LEN 20
583 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 */
584
585 #define VID_CP_LEN 20
586 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};
587
588 static const guint8 VID_CYBERGUARD[VID_LEN] = {0x9A, 0xA1, 0xF3, 0xB4, 0x34, 0x72, 0xA4, 0x5D, 0x5F, 0x50, 0x6A, 0xEB, 0x26, 0xC, 0xF2, 0x14};
589
590 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 */
591
592 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*/
593
594 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 */
595
596 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 */
597
598 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 */
599
600 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 */
601
602 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 */
603
604 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 */
605
606 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 */
607
608 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 */
609
610 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 */
611
612 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 */
613
614 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 */
615
616 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 */
617
618 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 */
619
620 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 */
621
622 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 */
623
624 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 */
625
626 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 */
627
628 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 */
629
630 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 */
631
632 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 */
633
634 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 */
635
636 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 */
637
638 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 */
639
640 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 */
641
642 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 */
643
644 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 */
645
646 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 */
647
648 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 */
649
650 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 */
651
652 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 */
653
654 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 */
655
656 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 */
657
658 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 */
659
660 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 */
661
662 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 */
663
664
665 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 */
666
667 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 */
668
669 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 */
670
671 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) */
672
673 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) */
674
675 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 */
676
677 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 */
678
679 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 */
680
681 static const guint8 VID_GSSAPI[VID_LEN]= {0x62, 0x1B, 0x04, 0xBB, 0x09, 0x88, 0x2A, 0xC1, 0xE1, 0x59, 0x35, 0xFE, 0xFA, 0x24, 0xAE, 0xEE}; /* GSSAPI */
682
683 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 */
684
685 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 */
686
687 #define VID_LEN_8 8
688 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 */
689
690 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 */
691
692 /*
693 *  Seen in Netscreen. Suppose to be ASCII HeartBeat_Notify - but I don't know the rest yet. I suspect it then proceeds with
694 *  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
695 *  means. ykaul-at-bezeqint.net
696 */
697 static const guint8 VID_HeartBeat_Notify[VID_LEN] = {0x48, 0x65, 0x61, 0x72, 0x74, 0x42, 0x65, 0x61, 0x74, 0x5f, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79};
698
699 void
700 isakmp_dissect_payloads(tvbuff_t *tvb, proto_tree *tree, int isakmp_version,
701                         guint8 initial_payload, int offset, int length,
702                         packet_info *pinfo)
703 {
704   dissect_payloads(tvb, tree, isakmp_version, initial_payload, offset, length,
705                    pinfo);
706 }
707
708 static void
709 dissect_payloads(tvbuff_t *tvb, proto_tree *tree, int isakmp_version,
710                  guint8 initial_payload, int offset, int length,
711                  packet_info *pinfo)
712 {
713   guint8 payload, next_payload;
714   guint16               payload_length;
715   proto_tree *          ntree;
716   struct payload_func * f;
717
718   for (payload = initial_payload; length > 0; payload = next_payload) {
719     if (payload == LOAD_TYPE_NONE) {
720       /*
721        * What?  There's more stuff in this chunk of data, but the
722        * previous payload had a "next payload" type of None?
723        */
724       proto_tree_add_text(tree, tvb, offset, length,
725                           "Extra data: %s",
726                           tvb_bytes_to_str(tvb, offset, length));
727       break;
728     }
729     ntree = dissect_payload_header(tvb, offset, length, isakmp_version,
730       payload, &next_payload, &payload_length, tree);
731     if (ntree == NULL)
732       break;
733     if (payload_length >= 4) {  /* XXX = > 4? */
734       tvb_ensure_bytes_exist(tvb, offset + 4, payload_length - 4);
735       if ((f = getpayload_func(payload, isakmp_version)) != NULL && f->func != NULL)
736         (*f->func)(tvb, offset + 4, payload_length - 4, ntree, pinfo,
737                    isakmp_version, -1);
738       else {
739         proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4,
740                             "Payload");
741       }
742     }
743     else if (payload_length > length) {
744         proto_tree_add_text(ntree, tvb, 0, 0,
745             "Payload (bogus, length is %u, greater than remaining length %d",
746             payload_length, length);
747         return;
748     }
749     else {
750         proto_tree_add_text(ntree, tvb, 0, 0,
751             "Payload (bogus, length is %u, must be at least 4)",
752             payload_length);
753         payload_length = 4;
754     }
755     offset += payload_length;
756     length -= payload_length;
757   }
758 }
759
760 static struct payload_func *
761 getpayload_func(guint8 payload, int isakmp_version)
762 {
763   struct payload_func *f = 0;
764   int i, len;
765
766   if (isakmp_version == 1) {
767     f = v1_plfunc;
768     len = ARLEN(v1_plfunc);
769   } else if (isakmp_version == 2) {
770     f = v2_plfunc;
771     len = ARLEN(v2_plfunc);
772   } else
773     return NULL;
774   for (i = 0; i < len; i++) {
775     if (f[i].type == payload)
776       return &f[i];
777   }
778   return NULL;
779 }
780
781 static void
782 dissect_isakmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
783 {
784   int                   offset = 0, len;
785   isakmp_hdr_t          hdr;
786   proto_item *          ti;
787   proto_tree *          isakmp_tree = NULL;
788   int                   isakmp_version;
789 #ifdef HAVE_LIBNETTLE
790   guint8                zeroes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
791   guint8                i_cookie[COOKIE_SIZE], *ic_key;
792   decrypt_data_t       *decr = NULL;
793   tvbuff_t             *decr_tvb;
794   proto_tree           *decr_tree;
795   void                 *pd = pinfo->private_data;
796   address               null_addr;
797 #endif /* HAVE_LIBNETTLE */
798
799   if (check_col(pinfo->cinfo, COL_PROTOCOL))
800     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISAKMP");
801   if (check_col(pinfo->cinfo, COL_INFO))
802     col_clear(pinfo->cinfo, COL_INFO);
803
804   if (tree) {
805     ti = proto_tree_add_item(tree, proto_isakmp, tvb, offset, -1, FALSE);
806     isakmp_tree = proto_item_add_subtree(ti, ett_isakmp);
807   }
808
809   /* RFC3948 2.3 NAT Keepalive packet:
810    * 1 byte payload with the value 0xff.
811    */
812   if( (tvb_length(tvb)==1) && (tvb_get_guint8(tvb, offset)==0xff) ){
813     if (check_col(pinfo->cinfo, COL_INFO)){
814       col_add_str(pinfo->cinfo, COL_INFO, "NAT Keepalive");
815     }
816     proto_tree_add_item(isakmp_tree, hf_ike_nat_keepalive, tvb, offset, 1, FALSE);
817     return;
818   }
819
820   hdr.length = tvb_get_ntohl(tvb, offset + ISAKMP_HDR_SIZE - sizeof(hdr.length));
821   hdr.exch_type = tvb_get_guint8(tvb, COOKIE_SIZE + COOKIE_SIZE + sizeof(hdr.next_payload) + sizeof(hdr.version));
822   hdr.version = tvb_get_guint8(tvb, COOKIE_SIZE + COOKIE_SIZE + sizeof(hdr.next_payload));
823   isakmp_version = hi_nibble(hdr.version);      /* save the version */
824   if (check_col(pinfo->cinfo, COL_INFO))
825     col_add_str(pinfo->cinfo, COL_INFO,
826                 exchtype2str(isakmp_version, hdr.exch_type));
827
828 #ifdef HAVE_LIBNETTLE
829   SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
830
831   tvb_memcpy(tvb, i_cookie, offset, COOKIE_SIZE);
832   decr = (decrypt_data_t*) g_hash_table_lookup(isakmp_hash, i_cookie);
833
834   if (! decr) {
835     ic_key = g_mem_chunk_alloc(isakmp_key_data);
836     memcpy(ic_key, i_cookie, COOKIE_SIZE);
837     decr = g_mem_chunk_alloc(isakmp_decrypt_data);
838     memset(decr, 0, sizeof(decrypt_data_t));
839     SET_ADDRESS(&decr->initiator, AT_NONE, 0, NULL);
840
841     g_hash_table_insert(isakmp_hash, ic_key, decr);
842   }
843
844   if (ADDRESSES_EQUAL(&decr->initiator, &null_addr)) {
845     /* XXX - We assume that we're seeing the second packet in an exchange here.
846      * Is there a way to verify this? */
847     COPY_ADDRESS(&decr->initiator, &pinfo->src);
848   }
849
850   pinfo->private_data = decr;
851 #endif /* HAVE_LIBNETTLE */
852
853   if (tree) {
854     proto_tree_add_item(isakmp_tree, hf_isakmp_icookie, tvb, offset, COOKIE_SIZE, FALSE);
855     offset += COOKIE_SIZE;
856
857     proto_tree_add_item(isakmp_tree, hf_isakmp_rcookie, tvb, offset, COOKIE_SIZE, FALSE);
858     offset += COOKIE_SIZE;
859
860     hdr.next_payload = tvb_get_guint8(tvb, offset);
861     proto_tree_add_uint_format(isakmp_tree, hf_isakmp_nextpayload, tvb, offset,
862                         sizeof(hdr.next_payload), hdr.next_payload,
863                         "Next payload: %s (%u)",
864                         payloadtype2str(isakmp_version, hdr.next_payload),
865                         hdr.next_payload);
866     offset += sizeof(hdr.next_payload);
867
868     proto_tree_add_uint_format(isakmp_tree, hf_isakmp_version, tvb, offset,
869                         sizeof(hdr.version), hdr.version, "Version: %u.%u",
870                         hi_nibble(hdr.version), lo_nibble(hdr.version));
871     offset += sizeof(hdr.version);
872
873     hdr.exch_type = tvb_get_guint8(tvb, offset);
874     proto_tree_add_uint_format(isakmp_tree, hf_isakmp_exchangetype, tvb, offset,
875                         sizeof(hdr.exch_type), hdr.exch_type,
876                         "Exchange type: %s (%u)",
877                         exchtype2str(isakmp_version, hdr.exch_type),
878                         hdr.exch_type);
879     offset += sizeof(hdr.exch_type);
880
881     {
882       proto_item *      fti;
883       proto_tree *      ftree;
884
885       hdr.flags = tvb_get_guint8(tvb, offset);
886       fti   = proto_tree_add_item(isakmp_tree, hf_isakmp_flags, tvb, offset, sizeof(hdr.flags), FALSE);
887       ftree = proto_item_add_subtree(fti, ett_isakmp_flags);
888
889       if (isakmp_version == 1) {
890         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
891                           decode_boolean_bitfield(hdr.flags, E_FLAG, sizeof(hdr.flags)*8,
892                                                   "Encrypted", "Not encrypted"));
893         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
894                           decode_boolean_bitfield(hdr.flags, C_FLAG, sizeof(hdr.flags)*8,
895                                                   "Commit", "No commit"));
896         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
897                           decode_boolean_bitfield(hdr.flags, A_FLAG, sizeof(hdr.flags)*8,
898                                                   "Authentication", "No authentication"));
899       } else if (isakmp_version == 2) {
900         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
901                           decode_boolean_bitfield(hdr.flags, I_FLAG, sizeof(hdr.flags)*8,
902                                                   "Initiator", "Responder"));
903         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
904                           decode_boolean_bitfield(hdr.flags, V_FLAG, sizeof(hdr.flags)*8,
905                                                   "A higher version enabled", ""));
906         proto_tree_add_text(ftree, tvb, offset, 1, "%s",
907                           decode_boolean_bitfield(hdr.flags, R_FLAG, sizeof(hdr.flags)*8,
908                                                   "Response", "Request"));
909       }
910       offset += sizeof(hdr.flags);
911     }
912
913     hdr.message_id = tvb_get_ntohl(tvb, offset);
914     proto_tree_add_item(isakmp_tree, hf_isakmp_messageid, tvb, offset, sizeof(hdr.message_id), FALSE);
915     offset += sizeof(hdr.message_id);
916
917     if (hdr.length < ISAKMP_HDR_SIZE) {
918         proto_tree_add_uint_format(isakmp_tree, hf_isakmp_length, tvb, offset, sizeof(hdr.length),
919                             hdr.length, "Length: (bogus, length is %u, should be at least %lu)",
920                             hdr.length, (unsigned long)ISAKMP_HDR_SIZE);
921         return;
922     }
923
924     len = hdr.length - ISAKMP_HDR_SIZE;
925
926     if (len < 0) {
927         proto_tree_add_uint_format(isakmp_tree, hf_isakmp_length, tvb, offset, sizeof(hdr.length),
928                             hdr.length, "Length: (bogus, length is %u, which is too large)",
929                             hdr.length);
930         return;
931     }
932
933     proto_tree_add_item(isakmp_tree, hf_isakmp_length, tvb, offset, sizeof(hdr.length), FALSE);
934     offset += sizeof(hdr.length);
935
936     if (hdr.flags & E_FLAG) {
937       if (len && isakmp_tree) {
938         ti = proto_tree_add_text(isakmp_tree, tvb, offset, len,
939                         "Encrypted payload (%d byte%s)",
940                         len, plurality(len, "", "s"));
941 #ifdef HAVE_LIBNETTLE
942
943         if (decr) {
944           decr_tvb = decrypt_payload(isakmp_tree, tvb, pinfo, tvb_get_ptr(tvb, offset, len), len, &hdr);
945           if (decr_tvb) {
946             decr_tree = proto_item_add_subtree(ti, ett_isakmp);
947             dissect_payloads(decr_tvb, decr_tree, isakmp_version, hdr.next_payload,
948                        0, tvb_length(decr_tvb), pinfo);
949           }
950         }
951 #endif /* HAVE_LIBNETTLE */
952       }
953     } else
954       dissect_payloads(tvb, isakmp_tree, isakmp_version, hdr.next_payload,
955                        offset, len, pinfo);
956   }
957 }
958
959 static proto_tree *
960 dissect_payload_header(tvbuff_t *tvb, int offset, int length,
961     int isakmp_version, guint8 payload, guint8 *next_payload_p,
962     guint16 *payload_length_p, proto_tree *tree)
963 {
964   guint8                next_payload;
965   guint16               payload_length;
966   proto_item *          ti;
967   proto_tree *          ntree;
968
969   if (length < 4) {
970     proto_tree_add_text(tree, tvb, offset, length,
971           "Not enough room in payload for all transforms");
972     return NULL;
973   }
974   next_payload = tvb_get_guint8(tvb, offset);
975   payload_length = tvb_get_ntohs(tvb, offset + 2);
976
977   ti = proto_tree_add_text(tree, tvb, offset, payload_length,
978             "%s payload", payloadtype2str(isakmp_version, payload));
979   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
980
981   proto_tree_add_uint_format(ntree, hf_isakmp_nextpayload, tvb, offset, 1,
982                         next_payload, "Next payload: %s (%u)",
983                         payloadtype2str(isakmp_version, next_payload),
984                         next_payload);
985   if (isakmp_version == 2) {
986     proto_tree_add_text(ntree, tvb, offset + 1, 1, "%s",
987                 decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 1), 0x80,
988                 8, "Critical", "Not critical"));
989   }
990   proto_tree_add_item(ntree, hf_isakmp_payloadlen, tvb, offset + 2, 2, FALSE);
991
992   *next_payload_p = next_payload;
993   *payload_length_p = payload_length;
994   return ntree;
995 }
996
997 static void
998 dissect_sa(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
999     packet_info *pinfo, int isakmp_version, int unused _U_)
1000 {
1001   guint32               doi;
1002   guint32               situation;
1003
1004   if (length < 4) {
1005     proto_tree_add_text(tree, tvb, offset, length,
1006                         "DOI %s (length is %u, should be >= 4)",
1007                         tvb_bytes_to_str(tvb, offset, length), length);
1008     return;
1009   }
1010   if (isakmp_version == 1) {
1011     doi = tvb_get_ntohl(tvb, offset);
1012     proto_tree_add_uint_format(tree, hf_isakmp_doi, tvb, offset, 4,
1013                         doi, "Domain of interpretation: %s (%u)",
1014                         doitype2str(doi), doi);
1015     offset += 4;
1016     length -= 4;
1017
1018     if (doi == 1) {
1019       /* IPSEC */
1020       if (length < 4) {
1021         proto_tree_add_bytes_format(tree, hf_isakmp_sa_situation, tvb, offset, length,
1022                           tvb_get_ptr(tvb, offset, length),
1023                           "Situation: %s (length is %u, should be >= 4)",
1024                           tvb_bytes_to_str(tvb, offset, length), length);
1025         return;
1026       }
1027       situation = tvb_get_ntohl(tvb, offset);
1028       proto_tree_add_bytes_format(tree, hf_isakmp_sa_situation, tvb, offset, 4,
1029                         tvb_get_ptr(tvb, offset, 4), "Situation: %s (%u)",
1030                         situation2str(situation), situation);
1031       offset += 4;
1032       length -= 4;
1033
1034       dissect_payloads(tvb, tree, isakmp_version, LOAD_TYPE_PROPOSAL, offset,
1035                        length, pinfo);
1036     } else {
1037       /* Unknown */
1038       proto_tree_add_item(tree, hf_isakmp_sa_situation, tvb, offset, length, FALSE);
1039     }
1040   } else if (isakmp_version == 2) {
1041     dissect_payloads(tvb, tree, isakmp_version, LOAD_TYPE_PROPOSAL, offset,
1042                      length, pinfo);
1043   }
1044 }
1045
1046 static void
1047 dissect_proposal(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1048     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1049 {
1050   guint8                protocol_id;
1051   guint8                spi_size;
1052   guint8                num_transforms;
1053   guint8                next_payload;
1054   guint16               payload_length;
1055   proto_tree *          ntree;
1056   guint8                proposal_num;
1057
1058   proposal_num = tvb_get_guint8(tvb, offset);
1059
1060   proto_item_append_text(tree, " # %d", proposal_num);
1061
1062   proto_tree_add_item(tree, hf_isakmp_prop_number, tvb, offset, 1, FALSE);
1063   offset += 1;
1064   length -= 1;
1065
1066   protocol_id = tvb_get_guint8(tvb, offset);
1067   proto_tree_add_uint_format(tree, hf_isakmp_protoid, tvb, offset, 1,
1068                         protocol_id, "Protocol ID: %s (%u)",
1069                         val_to_str(protocol_id, vs_proto, "UNKNOWN-PROTO-TYPE"), protocol_id);
1070   offset += 1;
1071   length -= 1;
1072
1073   spi_size = tvb_get_guint8(tvb, offset);
1074   proto_tree_add_item(tree, hf_isakmp_spisize, tvb, offset, 1, FALSE);
1075   offset += 1;
1076   length -= 1;
1077
1078   num_transforms = tvb_get_guint8(tvb, offset);
1079   proto_tree_add_item(tree, hf_isakmp_prop_transforms, tvb, offset, 1, FALSE);
1080   offset += 1;
1081   length -= 1;
1082
1083   if (spi_size) {
1084     proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: 0x%s",
1085                         tvb_bytes_to_str(tvb, offset, spi_size));
1086     offset += spi_size;
1087     length -= spi_size;
1088   }
1089
1090   while (num_transforms > 0) {
1091     ntree = dissect_payload_header(tvb, offset, length, isakmp_version,
1092       LOAD_TYPE_TRANSFORM, &next_payload, &payload_length, tree);
1093     if (ntree == NULL)
1094       break;
1095     if (length < payload_length) {
1096       proto_tree_add_text(tree, tvb, offset + 4, length,
1097           "Not enough room in payload for all transforms");
1098       break;
1099     }
1100     if (payload_length >= 4) {
1101       if (isakmp_version == 1)
1102         dissect_transform(tvb, offset + 4, payload_length - 4, ntree,
1103                         pinfo, isakmp_version, protocol_id);
1104       else if (isakmp_version == 2)
1105         dissect_transform2(tvb, offset + 4, payload_length - 4, ntree,
1106                         pinfo, isakmp_version, protocol_id);
1107     }
1108     else
1109       proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4, "Payload");
1110     offset += payload_length;
1111     length -= payload_length;
1112     num_transforms--;
1113   }
1114 }
1115
1116 static void
1117 dissect_transform(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1118     packet_info *pinfo _U_, int isakmp_version _U_, int protocol_id)
1119 {
1120   static const value_string vs_v1_attr[] = {
1121     { 1,        "Encryption-Algorithm" },
1122     { 2,        "Hash-Algorithm" },
1123     { 3,        "Authentication-Method" },
1124     { 4,        "Group-Description" },
1125     { 5,        "Group-Type" },
1126     { 6,        "Group-Prime" },
1127     { 7,        "Group-Generator-One" },
1128     { 8,        "Group-Generator-Two" },
1129     { 9,        "Group-Curve-A" },
1130     { 10,       "Group-Curve-B" },
1131     { 11,       "Life-Type" },
1132     { 12,       "Life-Duration" },
1133     { 13,       "PRF" },
1134     { 14,       "Key-Length" },
1135     { 15,       "Field-Size" },
1136     { 16,       "Group-Order" },
1137     { 0,        NULL },
1138   };
1139
1140   static const value_string vs_v2_sttr[] = {
1141     { 1,        "SA-Life-Type" },
1142     { 2,        "SA-Life-Duration" },
1143     { 3,        "Group-Description" },
1144     { 4,        "Encapsulation-Mode" },
1145     { 5,        "Authentication-Algorithm" },
1146     { 6,        "Key-Length" },
1147     { 7,        "Key-Rounds" },
1148     { 8,        "Compress-Dictinary-Size" },
1149     { 9,        "Compress-Private-Algorithm" },
1150     { 10,       "ECN Tunnel" },
1151     { 0,        NULL },
1152   };
1153
1154   static const value_string vs_v1_trans_isakmp[] = {
1155     { 0,        "RESERVED" },
1156     { 1,        "KEY_IKE" },
1157     { 0,        NULL },
1158   };
1159
1160   static const value_string vs_v1_trans_ah[] = {
1161     { 0,        "RESERVED" },
1162     { 1,        "RESERVED" },
1163     { 2,        "MD5" },
1164     { 3,        "SHA" },
1165     { 4,        "DES" },
1166     { 5,        "SHA2-256" },
1167     { 6,        "SHA2-384" },
1168     { 7,        "SHA2-512" },
1169     { 0,        NULL },
1170   };
1171
1172   static const value_string vs_v1_trans_esp[] = {
1173     { 0,        "RESERVED" },
1174     { 1,        "DES-IV64" },
1175     { 2,        "DES" },
1176     { 3,        "3DES" },
1177     { 4,        "RC5" },
1178     { 5,        "IDEA" },
1179     { 6,        "CAST" },
1180     { 7,        "BLOWFISH" },
1181     { 8,        "3IDEA" },
1182     { 9,        "DES-IV32" },
1183     { 10,       "RC4" },
1184     { 11,       "NULL" },
1185     { 12,       "AES" },
1186     { 0,        NULL },
1187   };
1188
1189   static const value_string vs_v1_trans_ipcomp[] = {
1190     { 0,        "RESERVED" },
1191     { 1,        "OUI" },
1192     { 2,        "DEFLATE" },
1193     { 3,        "LZS" },
1194     { 4,        "LZJH" },
1195     { 0,        NULL },
1196   };
1197
1198   guint8                transform_id;
1199   guint8                transform_num;
1200 #ifdef HAVE_LIBNETTLE
1201   decrypt_data_t *decr = (decrypt_data_t *) pinfo->private_data;
1202 #endif /* HAVE_LIBNETTLE */
1203
1204   transform_num = tvb_get_guint8(tvb, offset);
1205   proto_item_append_text(tree," # %d",transform_num);
1206   proto_tree_add_item(tree, hf_isakmp_trans_number, tvb, offset, 1, FALSE);
1207   offset += 1;
1208   length -= 1;
1209
1210   transform_id = tvb_get_guint8(tvb, offset);
1211   switch (protocol_id) {
1212   default:
1213     proto_tree_add_item(tree, hf_isakmp_trans_id, tvb, offset, 1, FALSE);
1214     break;
1215   case 1:       /* ISAKMP */
1216     proto_tree_add_uint_format(tree, hf_isakmp_trans_id, tvb, offset, 1,
1217                         transform_id, "Transform ID: %s (%u)",
1218                         val_to_str(transform_id, vs_v1_trans_isakmp, "UNKNOWN-TRANS-TYPE"), transform_id);
1219     break;
1220   case 2:       /* AH */
1221     proto_tree_add_uint_format(tree, hf_isakmp_trans_id, tvb, offset, 1,
1222                         transform_id, "Transform ID: %s (%u)",
1223                         val_to_str(transform_id, vs_v1_trans_ah, "UNKNOWN-AH-TRANS-TYPE"), transform_id);
1224     break;
1225   case 3:       /* ESP */
1226     proto_tree_add_uint_format(tree, hf_isakmp_trans_id, tvb, offset, 1,
1227                         transform_id, "Transform ID: %s (%u)",
1228                         val_to_str(transform_id, vs_v1_trans_esp, "UNKNOWN-ESP-TRANS-TYPE"), transform_id);
1229     break;
1230   case 4:       /* IPCOMP */
1231     proto_tree_add_uint_format(tree, hf_isakmp_trans_id, tvb, offset, 1,
1232                         transform_id, "Transform ID: %s (%u)",
1233                         val_to_str(transform_id, vs_v1_trans_ipcomp, "UNKNOWN-IPCOMP-TRANS-TYPE"), transform_id);
1234     break;
1235   }
1236   offset += 3;
1237   length -= 3;
1238
1239   while (length>0) {
1240     const char *str;
1241     int ike_phase1 = 0;
1242     guint16 aft     = tvb_get_ntohs(tvb, offset);
1243     guint16 type    = aft & 0x7fff;
1244     guint16 len;
1245     guint32 val;
1246     guint pack_len;
1247
1248     /* XXX - Add header fields */
1249     if (protocol_id == 1 && transform_id == 1) {
1250       ike_phase1 = 1;
1251       str = val_to_str(type, vs_v1_attr, "UNKNOWN-ATTRIBUTE-TYPE");
1252     }
1253     else {
1254       str = val_to_str(type, vs_v2_sttr, "UNKNOWN-ATTRIBUTE-TYPE");
1255     }
1256
1257     if (aft & 0x8000) {
1258       val = tvb_get_ntohs(tvb, offset + 2);
1259       proto_tree_add_text(tree, tvb, offset, 4,
1260                           "%s (%u): %s (%u)",
1261                           str, type,
1262                           v1_attrval2str(ike_phase1, type, val), val);
1263 #ifdef HAVE_LIBNETTLE
1264       set_transform_vals(decr, ike_phase1, type, val);
1265 #endif
1266       offset += 4;
1267       length -= 4;
1268     }
1269     else {
1270       len = tvb_get_ntohs(tvb, offset + 2);
1271       pack_len = 4 + len;
1272       if (!get_num(tvb, offset + 4, len, &val)) {
1273         proto_tree_add_text(tree, tvb, offset, pack_len,
1274                             "%s (%u): <too big (%u bytes)>",
1275                             str, type, len);
1276       } else {
1277         proto_tree_add_text(tree, tvb, offset, pack_len,
1278                             "%s (%u): %s (%u)",
1279                             str, type,
1280                             v1_attrval2str(ike_phase1, type, val), val);
1281 #ifdef HAVE_LIBNETTLE
1282         set_transform_vals(decr, ike_phase1, type, val);
1283 #endif
1284       }
1285       offset += pack_len;
1286       length -= pack_len;
1287     }
1288   }
1289 }
1290
1291 /* For Transform Type 1 (Encryption Algorithm), defined Transform IDs */
1292 static const char *
1293 v2_tid2encstr(guint16 tid)
1294 {
1295   static const value_string vs_v2_trans_enc[] = {
1296     { 0,        "RESERVED" },
1297     { 1,        "ENCR_DES_IV64" },
1298     { 2,        "ENCR_DES" },
1299     { 3,        "ENCR_3DE" },
1300     { 4,        "ENCR_RC5" },
1301     { 5,        "ENCR_IDEA" },
1302     { 6,        "ENCR_CAST" },
1303     { 7,        "ENCR_BLOWFISH" },
1304     { 8,        "ENCR_3IDEA" },
1305     { 9,        "ENCR_DES_IV32" },
1306     { 10,       "RESERVED" },
1307     { 11,       "ENCR_NULL" },
1308     { 12,       "ENCR_AES_CBC" },
1309     { 13,       "ENCR_AES_CTR" },
1310     { 0,        NULL },
1311   };
1312
1313   return val_to_str(tid, vs_v2_trans_enc, "UNKNOWN-ENC-ALG");
1314 }
1315
1316 /* For Transform Type 2 (Pseudo-random Function), defined Transform IDs */
1317 static const char *
1318 v2_tid2prfstr(guint16 tid)
1319 {
1320   static const value_string vs_v2_trans_prf[] = {
1321     { 0,        "RESERVED" },
1322     { 1,        "PRF_HMAC_MD5" },
1323     { 2,        "PRF_HMAC_SHA1" },
1324     { 3,        "PRF_HMAC_TIGER" },
1325     { 4,        "PRF_AES128_CBC" },
1326     { 0,        NULL },
1327   };
1328   return val_to_str(tid, vs_v2_trans_prf, "UNKNOWN-PRF");
1329 }
1330
1331 /* For Transform Type 3 (Integrity Algorithm), defined Transform IDs */
1332 static const char *
1333 v2_tid2iastr(guint16 tid)
1334 {
1335   static const value_string vs_v2_trans_integrity[] = {
1336     { 0,        "NONE" },
1337     { 1,        "AUTH_HMAC_MD5_96" },
1338     { 2,        "AUTH_HMAC_SHA1_96" },
1339     { 3,        "AUTH_DES_MAC" },
1340     { 4,        "AUTH_KPDK_MD5" },
1341     { 5,        "AUTH_AES_XCBC_96" },
1342     { 0,        NULL },
1343   };
1344   return val_to_str(tid, vs_v2_trans_integrity, "UNKNOWN-INTEGRITY-ALG");
1345 }
1346
1347 /* For Transform Type 4 (Diffie-Hellman Group), defined Transform IDs */
1348 static const char *
1349 v2_tid2dhstr(guint16 tid)
1350 {
1351   static const value_string vs_v2_trans_dhgroup[] = {
1352     {  0,       "NONE" },
1353     {  1,       "Group 1 - 768 Bit MODP" },
1354     {  2,       "Group 2 - 1024 Bit MODP" },
1355     {  3,       "RESERVED" },
1356     {  4,       "RESERVED" },
1357     {  5,       "group 5 - 1536 Bit MODP" },
1358     { 14,       "2048-bit MODP Group" },
1359     { 15,       "3072-bit MODP Group" },
1360     { 16,       "4096-bit MODP Group" },
1361     { 17,       "6144-bit MODP Group" },
1362     { 18,       "8192-bit MODP Group" },
1363     { 0,        NULL },
1364   };
1365
1366   if ((tid >= 6 && tid <= 13) || (tid >= 19 && tid <= 1023))
1367     return "RESERVED TO IANA";
1368   if (tid >= 1024)
1369     return "PRIVATE USE";
1370   return val_to_str(tid, vs_v2_trans_dhgroup, "UNKNOWN-DH-GROUP");
1371 }
1372
1373 /* For Transform Type 5 (Extended Sequence Numbers), defined Transform */
1374 static const char *
1375 v2_tid2esnstr(guint16 tid)
1376 {
1377   static const value_string vs_v2_trans_esn[] = {
1378     { 0,        "No Extended Sequence Numbers" },
1379     { 1,        "Extended Sequence Numbers" },
1380     { 0,        NULL },
1381   };
1382
1383   return val_to_str(tid, vs_v2_trans_esn, "UNKNOWN-ESN-TYPE");
1384 }
1385
1386 static struct {
1387   const gint8 type;
1388   const char *str;
1389   const char *(*func)(guint16);
1390 } v2_tid_func[] = {
1391   { 0,  "RESERVED", NULL, },
1392   { 1,  "Encryption Algorithm (ENCR)", v2_tid2encstr },
1393   { 2,  "Pseudo-random Function (PRF)", v2_tid2prfstr },
1394   { 3,  "Integrity Algorithm (INTEG)", v2_tid2iastr },
1395   { 4,  "Diffie-Hellman Group (D-H)", v2_tid2dhstr },
1396   { 5,  "Extended Sequence Numbers (ESN)", v2_tid2esnstr },
1397 };
1398
1399 static const char *
1400 v2_trans2str(guint8 type)
1401 {
1402   if (type < ARLEN(v2_tid_func)) return v2_tid_func[type].str;
1403   if (type < 240) return "RESERVED TO IANA";
1404   return "PRIVATE USE";
1405 }
1406
1407 static const char *
1408 v2_tid2str(guint8 type, guint16 tid)
1409 {
1410   if (type < ARLEN(v2_tid_func) && v2_tid_func[type].func != NULL) {
1411     return (v2_tid_func[type].func)(tid);
1412   }
1413   return "RESERVED";
1414 }
1415
1416 static const char *
1417 v2_aft2str(guint16 aft)
1418 {
1419     if (aft < 14 || (aft > 14 && aft < 18)) return "RESERVED";
1420     if (aft == 14) return "Key Length (in bits)";
1421     if (aft >= 18 && aft < 16384) return "RESERVED TO IANA";
1422     return "PRIVATE USE";
1423 }
1424
1425 static void
1426 dissect_transform2(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1427     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1428 {
1429   guint8 transform_type;
1430   guint16 transform_id;
1431
1432   transform_type = tvb_get_guint8(tvb, offset);
1433   proto_tree_add_text(tree, tvb, offset, 1,
1434     "Transform type: %s (%u)", v2_trans2str(transform_type), transform_type);
1435   offset += 2;
1436   length -= 2;
1437
1438   transform_id = tvb_get_ntohs(tvb, offset);
1439   proto_tree_add_text(tree, tvb, offset, 2,
1440     "Transform ID: %s (%u)", v2_tid2str(transform_type, transform_id),
1441     transform_id);
1442   offset += 2;
1443   length -= 2;
1444
1445   while (length>0) {
1446     const char *str;
1447     guint16 aft     = tvb_get_ntohs(tvb, offset);
1448     guint16 type    = aft & 0x7fff;
1449     guint16 len;
1450     guint32 val;
1451     guint pack_len;
1452
1453     str = v2_aft2str(aft);
1454
1455     if (aft & 0x8000) {
1456       val = tvb_get_ntohs(tvb, offset + 2);
1457       proto_tree_add_text(tree, tvb, offset, 4,
1458                           "%s (%u): %s (%u)",
1459                           str, type,
1460                           v2_attrval2str(type, val), val);
1461       offset += 4;
1462       length -= 4;
1463     }
1464     else {
1465       len = tvb_get_ntohs(tvb, offset + 2);
1466       pack_len = 4 + len;
1467       if (!get_num(tvb, offset + 4, len, &val)) {
1468         proto_tree_add_text(tree, tvb, offset, pack_len,
1469                             "%s (%u): <too big (%u bytes)>",
1470                             str, type, len);
1471       } else {
1472         proto_tree_add_text(tree, tvb, offset, pack_len,
1473                             "%s (%u): %s (%u)",
1474                             str, type,
1475                             v2_attrval2str(type, val), val);
1476       }
1477       offset += pack_len;
1478       length -= pack_len;
1479     }
1480   }
1481 }
1482
1483 static void
1484 dissect_key_exch(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1485     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1486 {
1487   guint16 dhgroup;
1488 #ifdef HAVE_LIBNETTLE
1489   decrypt_data_t *decr = (decrypt_data_t *) pinfo->private_data;
1490 #endif /* HAVE_LIBNETTLE */
1491
1492   if (isakmp_version == 2) {
1493     dhgroup = tvb_get_ntohs(tvb, offset);
1494     proto_tree_add_text(tree, tvb, offset, 2,
1495                       "DH Group #: %u", dhgroup);
1496     offset += 4;
1497     length -= 4;
1498   }
1499
1500   proto_tree_add_text(tree, tvb, offset, length, "Key Exchange Data (%d bytes / %d bits)",
1501         length, length * 8);
1502
1503 #ifdef HAVE_LIBNETTLE
1504   if (decr && decr->gi_len == 0 && ADDRESSES_EQUAL(&decr->initiator, &pinfo->src)) {
1505     decr->gi = g_malloc(length);
1506     tvb_memcpy(tvb, decr->gi, offset, length);
1507     decr->gi_len = length;
1508   } else if (decr && decr->gr_len == 0 && !ADDRESSES_EQUAL(&decr->initiator, &pinfo->src)) {
1509     decr->gr = g_malloc(length);
1510     tvb_memcpy(tvb, decr->gr, offset, length);
1511     decr->gr_len = length;
1512   }
1513 #endif /* HAVE_LIBNETTLE */
1514 }
1515
1516 static void
1517 dissect_id(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1518     packet_info *pinfo, int isakmp_version, int unused _U_)
1519 {
1520   guint8                id_type;
1521   guint8                protocol_id;
1522   guint16               port;
1523
1524   id_type = tvb_get_guint8(tvb, offset);
1525   proto_tree_add_item(tree, hf_isakmp_id_type, tvb, offset, 1, FALSE);
1526   proto_tree_add_text(tree, tvb, offset, 1,
1527                       "ID type: %s (%u)",
1528                       id2str(isakmp_version, id_type), id_type);
1529   offset += 1;
1530   length -= 1;
1531
1532   protocol_id = tvb_get_guint8(tvb, offset);
1533   if (protocol_id == 0) {
1534     proto_tree_add_uint_format(tree, hf_isakmp_protoid, tvb, offset, 1,
1535                         protocol_id, "Protocol ID: Unused");
1536   } else {
1537     proto_tree_add_uint_format(tree, hf_isakmp_protoid, tvb, offset, 1,
1538                         protocol_id, "Protocol ID: %s (%u)",
1539                         ipprotostr(protocol_id), protocol_id);
1540   }
1541   offset += 1;
1542   length -= 1;
1543
1544   port = tvb_get_ntohs(tvb, offset);
1545   if (port == 0)
1546     proto_tree_add_uint_format(tree, hf_isakmp_id_port, tvb, offset, 2,
1547                         port, "Port: Unused");
1548   else
1549     proto_tree_add_item(tree, hf_isakmp_id_port, tvb, offset, 2, FALSE);
1550   offset += 2;
1551   length -= 2;
1552
1553   /*
1554    * It shows strings of all types though some of types are not
1555    * supported in IKEv2 specification actually.
1556    */
1557   switch (id_type) {
1558     case IKE_ID_IPV4_ADDR:
1559       proto_tree_add_text(tree, tvb, offset, length,
1560                           "Identification data: %s",
1561                           ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1562       break;
1563     case IKE_ID_FQDN:
1564     case IKE_ID_USER_FQDN:
1565       proto_tree_add_text(tree, tvb, offset, length,
1566                           "Identification data: %.*s", length,
1567                           tvb_get_ptr(tvb, offset, length));
1568       break;
1569     case IKE_ID_IPV4_ADDR_SUBNET:
1570     case IKE_ID_IPV4_ADDR_RANGE:
1571       proto_tree_add_text(tree, tvb, offset, length,
1572                           "Identification data: %s/%s",
1573                           ip_to_str(tvb_get_ptr(tvb, offset, 4)),
1574                           ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
1575       break;
1576     case IKE_ID_IPV6_ADDR:
1577       proto_tree_add_text(tree, tvb, offset, length,
1578                           "Identification data: %s",
1579                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)));
1580       break;
1581     case IKE_ID_IPV6_ADDR_SUBNET:
1582     case IKE_ID_IPV6_ADDR_RANGE:
1583       proto_tree_add_text(tree, tvb, offset, length,
1584                           "Identification data: %s/%s",
1585                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)),
1586                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset+16, 16)));
1587       break;
1588     case IKE_ID_DER_ASN1_DN:
1589       dissect_x509if_Name(FALSE, tvb, offset, pinfo, tree,
1590                           hf_ike_certificate_authority);
1591       break;
1592     default:
1593       proto_tree_add_text(tree, tvb, offset, length, "Identification Data");
1594       break;
1595   }
1596 }
1597
1598 static void
1599 dissect_cert(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1600     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1601 {
1602   guint8                cert_enc;
1603
1604   cert_enc = tvb_get_guint8(tvb, offset);
1605   proto_tree_add_uint_format(tree, hf_isakmp_cert_encoding, tvb, offset, 1,
1606                         cert_enc, "Certificate encoding: %u - %s",
1607                         cert_enc, certtype2str(isakmp_version, cert_enc));
1608   offset += 1;
1609   length -= 1;
1610
1611   proto_tree_add_text(tree, tvb, offset, length, "Certificate Data");
1612 }
1613
1614 static void
1615 dissect_certreq_v1(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1616     packet_info *pinfo, int isakmp_version, int unused _U_)
1617 {
1618   guint8                cert_type;
1619
1620   cert_type = tvb_get_guint8(tvb, offset);
1621   proto_tree_add_uint_format(tree, hf_isakmp_certreq_type, tvb, offset, 1,
1622                         cert_type, "Certificate type: %u - %s",
1623                         cert_type, certtype2str(isakmp_version, cert_type));
1624   offset += 1;
1625   length -= 1;
1626
1627   if (length) {
1628     if (cert_type == 4){
1629       dissect_x509if_Name(FALSE, tvb, offset, pinfo, tree, hf_ike_certificate_authority);
1630     } else {
1631       proto_tree_add_text(tree, tvb, offset, length, "Certificate Authority");
1632     }
1633   }
1634   else
1635     proto_tree_add_text(tree, tvb, offset, length, "Certificate Authority (empty)");
1636 }
1637
1638 static void
1639 dissect_certreq_v2(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1640     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1641 {
1642   guint8                cert_type;
1643
1644   cert_type = tvb_get_guint8(tvb, offset);
1645   proto_tree_add_text(tree, tvb, offset, 1,
1646                       "Certificate type: %u - %s",
1647                       cert_type, certtype2str(isakmp_version, cert_type));
1648   offset += 1;
1649   length -= 1;
1650
1651   /* this is a list of 20 byte SHA-1 hashes */
1652   while (length > 0) {
1653     proto_tree_add_item(tree, hf_ike_v2_certificate_authority, tvb, offset, 20, FALSE);
1654     length-=20;
1655   }
1656 }
1657
1658 static void
1659 dissect_hash(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1660     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1661 {
1662   proto_tree_add_text(tree, tvb, offset, length, "Hash Data");
1663 }
1664
1665 static void
1666 dissect_auth(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1667     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1668 {
1669   guint8 auth;
1670
1671   auth = tvb_get_guint8(tvb, offset);
1672   proto_tree_add_text(tree, tvb, offset, 1,
1673                       "Auth Method: %s (%u)", v2_auth2str(auth), auth);
1674   offset += 4;
1675   length -= 4;
1676
1677   proto_tree_add_text(tree, tvb, offset, length, "Authentication Data");
1678 }
1679
1680 static void
1681 dissect_sig(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1682     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1683 {
1684   proto_tree_add_text(tree, tvb, offset, length, "Signature Data");
1685 }
1686
1687 static void
1688 dissect_nonce(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1689     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1690 {
1691   proto_tree_add_text(tree, tvb, offset, length, "Nonce Data");
1692 }
1693
1694 static const char *
1695 v2_ipcomptype2str(guint8 type)
1696 {
1697   static const value_string vs_v2_ipcomptype[] = {
1698     { 0,        "RESERVED" },
1699     { 1,        "IPCOMP_OUI" },
1700     { 2,        "IPCOMP_DEFLATE" },
1701     { 3,        "IPCOMP_LZS" },
1702     { 4,        "IPCOMP_LZJH" },
1703     { 0,        NULL },
1704   };
1705
1706   if (type >= 5 && type <= 240)
1707     return "RESERVED TO IANA";
1708   if (type >= 241)
1709     return "PRIVATE USE";
1710   return val_to_str(type, vs_v2_ipcomptype, "UNKNOWN-IPCOMP-TYPE");
1711 }
1712
1713 static void
1714 dissect_notif(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1715     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
1716 {
1717   guint32               doi;
1718   guint8                protocol_id;
1719   guint8                spi_size;
1720   guint16               msgtype;
1721   guint8                ipcomptype;
1722
1723   if (isakmp_version == 1) {
1724     doi = tvb_get_ntohl(tvb, offset);
1725     proto_tree_add_uint_format(tree, hf_isakmp_doi, tvb, offset, 4,
1726                         doi, "Domain of interpretation: %s (%u)",
1727                         doitype2str(doi), doi);
1728     offset += 4;
1729     length -= 4;
1730   }
1731
1732   protocol_id = tvb_get_guint8(tvb, offset);
1733   proto_tree_add_uint_format(tree, hf_isakmp_protoid, tvb, offset, 1,
1734                         protocol_id, "Protocol ID: %s (%u)",
1735                         val_to_str(protocol_id, vs_proto, "UNKNOWN-PROTO-TYPE"), protocol_id);
1736   offset += 1;
1737   length -= 1;
1738
1739   spi_size = tvb_get_guint8(tvb, offset);
1740   proto_tree_add_item(tree, hf_isakmp_spisize, tvb, offset, 1, FALSE);
1741   offset += 1;
1742   length -= 1;
1743
1744   msgtype = tvb_get_ntohs(tvb, offset);
1745   proto_tree_add_uint_format(tree, hf_isakmp_notify_msgtype, tvb, offset, 2,
1746                         msgtype, "Message type: %s (%u)",
1747                         msgtype2str(isakmp_version, msgtype), msgtype);
1748   offset += 2;
1749   length -= 2;
1750
1751   if (spi_size) {
1752     proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: 0x%s",
1753                         tvb_bytes_to_str(tvb, offset, spi_size));
1754     offset += spi_size;
1755     length -= spi_size;
1756   }
1757
1758   if (length > 0) {
1759     proto_tree_add_text(tree, tvb, offset, length, "Notification Data");
1760
1761     /* notification data */
1762     if (isakmp_version == 2 && msgtype == 16387) {
1763       /* IPCOMP_SUPPORTED */
1764       proto_tree_add_text(tree, tvb, offset, 2,
1765                         "IPComp CPI (%u)", tvb_get_ntohs(tvb, offset));
1766       ipcomptype = tvb_get_guint8(tvb, offset + 2);
1767       proto_tree_add_text(tree, tvb, offset + 2, 1,
1768                         "Transform ID: %s (%u)",
1769                         v2_ipcomptype2str(ipcomptype), ipcomptype);
1770       offset += 3;
1771       length -= 3;
1772     }
1773   }
1774 }
1775
1776 static void
1777 dissect_delete(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1778     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1779 {
1780   guint32               doi;
1781   guint8                protocol_id;
1782   guint8                spi_size;
1783   guint16               num_spis;
1784   guint16               i;
1785
1786   if (isakmp_version == 1) {
1787     doi = tvb_get_ntohl(tvb, offset);
1788     proto_tree_add_text(tree, tvb, offset, 4,
1789                         "Domain of Interpretation: %s (%u)",
1790                         doitype2str(doi), doi);
1791     offset += 4;
1792     length -= 4;
1793   }
1794
1795   protocol_id = tvb_get_guint8(tvb, offset);
1796   proto_tree_add_uint_format(tree, hf_isakmp_protoid, tvb, offset, 1,
1797                         protocol_id, "Protocol ID: %s (%u)",
1798                         val_to_str(protocol_id, vs_proto, "UNKNOWN-PROTO-TYPE"), protocol_id);
1799   offset += 1;
1800   length -= 1;
1801
1802   spi_size = tvb_get_guint8(tvb, offset);
1803   proto_tree_add_item(tree, hf_isakmp_spisize, tvb, offset, 1, FALSE);
1804   offset += 1;
1805   length -= 1;
1806
1807   num_spis = tvb_get_ntohs(tvb, offset);
1808   proto_tree_add_item(tree, hf_isakmp_num_spis, tvb, offset, 2, FALSE);
1809   offset += 2;
1810   length -= 2;
1811
1812   for (i = 0; i < num_spis; ++i) {
1813     if (length < spi_size) {
1814       proto_tree_add_text(tree, tvb, offset, length,
1815           "Not enough room in payload for all SPI's");
1816       break;
1817     }
1818     proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: 0x%s",
1819                         tvb_bytes_to_str(tvb, offset, spi_size));
1820     offset += spi_size;
1821     length -= spi_size;
1822   }
1823 }
1824
1825 static void
1826 dissect_vid(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
1827     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
1828 {
1829   guint32 CPproduct, CPversion;
1830   const guint8 * pVID;
1831   proto_item * pt;
1832   proto_tree * ntree;
1833   pVID = tvb_get_ptr(tvb, offset, length);
1834   pt = proto_tree_add_text(tree, tvb, offset, length, "Vendor ID: ");
1835   if (memcmp(pVID, VID_MS_W2K_WXP, isakmp_min(VID_MS_LEN, length)) == 0)
1836         proto_item_append_text(pt, "Microsoft Win2K/WinXP");
1837   else
1838   if (memcmp(pVID, VID_CP, isakmp_min(VID_CP_LEN, length)) == 0)
1839   {
1840         proto_item_append_text(pt, "Check Point");
1841         offset += VID_CP_LEN;
1842         CPproduct = tvb_get_ntohl(tvb, offset);
1843         ntree = proto_item_add_subtree(pt, ett_isakmp_payload);
1844         pt = proto_tree_add_text(ntree, tvb, offset, sizeof(CPproduct), "Check Point Product: ");
1845         switch (CPproduct) {
1846                 case 1: proto_item_append_text(pt, "VPN-1");
1847                         break;
1848                 case 2: proto_item_append_text(pt, "SecuRemote/SecureClient");
1849                         break;
1850                 default: proto_item_append_text(pt, "Unknown CP product!");
1851                         break;
1852         }
1853         offset += sizeof(CPproduct);
1854         CPversion = tvb_get_ntohl(tvb, offset);
1855         pt = proto_tree_add_text(ntree, tvb, offset, sizeof(CPversion), "Version: ");
1856         switch (CPversion) {
1857                 case 2: proto_item_append_text(pt, "4.1");
1858                         break;
1859                 case 3: proto_item_append_text(pt, "4.1 SP-1");
1860                         break;
1861                 case 4002: proto_item_append_text(pt, "4.1 (SP-2 or above)");
1862                         break;
1863                 case 5000: proto_item_append_text(pt, "NG");
1864                         break;
1865                 case 5001: proto_item_append_text(pt, "NG Feature Pack 1");
1866                         break;
1867                 case 5002: proto_item_append_text(pt, "NG Feature Pack 2");
1868                         break;
1869                 case 5003: proto_item_append_text(pt, "NG Feature Pack 3");
1870                         break;
1871                 case 5004: proto_item_append_text(pt, "NG with Application Intelligence");
1872                         break;
1873                 case 5005: proto_item_append_text(pt, "NG with Application Intelligence R55");
1874                         break;
1875                 default: proto_item_append_text(pt, " Unknown CP version!");
1876                         break;
1877         }
1878         offset += sizeof(CPversion);
1879         proto_tree_add_text(ntree, tvb, offset, length - VID_CP_LEN - sizeof(CPproduct) - sizeof(CPversion),"Check Point Vendor ID parameters");
1880   }
1881   else
1882   if (memcmp(pVID, VID_CYBERGUARD, isakmp_min(VID_LEN, length)) == 0)
1883         proto_item_append_text(pt, "Cyber Guard");
1884   else
1885   if (memcmp(pVID,  VID_draft_ietf_ipsec_nat_t_ike_03, isakmp_min(VID_LEN, length)) == 0)
1886         proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-03");
1887   else
1888   if (memcmp(pVID,  VID_rfc3947, isakmp_min(VID_LEN, length)) == 0)
1889         proto_item_append_text(pt, "RFC 3947 Negotiation of NAT-Traversal in the IKE");
1890   else
1891   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_1_0, isakmp_min(VID_LEN, length)) == 0)
1892         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.0");
1893   else
1894   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_1_1, isakmp_min(VID_LEN, length)) == 0)
1895         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.1");
1896   else
1897   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_1_2, isakmp_min(VID_LEN, length)) == 0)
1898         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.2");
1899   else
1900   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_2_1, isakmp_min(VID_LEN, length)) == 0)
1901         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.2.1");
1902   else
1903   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_1_2_2, isakmp_min(VID_LEN, length)) == 0)
1904         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.2.2");
1905   else
1906   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_2_0_0, isakmp_min(VID_LEN, length)) == 0)
1907         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.0.0");
1908   else
1909   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_2_1_0, isakmp_min(VID_LEN, length)) == 0)
1910         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.0");
1911   else
1912   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_2_1_1, isakmp_min(VID_LEN, length)) == 0)
1913         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.1");
1914   else
1915   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_2_1_2, isakmp_min(VID_LEN, length)) == 0)
1916         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.2");
1917   else
1918   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_3_0_0, isakmp_min(VID_LEN, length)) == 0)
1919         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 3.0.0");
1920   else
1921   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_3_0_1, isakmp_min(VID_LEN, length)) == 0)
1922         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 3.0.1");
1923   else
1924   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_4_0_0, isakmp_min(VID_LEN, length)) == 0)
1925         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.0.0");
1926   else
1927   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_4_0_1, isakmp_min(VID_LEN, length)) == 0)
1928         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.0.1");
1929   else
1930   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_4_1_0, isakmp_min(VID_LEN, length)) == 0)
1931         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.1.0");
1932   else
1933   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_4_1_1, isakmp_min(VID_LEN, length)) == 0)
1934         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.1.1");
1935   else
1936   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_5_0, isakmp_min(VID_LEN, length)) == 0)
1937         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.0");
1938   else
1939   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_5_0_0, isakmp_min(VID_LEN, length)) == 0)
1940         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.0.0");
1941   else
1942   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_5_1_0, isakmp_min(VID_LEN, length)) == 0)
1943         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.1.0");
1944   else
1945   if (memcmp(pVID,  VID_SSH_IPSEC_EXPRESS_5_1_1, isakmp_min(VID_LEN, length)) == 0)
1946         proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.1.1");
1947   else
1948   if (memcmp(pVID,  VID_SSH_SENTINEL, isakmp_min(VID_LEN, length)) == 0)
1949         proto_item_append_text(pt, "SSH Sentinel");
1950   else
1951   if (memcmp(pVID,  VID_SSH_SENTINEL_1_1, isakmp_min(VID_LEN, length)) == 0)
1952         proto_item_append_text(pt, "SSH Sentinel 1.1");
1953   else
1954   if (memcmp(pVID,  VID_SSH_SENTINEL_1_2, isakmp_min(VID_LEN, length)) == 0)
1955         proto_item_append_text(pt, "SSH Sentinel 1.2");
1956   else
1957   if (memcmp(pVID,  VID_SSH_SENTINEL_1_3, isakmp_min(VID_LEN, length)) == 0)
1958         proto_item_append_text(pt, "SSH Sentinel 1.3");
1959   else
1960   if (memcmp(pVID,  VID_SSH_QUICKSEC_0_9_0, isakmp_min(VID_LEN, length)) == 0)
1961         proto_item_append_text(pt, "SSH Communications Security QuickSec 0.9.0");
1962   else
1963   if (memcmp(pVID,  VID_SSH_QUICKSEC_1_1_0, isakmp_min(VID_LEN, length)) == 0)
1964         proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.0");
1965   else
1966   if (memcmp(pVID,  VID_SSH_QUICKSEC_1_1_1, isakmp_min(VID_LEN, length)) == 0)
1967         proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.1");
1968   else
1969   if (memcmp(pVID,  VID_SSH_QUICKSEC_1_1_2, isakmp_min(VID_LEN, length)) == 0)
1970         proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.2");
1971   else
1972   if (memcmp(pVID,  VID_SSH_QUICKSEC_1_1_3, isakmp_min(VID_LEN, length)) == 0)
1973         proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.3");
1974   else
1975   if (memcmp(pVID,  VID_draft_huttunen_ipsec_esp_in_udp_01, isakmp_min(VID_LEN, length)) == 0)
1976         proto_item_append_text(pt, "draft-huttunen-ipsec-esp-in-udp-01.txt");
1977   else
1978   if (memcmp(pVID,  VID_draft_stenberg_ipsec_nat_traversal_01, isakmp_min(VID_LEN, length)) == 0)
1979         proto_item_append_text(pt, "draft-stenberg-ipsec-nat-traversal-01");
1980   else
1981   if (memcmp(pVID,  VID_draft_stenberg_ipsec_nat_traversal_02, isakmp_min(VID_LEN, length)) == 0)
1982         proto_item_append_text(pt, "draft-stenberg-ipsec-nat-traversal-02");
1983   else
1984   if (memcmp(pVID,  VID_draft_ietf_ipsec_nat_t_ike_00, isakmp_min(VID_LEN, length)) == 0)
1985         proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-00");
1986   else
1987   if (memcmp(pVID,  VID_draft_ietf_ipsec_nat_t_ike_02a, isakmp_min(VID_LEN, length)) == 0)
1988         proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-02");
1989   else
1990   if (memcmp(pVID,  VID_draft_ietf_ipsec_nat_t_ike_02b, isakmp_min(VID_LEN, length)) == 0)
1991         proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-02");
1992   else
1993   if (memcmp(pVID,  VID_draft_beaulieu_ike_xauth_02, isakmp_min(VID_LEN, length)) == 0)
1994         proto_item_append_text(pt, "draft-beaulieu-ike-xauth-02.txt");
1995   else
1996   if (memcmp(pVID,  VID_rfc3706_dpd, isakmp_min(VID_LEN, length)) == 0)
1997         proto_item_append_text(pt, "RFC 3706 Detecting Dead IKE Peers (DPD)");
1998   else
1999   if (memcmp(pVID,  VID_IKE_CHALLENGE_RESPONSE_1, isakmp_min(VID_LEN, length)) == 0)
2000         proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys");
2001   else
2002   if (memcmp(pVID,  VID_IKE_CHALLENGE_RESPONSE_2, isakmp_min(VID_LEN, length)) == 0)
2003         proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys");
2004   else
2005   if (memcmp(pVID,  VID_IKE_CHALLENGE_RESPONSE_REV_1, isakmp_min(VID_LEN, length)) == 0)
2006         proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys (Revised)");
2007   else
2008   if (memcmp(pVID,  VID_IKE_CHALLENGE_RESPONSE_REV_2, isakmp_min(VID_LEN, length)) == 0)
2009         proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys (Revised)");
2010   else
2011   if (memcmp(pVID,  VID_MS_L2TP_IPSEC_VPN_CLIENT, isakmp_min(VID_LEN, length)) == 0)
2012         proto_item_append_text(pt, "Microsoft L2TP/IPSec VPN Client");
2013   else
2014   if (memcmp(pVID,  VID_GSS_API_1, isakmp_min(VID_LEN, length)) == 0)
2015         proto_item_append_text(pt, "A GSS-API Authentication Method for IKE");
2016   else
2017   if (memcmp(pVID,  VID_GSS_API_2, isakmp_min(VID_LEN, length)) == 0)
2018         proto_item_append_text(pt, "A GSS-API Authentication Method for IKE");
2019   else
2020   if (memcmp(pVID,  VID_GSSAPI, isakmp_min(VID_LEN, length)) == 0)
2021         proto_item_append_text(pt, "GSSAPI");
2022   else
2023   if (memcmp(pVID,  VID_MS_NT5_ISAKMPOAKLEY, isakmp_min(VID_LEN, length)) == 0)
2024         proto_item_append_text(pt, "MS NT5 ISAKMPOAKLEY");
2025   else
2026   if (memcmp(pVID,  VID_CISCO_UNITY, isakmp_min(VID_LEN, length)) == 0)
2027         proto_item_append_text(pt, "CISCO-UNITY");
2028   else
2029   if (memcmp(pVID,  VID_draft_ietf_ipsec_antireplay_00, isakmp_min(VID_LEN_8, length)) == 0)
2030         proto_item_append_text(pt, "draft-ietf-ipsec-antireplay-00.txt");
2031   else
2032   if (memcmp(pVID,  VID_draft_ietf_ipsec_heartbeats_00, isakmp_min(VID_LEN_8, length)) == 0)
2033         proto_item_append_text(pt, "draft-ietf-ipsec-heartbeats-00.txt");
2034   else
2035         proto_item_append_text(pt, "unknown vendor ID: 0x%s",tvb_bytes_to_str(tvb, offset, length));
2036 }
2037
2038 static void
2039 dissect_config(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
2040     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
2041 {
2042   guint8                type;
2043
2044   if (isakmp_version == 1) {
2045     type = tvb_get_guint8(tvb, offset);
2046     proto_tree_add_text(tree, tvb, offset, 1,
2047                         "Type %s (%u)",
2048                         cfgtype2str(isakmp_version, type), type);
2049     offset += 2;
2050     length -= 2;
2051
2052     proto_tree_add_text(tree, tvb, offset, 2,
2053                         "Identifier: %u", tvb_get_ntohs(tvb, offset));
2054     offset += 2;
2055     length -= 2;
2056   } else if (isakmp_version == 2) {
2057     type = tvb_get_guint8(tvb, offset);
2058     proto_tree_add_text(tree, tvb, offset, 1,
2059                         "CFG Type %s (%u)",
2060                         cfgtype2str(isakmp_version, type), type);
2061     offset += 4;
2062     length -= 4;
2063   }
2064
2065   while(length>0) {
2066     guint16 aft     = tvb_get_ntohs(tvb, offset);
2067     guint16 type    = aft & 0x7fff;
2068     guint16 len;
2069     guint32 val;
2070     guint pack_len;
2071
2072     if (aft & 0x8000) {
2073       val = tvb_get_ntohs(tvb, offset + 2);
2074       proto_tree_add_text(tree, tvb, offset, 4,
2075                           "%s (%u)",
2076                           cfgattr2str(isakmp_version, type), val);
2077       offset += 4;
2078       length -= 4;
2079     }
2080     else {
2081       len = tvb_get_ntohs(tvb, offset + 2);
2082       pack_len = 4 + len;
2083       if (!get_num(tvb, offset + 4, len, &val)) {
2084         proto_tree_add_text(tree, tvb, offset, pack_len,
2085                             "%s: <too big (%u bytes)>",
2086                             cfgattr2str(isakmp_version, type), len);
2087       } else {
2088         proto_tree_add_text(tree, tvb, offset, 4,
2089                             "%s (%ue)",
2090                             cfgattr2str(isakmp_version, type), val);
2091       }
2092       offset += pack_len;
2093       length -= pack_len;
2094     }
2095   }
2096 }
2097
2098 static void
2099 dissect_nat_discovery(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
2100     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
2101 {
2102   proto_tree_add_text(tree, tvb, offset, length,
2103                       "Hash of address and port: %s",
2104                       tvb_bytes_to_str(tvb, offset, length));
2105 }
2106
2107 static void
2108 dissect_nat_original_address(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
2109     packet_info *pinfo _U_, int isakmp_version, int unused _U_)
2110 {
2111   guint8 id_type;
2112   guint32 addr_ipv4;
2113   struct e_in6_addr addr_ipv6;
2114
2115   id_type = tvb_get_guint8(tvb, offset);
2116   proto_tree_add_text(tree, tvb, offset, 1,
2117                       "ID type: %s (%u)",
2118                       id2str(isakmp_version, id_type), id_type);
2119   offset += 1;
2120   length -= 1;
2121
2122   offset += 3;          /* reserved */
2123   length -= 3;
2124
2125   switch (id_type) {
2126
2127   case IKE_ID_IPV4_ADDR:
2128     if (length == 4) {
2129       addr_ipv4 = tvb_get_ipv4(tvb, offset);
2130       proto_tree_add_text(tree, tvb, offset, length,
2131                           "Original address: %s",
2132                           ip_to_str((guint8 *)&addr_ipv4));
2133     } else {
2134       proto_tree_add_text(tree, tvb, offset, length,
2135                           "Original address: bad length, should be 4, is %u",
2136                           length);
2137     }
2138     break;
2139
2140   case IKE_ID_IPV6_ADDR:
2141     if (length == 16) {
2142       tvb_get_ipv6(tvb, offset, &addr_ipv6);
2143       proto_tree_add_text(tree, tvb, offset, length,
2144                           "Original address: %s",
2145                           ip6_to_str(&addr_ipv6));
2146     } else {
2147       proto_tree_add_text(tree, tvb, offset, length,
2148                           "Original address: bad length, should be 16, is %u",
2149                           length);
2150     }
2151     break;
2152
2153   default:
2154     proto_tree_add_text(tree, tvb, offset, length,
2155                         "Original address: bad address type");
2156     break;
2157   }
2158 }
2159
2160 static void
2161 dissect_ts(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
2162     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
2163 {
2164   guint8        num, tstype, protocol_id, addrlen;
2165   guint16       len, port;
2166
2167   proto_tree_add_text(tree, tvb, offset, length, "Traffic Selector");
2168
2169   num = tvb_get_guint8(tvb, offset);
2170   proto_item_append_text(tree," # %d", num);
2171   proto_tree_add_text(tree, tvb, offset, 1,
2172                       "Number of TSs: %u", num);
2173   offset += 4;
2174   length -= 4;
2175
2176   while (length > 0) {
2177     tstype = tvb_get_guint8(tvb, offset);
2178     proto_tree_add_text(tree, tvb, offset, 1,
2179                       "TS Type: %s (%u)",
2180                       v2_tstype2str(tstype), tstype);
2181     switch (tstype) {
2182     case IKEV2_TS_IPV4_ADDR_RANGE:
2183       addrlen = 4;
2184       break;
2185     case IKEV2_TS_IPV6_ADDR_RANGE:
2186       addrlen = 16;
2187       break;
2188     default:
2189       proto_item_append_text(tree, "unknown TS data (aborted decoding): 0x%s",
2190                         tvb_bytes_to_str(tvb, offset, length));
2191       return;
2192     }
2193
2194     /*
2195      * XXX should the remaining of the length check be done here ?
2196      * it seems other routines don't check the length.
2197      */
2198     if (length < (8 + addrlen * 2)) {
2199       proto_tree_add_text(tree, tvb, offset, length,
2200                           "Length mismatch (%u)", length);
2201       return;
2202     }
2203     offset += 1;
2204     length -= 1;
2205
2206     protocol_id = tvb_get_guint8(tvb, offset);
2207     proto_tree_add_text(tree, tvb, offset, 1,
2208                       "Protocol ID: (%u)", protocol_id);
2209     offset += 1;
2210     length -= 1;
2211
2212     len = tvb_get_ntohs(tvb, offset);
2213     proto_tree_add_text(tree, tvb, offset, 2,
2214                       "Selector Length: %u", len);
2215     offset += 2;
2216     length -= 2;
2217
2218     port = tvb_get_ntohs(tvb, offset);
2219     proto_tree_add_text(tree, tvb, offset, 2,
2220                       "Start Port: (%u)", port);
2221     offset += 2;
2222     length -= 2;
2223
2224     port = tvb_get_ntohs(tvb, offset);
2225     proto_tree_add_text(tree, tvb, offset, 2,
2226                       "End Port: (%u)", port);
2227     offset += 2;
2228     length -= 2;
2229
2230     switch (tstype) {
2231     case IKEV2_TS_IPV4_ADDR_RANGE:
2232         proto_tree_add_text(tree, tvb, offset, length,
2233                           "Starting Address: %s",
2234                           ip_to_str(tvb_get_ptr(tvb, offset, addrlen)));
2235         offset += addrlen;
2236         length -= addrlen;
2237         proto_tree_add_text(tree, tvb, offset, length,
2238                           "Ending Address: %s",
2239                           ip_to_str(tvb_get_ptr(tvb, offset, addrlen)));
2240         offset += addrlen;
2241         length -= addrlen;
2242         break;
2243     case IKEV2_TS_IPV6_ADDR_RANGE:
2244         proto_tree_add_text(tree, tvb, offset, length,
2245                           "Starting Address: %s",
2246                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, addrlen)));
2247         offset += addrlen;
2248         length -= addrlen;
2249         proto_tree_add_text(tree, tvb, offset, length,
2250                           "Ending Address: %s",
2251                           ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, addrlen)));
2252         offset += addrlen;
2253         length -= addrlen;
2254         break;
2255     }
2256   }
2257 }
2258
2259 static void
2260 dissect_enc(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
2261     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
2262 {
2263   proto_tree_add_text(tree, tvb, offset, 4, "Initialization Vector: 0x%s",
2264                       tvb_bytes_to_str(tvb, offset, 4));
2265   proto_tree_add_text(tree, tvb, offset + 4, length, "Encrypted Data");
2266 }
2267
2268 static void
2269 dissect_eap(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
2270     packet_info *pinfo _U_, int isakmp_version _U_, int unused _U_)
2271 {
2272   proto_tree_add_text(tree, tvb, offset, length, "EAP Message");
2273 }
2274
2275 static const char *
2276 payloadtype2str(int isakmp_version, guint8 type)
2277 {
2278   struct payload_func *f;
2279
2280   if ((f = getpayload_func(type, isakmp_version)) != NULL)
2281       return f->str;
2282
2283   if (isakmp_version == 1) {
2284     if (type < 128)
2285       return "RESERVED";
2286     return "Private USE";
2287   } else if (isakmp_version == 2) {
2288     if (type > 127)
2289       return "PRIVATE USE";
2290     if (type > 48)
2291       return "RESERVED TO IANA";
2292     return "RESERVED";
2293   }
2294   return "UNKNOWN-ISAKMP-VERSION";
2295 }
2296
2297 static const char *
2298 exchtype2str(int isakmp_version, guint8 type)
2299 {
2300   static const value_string vs_v1_exchange[] = {
2301     { 0,        "NONE" },
2302     { 1,        "Base" },
2303     { 2,        "Identity Protection (Main Mode)" },
2304     { 3,        "Authentication Only" },
2305     { 4,        "Aggressive" },
2306     { 5,        "Informational" },
2307     { 6,        "Transaction (Config Mode)" },
2308     { 32,       "Quick Mode" },
2309     { 33,       "New Group Mode" },
2310     { 0,        NULL },
2311   };
2312
2313   static const value_string vs_v2_exchange[] = {
2314     { 34,       "IKE_SA_INIT" },
2315     { 35,       "IKE_AUTH " },
2316     { 36,       "CREATE_CHILD_SA" },
2317     { 37,       "INFORMATIONAL" },
2318     { 0,        NULL },
2319   };
2320
2321   if (isakmp_version == 1) {
2322     if (type > 6 && type < 32)
2323       return "ISAKMP Future Use";
2324     if (type > 33 && type < 240)
2325       return "DOI Specific Use";
2326     return val_to_str(type, vs_v1_exchange, "Private Use");
2327   } else if (isakmp_version == 2) {
2328     if (type < 34)
2329       return "RESERVED";
2330     if (type > 37 && type < 240)
2331       return "Reserved for IKEv2+";
2332     return val_to_str(type, vs_v2_exchange, "Reserved for private use");
2333   }
2334   return "UNKNOWN-ISAKMP-VERSION";
2335 }
2336
2337 static const char *
2338 doitype2str(guint32 type)
2339 {
2340   if (type == 1) return "IPSEC";
2341   return "Unknown DOI Type";
2342 }
2343
2344 static const char *
2345 msgtype2str(int isakmp_version, guint16 type)
2346 {
2347   static const value_string vs_v1_notifmsg[] = {
2348     { 0,        "<UNKNOWN>" },
2349     { 1,        "INVALID-PAYLOAD-TYPE" },
2350     { 2,        "DOI-NOT-SUPPORTED" },
2351     { 3,        "SITUATION-NOT-SUPPORTED" },
2352     { 4,        "INVALID-COOKIE" },
2353     { 5,        "INVALID-MAJOR-VERSION" },
2354     { 6,        "INVALID-MINOR-VERSION" },
2355     { 7,        "INVALID-EXCHANGE-TYPE" },
2356     { 8,        "INVALID-FLAGS" },
2357     { 9,        "INVALID-MESSAGE-ID" },
2358     { 10,       "INVALID-PROTOCOL-ID" },
2359     { 11,       "INVALID-SPI" },
2360     { 12,       "INVALID-TRANSFORM-ID" },
2361     { 13,       "ATTRIBUTES-NOT-SUPPORTED" },
2362     { 14,       "NO-PROPOSAL-CHOSEN" },
2363     { 15,       "BAD-PROPOSAL-SYNTAX" },
2364     { 16,       "PAYLOAD-MALFORMED" },
2365     { 17,       "INVALID-KEY-INFORMATION" },
2366     { 18,       "INVALID-ID-INFORMATION" },
2367     { 19,       "INVALID-CERT-ENCODING" },
2368     { 20,       "INVALID-CERTIFICATE" },
2369     { 21,       "CERT-TYPE-UNSUPPORTED" },
2370     { 22,       "INVALID-CERT-AUTHORITY" },
2371     { 23,       "INVALID-HASH-INFORMATION" },
2372     { 24,       "AUTHENTICATION-FAILED" },
2373     { 25,       "INVALID-SIGNATURE" },
2374     { 26,       "ADDRESS-NOTIFICATION" },
2375     { 27,       "NOTIFY-SA-LIFETIME" },
2376     { 28,       "CERTIFICATE-UNAVAILABLE" },
2377     { 29,       "UNSUPPORTED-EXCHANGE-TYPE" },
2378     { 30,       "UNEQUAL-PAYLOAD-LENGTHS" },
2379     { 8192,     "RESERVED" },
2380     { 16384,    "CONNECTED" },
2381     { 24576,    "RESPONDER-LIFETIME" },
2382     { 24577,    "REPLAY-STATUS" },
2383     { 24578,    "INITIAL-CONTACT" },
2384     { 0,        NULL },
2385   };
2386
2387   static const value_string vs_v2_notifmsg[] = {
2388     {     0,    "RESERVED" },
2389     {     4,    "INVALID_IKE_SPI" },
2390     {     5,    "INVALID_MAJOR_VERSION" },
2391     {     7,    "INVALID_SYNTAX" },
2392     {     9,    "INVALID_MESSAGE_ID" },
2393     {    11,    "INVALID_SPI" },
2394     {    14,    "NO_PROPOSAL_CHOSEN" },
2395     {    17,    "INVALID_KE_PAYLOAD" },
2396     {    24,    "AUTHENTICATION_FAILED" },
2397     {    34,    "SINGLE_PAIR_REQUIRED" },
2398     {    35,    "NO_ADDITIONAL_SAS" },
2399     {    36,    "INTERNAL_ADDRESS_FAILURE" },
2400     {    37,    "FAILED_CP_REQUIRED" },
2401     {    38,    "TS_UNACCEPTABLE" },
2402     {    39,    "INVALID_SELECTORS" },
2403     { 16384,    "INITIAL_CONTACT" },
2404     { 16385,    "SET_WINDOW_SIZE" },
2405     { 16386,    "ADDITIONAL_TS_POSSIBLE" },
2406     { 16387,    "IPCOMP_SUPPORTED" },
2407     { 16388,    "NAT_DETECTION_SOURCE_IP" },
2408     { 16389,    "NAT_DETECTION_DESTINATION_IP" },
2409     { 16390,    "COOKIE" },
2410     { 16391,    "USE_TRANSPORT_MODE" },
2411     { 16392,    "HTTP_CERT_LOOKUP_SUPPORTED" },
2412     { 16393,    "REKEY_SA" },
2413     { 16394,    "ESP_TFC_PADDING_NOT_SUPPORTED" },
2414     { 16395,    "NON_FIRST_FRAGMENTS_ALSO" },
2415     { 0,        NULL },
2416   };
2417
2418   if (isakmp_version == 1) {
2419     if (type > 30 && type < 8192)
2420       return "RESERVED (Future Use)";
2421     if (type > 8192 && type < 16384)
2422       return "Private Use";
2423     if (type > 16384 && type < 24576)
2424       return "RESERVED (Future Use) - status";
2425     if (type > 24578 && type < 32768)
2426       return "DOI-specific codes";
2427     if (type > 32767 && type < 40960)
2428       return "Private Use - status";
2429     if (type > 40959 && type < 65535)
2430       return "RESERVED (Future Use) - status (2)";
2431     return val_to_str(type, vs_v1_notifmsg, "UNKNOWN-NOTIFY-MESSAGE-TYPE");
2432   } else if (isakmp_version == 2) {
2433     if (type >= 40 && type <= 8191)
2434       return "RESERVED TO IANA - Error types";
2435     if (type >= 16396 && type <= 40959)
2436       return "RESERVED TO IANA - STATUS TYPES";
2437     if (type >= 8192 && type <= 16383)
2438       return "Private Use - Errors";
2439     if (type >= 40960)
2440       return "Private Use - STATUS TYPES";
2441     return val_to_str(type, vs_v2_notifmsg, "UNKNOWN-NOTIFY-MESSAGE-TYPE");
2442   }
2443   return "UNKNOWN-ISAKMP-VERSION";
2444 }
2445
2446 static const char *
2447 situation2str(guint32 type)
2448 {
2449
2450 #define SIT_MSG_NUM     1024
2451 #define SIT_IDENTITY    0x01
2452 #define SIT_SECRECY     0x02
2453 #define SIT_INTEGRITY   0x04
2454
2455   static char   msg[SIT_MSG_NUM];
2456   int           n = 0;
2457   const char *  sep = "";
2458   int           ret;
2459
2460   if (type & SIT_IDENTITY) {
2461     ret = g_snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep);
2462     if (ret == -1 || ret >= SIT_MSG_NUM-n) {
2463       /* Truncated. */
2464       return msg;
2465     }
2466     n += ret;
2467     sep = " & ";
2468   }
2469   if (type & SIT_SECRECY) {
2470     if (n >= SIT_MSG_NUM) {
2471       /* No more room. */
2472       return msg;
2473     }
2474     ret = g_snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep);
2475     if (ret == -1 || ret >= SIT_MSG_NUM-n) {
2476       /* Truncated. */
2477       return msg;
2478     }
2479     n += ret;
2480     sep = " & ";
2481   }
2482   if (type & SIT_INTEGRITY) {
2483     if (n >= SIT_MSG_NUM) {
2484       /* No more room. */
2485       return msg;
2486     }
2487     ret = g_snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep);
2488     if (ret == -1 || ret >= SIT_MSG_NUM-n) {
2489       /* Truncated. */
2490       return msg;
2491     }
2492     n += ret;
2493     sep = " & ";
2494   }
2495
2496   return msg;
2497 }
2498
2499 static const char *
2500 v2_attrval2str(guint16 att_type, guint32 value)
2501 {
2502   value = 0;    /* dummy to be less warning in compiling it */
2503   switch (att_type) {
2504   case 14:
2505     return "Key-Length";
2506   default:
2507     return "UNKNOWN-ATTRIBUTE-TYPE";
2508   }
2509 }
2510
2511 static const char *
2512 v1_attrval2str(int ike_p1, guint16 att_type, guint32 value)
2513 {
2514   static const value_string vs_v1_attrval_lttype[] = {
2515     { 0,        "RESERVED" },
2516     { 1,        "Seconds" },
2517     { 2,        "Kilobytes" },
2518     { 0,        NULL },
2519   };
2520
2521   static const value_string vs_v1_attrval_encap[] = {
2522     { 0,        "RESERVED" },
2523     { 1,        "Tunnel" },
2524     { 2,        "Transport" },
2525     { 3,        "UDP-Encapsulated-Tunnel" }, /* http://www.ietf.org/internet-drafts/draft-ietf-ipsec-nat-t-ike-05.txt */
2526     { 4,        "UDP-Encapsulated-Transport" }, /* http://www.ietf.org/internet-drafts/draft-ietf-ipsec-nat-t-ike-05.txt */
2527     { 61440,    "Check Point IPSec UDP Encapsulation" },
2528     { 61443,    "UDP-Encapsulated-Tunnel (draft)" },
2529     { 61444,    "UDP-Encapsulated-Transport (draft)" },
2530     { 0,        NULL },
2531   };
2532
2533   static const value_string vs_v1_attrval_auth[] = {
2534     { 0,        "RESERVED" },
2535     { 1,        "HMAC-MD5" },
2536     { 2,        "HMAC-SHA" },
2537     { 3,        "DES-MAC" },
2538     { 4,        "KPDK" },
2539     { 5,        "HMAC-SHA2-256" },
2540     { 6,        "HMAC-SHA2-384" },
2541     { 7,        "HMAC-SHA2-512" },
2542     { 0,        NULL },
2543   };
2544
2545   static const value_string vs_v1_attrval_enc[] = {
2546     { 0,                        "RESERVED" },
2547     { ENC_DES_CBC,              "DES-CBC" },
2548     { ENC_IDEA_CBC,             "IDEA-CBC" },
2549     { ENC_BLOWFISH_CBC,         "BLOWFISH-CBC" },
2550     { ENC_RC5_R16_B64_CBC,      "RC5-R16-B64-CBC" },
2551     { ENC_3DES_CBC,             "3DES-CBC" },
2552     { ENC_CAST_CBC,             "CAST-CBC" },
2553     { ENC_AES_CBC,              "AES-CBC" },
2554     { 0,        NULL },
2555   };
2556
2557   static const value_string vs_v1_attrval_hash[] = {
2558     { 0,                "RESERVED" },
2559     { HMAC_MD5,         "MD5" },
2560     { HMAC_SHA,         "SHA" },
2561     { HMAC_TIGER,       "TIGER" },
2562     { HMAC_SHA2_256,    "SHA2-256" },
2563     { HMAC_SHA2_384,    "SHA2-384" },
2564     { HMAC_SHA2_512,    "SHA2-512" },
2565     { 0,        NULL },
2566   };
2567
2568   static const value_string vs_v1_attrval_authmeth[] = {
2569     { 0,        "RESERVED" },
2570     { 1,        "PSK" },
2571     { 2,        "DSS-SIG" },
2572     { 3,        "RSA-SIG" },
2573     { 4,        "RSA-ENC" },
2574     { 5,        "RSA-Revised-ENC" },
2575     { 6,        "Encryption with El-Gamal" },
2576     { 7,        "Revised encryption with El-Gamal" },
2577     { 8,        "ECDSA signatures" },
2578     { 9,        "AES-XCBC-MAC" },
2579     { 64221,    "HybridInitRSA" },
2580     { 64222,    "HybridRespRSA" },
2581     { 64223,    "HybridInitDSS" },
2582     { 64224,    "HybridRespDSS" },
2583     { 65001,    "XAUTHInitPreShared" },
2584     { 65002,    "XAUTHRespPreShared" },
2585     { 65003,    "XAUTHInitDSS" },
2586     { 65004,    "XAUTHRespDSS" },
2587     { 65005,    "XAUTHInitRSA" },
2588     { 65006,    "XAUTHRespRSA" },
2589     { 65007,    "XAUTHInitRSAEncryption" },
2590     { 65008,    "XAUTHRespRSAEncryption" },
2591     { 65009,    "XAUTHInitRSARevisedEncryption" },
2592     { 65010,    "XAUTHRespRSARevisedEncryption" },
2593     { 0,        NULL },
2594   };
2595
2596   static const value_string vs_v1_attrval_grpdesc[] = {
2597     { 0,        "UNDEFINED - 0" },
2598     { 1,        "Default 768-bit MODP group" },
2599     { 2,        "Alternate 1024-bit MODP group" },
2600     { 3,        "EC2N group on GP[2^155] group" },
2601     { 4,        "EC2N group on GP[2^185] group" },
2602     { 5,        "1536 bit MODP group" },
2603     { 6,        "EC2N group over GF[2^163]" },
2604     { 7,        "EC2N group over GF[2^163]" },
2605     { 8,        "EC2N group over GF[2^283]" },
2606     { 9,        "EC2N group over GF[2^283]" },
2607     { 10,       "EC2N group over GF[2^409]" },
2608     { 11,       "EC2N group over GF[2^409]" },
2609     { 12,       "EC2N group over GF[2^571]" },
2610     { 13,       "EC2N group over GF[2^571]" },
2611     { 14,       "2048 bit MODP group" },
2612     { 15,       "3072 bit MODP group" },
2613     { 16,       "4096 bit MODP group" },
2614     { 17,       "6144 bit MODP group" },
2615     { 18,       "8192 bit MODP group" },
2616     { 19,       "256-bit random curve group" },
2617     { 20,       "384-bit random curve group" },
2618     { 21,       "521-bit random curve group" },
2619     { 22,       "192-bit random curve group" },
2620     { 23,       "EC2N group over GF[2^163]" },
2621     { 24,       "224-bit random curve group" },
2622     { 25,       "EC2N group over GF[2^233]" },
2623     { 26,       "EC2N group over GF[2^233]" },
2624     { 0,        NULL }
2625   };
2626
2627   static const value_string vs_v1_attrval_grptype[] = {
2628     { 0,        "UNDEFINED - 0" },
2629     { 1,        "MODP" },
2630     { 2,        "ECP" },
2631     { 3,        "EC2N" },
2632     { 0,        NULL },
2633   };
2634
2635   static const value_string vs_v1_attrval_lifetype[] = {
2636     { 0,        "UNDEFINED - 0" },
2637     { 1,        "Seconds" },
2638     { 2,        "Kilobytes" },
2639     { 0,        NULL },
2640   };
2641
2642   if (value == 0) return "RESERVED";
2643
2644   if (!ike_p1) {
2645     switch (att_type) {
2646       case 1:
2647         return val_to_str(value, vs_v1_attrval_lttype, "UNKNOWN-LIFETIME-TYPE");
2648       case 2:
2649         return "Duration-Value";
2650       case 3:
2651         return "Group-Value";
2652       case 4:
2653         return val_to_str(value, vs_v1_attrval_encap, "UNKNOWN-ENCAPSULATION-VALUE");
2654       case 5:
2655         return val_to_str(value, vs_v1_attrval_auth, "UNKNOWN-AUTHENTICATION-VALUE");
2656       case 6:
2657         return "Key-Length";
2658       case 7:
2659         return "Key-Rounds";
2660       case 8:
2661         return "Compress-Dictionary-size";
2662       case 9:
2663         return "Compress Private Algorithm";
2664       default:
2665         return "UNKNOWN-ATTRIBUTE-TYPE";
2666     }
2667   }
2668   else {
2669     switch (att_type) {
2670       case 1:
2671         return val_to_str(value, vs_v1_attrval_enc, "UNKNOWN-ENCRYPTION-ALG");
2672       case 2:
2673         return val_to_str(value, vs_v1_attrval_hash, "UNKNOWN-HASH-ALG");
2674       case 3:
2675         return val_to_str(value, vs_v1_attrval_authmeth, "UNKNOWN-AUTH-METHOD");
2676       case 4:
2677         return val_to_str(value, vs_v1_attrval_grpdesc, "UNKNOWN-GROUP-DESCRIPTION");
2678       case 6:
2679       case 7:
2680       case 8:
2681       case 9:
2682       case 10:
2683       case 16:
2684         return "Group-Value";
2685       case 5:
2686         return val_to_str(value, vs_v1_attrval_grptype, "UNKNOWN-GROUP-TYPE");
2687       case 11:
2688         return val_to_str(value, vs_v1_attrval_lifetype, "UNKNOWN-LIFE-TYPE");
2689       case 12:
2690         return "Duration-Value";
2691       case 13:
2692         return "PRF-Value";
2693       case 14:
2694         return "Key-Length";
2695       case 15:
2696         return "Field-Size";
2697       default:
2698         return "UNKNOWN-ATTRIBUTE-TYPE";
2699     }
2700   }
2701 }
2702
2703 static const char *
2704 cfgtype2str(int isakmp_version, guint8 type)
2705 {
2706   static const value_string vs_v1_cfgtype[] = {
2707     { 0,        "Reserved" },
2708     { 1,        "ISAKMP_CFG_REQUEST" },
2709     { 2,        "ISAKMP_CFG_REPLY" },
2710     { 3,        "ISAKMP_CFG_SET" },
2711     { 4,        "ISAKMP_CFG_ACK" },
2712     { 0,        NULL },
2713   };
2714
2715 #if 0
2716   static const value_string vs_v2_cfgtype[] = {
2717     { 0,        "RESERVED" },
2718     { 1,        "CFG_REQUEST" },
2719     { 2,        "CFG_REPLY" },
2720     { 3,        "CFG_SET" },
2721     { 4,        "CFG_ACK" },
2722     { 0,        NULL },
2723   };
2724 #endif
2725
2726   if (isakmp_version == 1) {
2727     if (type >= 5 && type <= 127)
2728       return "Future use";
2729     if (type >= 128)
2730       return "Private Use";
2731     return val_to_str(type, vs_v1_cfgtype, "UNKNOWN-CFG-TYPE");
2732   } else if (isakmp_version == 2) {
2733     if (type >= 5 && type <= 127)
2734       return "RESERVED TO IANA";
2735     if (type >= 128)
2736       return "PRIVATE USE";
2737     return val_to_str(type, vs_v1_cfgtype, "UNKNOWN-CFG-TYPE");
2738   }
2739   return "UNKNOWN-ISAKMP-VERSION";
2740 }
2741
2742 static const char *
2743 id2str(int isakmp_version, guint8 type)
2744 {
2745   static const value_string vs_ident[] = {
2746     { IKE_ID_IPV4_ADDR,         "IPV4_ADDR" },
2747     { IKE_ID_FQDN,              "FQDN" },
2748     { IKE_ID_USER_FQDN,         "USER_FQDN" },
2749     { IKE_ID_IPV4_ADDR_SUBNET,  "IPV4_ADDR_SUBNET" },
2750     { IKE_ID_IPV6_ADDR,         "IPV6_ADDR" },
2751     { IKE_ID_IPV6_ADDR_SUBNET,  "IPV6_ADDR_SUBNET" },
2752     { IKE_ID_IPV4_ADDR_RANGE,   "IPV4_ADDR_RANGE" },
2753     { IKE_ID_IPV6_ADDR_RANGE,   "IPV6_ADDR_RANGE" },
2754     { IKE_ID_DER_ASN1_DN,       "DER_ASN1_DN" },
2755     { IKE_ID_DER_ASN1_GN,       "DER_ASN1_GN" },
2756     { IKE_ID_KEY_ID,            "KEY_ID" },
2757     { 0,                        NULL },
2758   };
2759
2760   if (isakmp_version == 1) {
2761     if (type == 0)
2762       return "RESERVED";
2763     return val_to_str(type, vs_ident, "UNKNOWN-ID-TYPE");
2764   } else if (isakmp_version == 2) {
2765     if (type == 4 || (type >= 6 && type <=8) || (type >= 12 && type <= 200))
2766       return "Reserved to IANA";
2767     if (type >= 201)
2768       return "Reserved for private use";
2769     if (type == IKE_ID_USER_FQDN)
2770       return "RFC822_ADDR";
2771     return val_to_str(type, vs_ident, "UNKNOWN-ID-TYPE");
2772   }
2773   return "UNKNOWN-ISAKMP-VERSION";
2774 }
2775
2776 static const char *
2777 v2_tstype2str(guint8 type)
2778 {
2779   static const value_string vs_v2_tstype[] = {
2780     { IKEV2_TS_IPV4_ADDR_RANGE, "TS_IPV4_ADDR_RANGE" },
2781     { IKEV2_TS_IPV6_ADDR_RANGE, "TS_IPV6_ADDR_RANGE" },
2782     { 0,        NULL },
2783   };
2784
2785   if (type <= 6)
2786     return "RESERVED";
2787   if (type >= 9 && type <= 240)
2788     return "RESERVED TO IANA";
2789   if (type >= 241)
2790     return "PRIVATE USE";
2791   return val_to_str(type, vs_v2_tstype, "UNKNOWN-TS-TYPE");
2792 }
2793
2794 static const char *
2795 v2_auth2str(guint8 type)
2796 {
2797   static const value_string vs_v2_authmeth[] = {
2798     { 0,        "RESERVED TO IANA" },
2799     { 1,        "RSA Digital Signature" },
2800     { 2,        "Shared Key Message Integrity Code" },
2801     { 3,        "DSS Digital Signature" },
2802     { 0,        NULL },
2803   };
2804
2805   if (type >= 4 && type <= 200)
2806     return "RESERVED TO IANA";
2807   if (type >= 201)
2808     return "PRIVATE USE";
2809   return val_to_str(type, vs_v2_authmeth, "UNKNOWN-AUTHMETHOD-TYPE");
2810 }
2811
2812 static const char *
2813 cfgattr2str(int isakmp_version, guint16 ident)
2814 {
2815   static const value_string vs_v1_cfgattr[] = {
2816     { 0,        "RESERVED" },
2817     { 1,        "INTERNAL_IP4_ADDRESS" },
2818     { 2,        "INTERNAL_IP4_NETMASK" },
2819     { 3,        "INTERNAL_IP4_DNS" },
2820     { 4,        "INTERNAL_IP4_NBNS" },
2821     { 5,        "INTERNAL_ADDRESS_EXPIREY" },
2822     { 6,        "INTERNAL_IP4_DHCP" },
2823     { 7,        "APPLICATION_VERSION" },
2824     { 8,        "INTERNAL_IP6_ADDRESS" },
2825     { 9,        "INTERNAL_IP6_NETMASK" },
2826     { 10,       "INTERNAL_IP6_DNS" },
2827     { 11,       "INTERNAL_IP6_NBNS" },
2828     { 12,       "INTERNAL_IP6_DHCP" },
2829     { 13,       "INTERNAL_IP4_SUBNET" },
2830     { 14,       "SUPPORTED_ATTRIBUTES" },
2831     { 16520,    "XAUTH_TYPE" },
2832     { 16521,    "XAUTH_USER_NAME" },
2833     { 16522,    "XAUTH_USER_PASSWORD" },
2834     { 16523,    "XAUTH_PASSCODE" },
2835     { 16524,    "XAUTH_MESSAGE" },
2836     { 16525,    "XAUTH_CHALLANGE" },
2837     { 16526,    "XAUTH_DOMAIN" },
2838     { 16527,    "XAUTH_STATUS" },
2839     { 16528,    "XAUTH_NEXT_PIN" },
2840     { 16529,    "XAUTH_ANSWER" },
2841     { 0,        NULL },
2842   };
2843
2844   static const value_string vs_v2_cfgattr[] = {
2845     { 0,        "RESERVED" },
2846     { 1,        "INTERNAL_IP4_ADDRESS" },
2847     { 2,        "INTERNAL_IP4_NETMASK" },
2848     { 3,        "INTERNAL_IP4_DNS" },
2849     { 4,        "INTERNAL_IP4_NBNS" },
2850     { 5,        "INTERNAL_ADDRESS_EXPIREY" },
2851     { 6,        "INTERNAL_IP4_DHCP" },
2852     { 7,        "APPLICATION_VERSION" },
2853     { 8,        "INTERNAL_IP6_ADDRESS" },
2854     { 9,        "RESERVED" },
2855     { 10,       "INTERNAL_IP6_DNS" },
2856     { 11,       "INTERNAL_IP6_NBNS" },
2857     { 12,       "INTERNAL_IP6_DHCP" },
2858     { 13,       "INTERNAL_IP4_SUBNET" },
2859     { 14,       "SUPPORTED_ATTRIBUTES" },
2860     { 15,       "INTERNAL_IP6_SUBNET" },
2861     { 0,        NULL },
2862   };
2863
2864   if (isakmp_version == 1) {
2865     if (ident >= 15 && ident <= 16383)
2866       return "Future use";
2867     if (ident >= 16384 && ident <= 16519)
2868       return "PRIVATE USE";
2869     if (ident >= 16530 && ident <= 32767)
2870       return "PRIVATE USE";
2871     return val_to_str(ident, vs_v1_cfgattr, "UNKNOWN-CFG-ATTRIBUTE");
2872   } else if (isakmp_version == 2) {
2873     if (ident >= 16 && ident <= 16383)
2874       return "RESERVED TO IANA";
2875     if (ident >= 16384 && ident <= 32767)
2876       return "PRIVATE USE";
2877     return val_to_str(ident, vs_v2_cfgattr, "UNKNOWN-CFG-ATTRIBUTE");
2878   }
2879   return "UNKNOWN-ISAKMP-VERSION";
2880 }
2881
2882 static const char *
2883 certtype2str(int isakmp_version, guint8 type)
2884 {
2885   static const value_string vs_v1_certtype[] = {
2886     { 0,        "NONE" },
2887     { 1,        "PKCS #7 wrapped X.509 certificate" },
2888     { 2,        "PGP Certificate" },
2889     { 3,        "DNS Signed Key" },
2890     { 4,        "X.509 Certificate - Signature" },
2891     { 5,        "X.509 Certificate - Key Exchange" },
2892     { 6,        "Kerberos Tokens" },
2893     { 7,        "Certificate Revocation List (CRL)" },
2894     { 8,        "Authority Revocation List (ARL)" },
2895     { 9,        "SPKI Certificate" },
2896     { 10,       "X.509 Certificate - Attribute" },
2897     { 0,        NULL },
2898   };
2899
2900   static const value_string vs_v2_certtype[] = {
2901     { 0,        "RESERVED" },
2902     { 1,        "PKCS #7 wrapped X.509 certificate" },
2903     { 2,        "PGP Certificate" },
2904     { 3,        "DNS Signed Key" },
2905     { 4,        "X.509 Certificate - Signature" },
2906     { 5,        "*undefined by any document*" },
2907     { 6,        "Kerberos Tokens" },
2908     { 7,        "Certificate Revocation List (CRL)" },
2909     { 8,        "Authority Revocation List (ARL)" },
2910     { 9,        "SPKI Certificate" },
2911     { 10,       "X.509 Certificate - Attribute" },
2912     { 11,       "Raw RSA Key" },
2913     { 12,       "Hash and URL of X.509 certificate" },
2914     { 13,       "Hash and URL of X.509 bundle" },
2915     { 0,        NULL },
2916   };
2917
2918   if (isakmp_version == 1)
2919     return val_to_str(type, vs_v1_certtype, "RESERVED");
2920   else if (isakmp_version == 2) {
2921     if (type >= 14 && type <= 200)
2922       return "RESERVED to IANA";
2923     if (type >= 201)
2924       return "PRIVATE USE";
2925     return val_to_str(type, vs_v2_certtype, "RESERVED");
2926   }
2927   return "UNKNOWN-ISAKMP-VERSION";
2928 }
2929
2930 static gboolean
2931 get_num(tvbuff_t *tvb, int offset, guint16 len, guint32 *num_p)
2932 {
2933   switch (len) {
2934   case 1:
2935     *num_p = tvb_get_guint8(tvb, offset);
2936     break;
2937   case 2:
2938     *num_p = tvb_get_ntohs(tvb, offset);
2939     break;
2940   case 3:
2941     *num_p = tvb_get_ntoh24(tvb, offset);
2942     break;
2943   case 4:
2944     *num_p = tvb_get_ntohl(tvb, offset);
2945     break;
2946   default:
2947     return FALSE;
2948   }
2949
2950   return TRUE;
2951 }
2952
2953 /*
2954  * Protocol initialization
2955  */
2956
2957 #ifdef HAVE_LIBNETTLE
2958 static guint
2959 isakmp_hash_func(gconstpointer c) {
2960   guint8 *i_cookie = (guint8 *) c;
2961   guint   val = 0, keychunk, i;
2962
2963   /* XOR our icookie down to the size of a guint */
2964   for (i = 0; i < COOKIE_SIZE - (COOKIE_SIZE % sizeof(keychunk)); i += sizeof(keychunk)) {
2965     memcpy(&keychunk, &i_cookie[i], sizeof(keychunk));
2966     val ^= keychunk;
2967   }
2968
2969   return val;
2970 }
2971
2972 static gint
2973 isakmp_equal_func(gconstpointer ic1, gconstpointer ic2) {
2974
2975   if (memcmp(ic1, ic2, COOKIE_SIZE) == 0)
2976     return 1;
2977
2978   return 0;
2979 }
2980 #endif
2981
2982 static void
2983 isakmp_init_protocol(void) {
2984 #ifdef HAVE_LIBNETTLE
2985   if (isakmp_hash) {
2986     g_hash_table_destroy(isakmp_hash);
2987   }
2988   if (isakmp_key_data)
2989     g_mem_chunk_destroy(isakmp_key_data);
2990   if (isakmp_decrypt_data)
2991     g_mem_chunk_destroy(isakmp_decrypt_data);
2992
2993   isakmp_hash = g_hash_table_new(isakmp_hash_func, isakmp_equal_func);
2994   isakmp_key_data = g_mem_chunk_new("isakmp_key_data",
2995         COOKIE_SIZE, 5 * COOKIE_SIZE,
2996         G_ALLOC_AND_FREE);
2997   isakmp_decrypt_data = g_mem_chunk_new("isakmp_decrypt_data",
2998         sizeof(decrypt_data_t), 5 * sizeof(decrypt_data_t),
2999         G_ALLOC_AND_FREE);
3000   if (logf)
3001     fclose(logf);
3002   logf = fopen(pluto_log_path, "r");
3003
3004   scan_pluto_log();
3005 #endif /* HAVE_LIBNETTLE */
3006 }
3007
3008 static void
3009 isakmp_prefs_apply_cb(void) {
3010 #ifdef HAVE_LIBNETTLE
3011   isakmp_init_protocol();
3012 #endif /* HAVE_LIBNETTLE */
3013 }
3014
3015 void
3016 proto_register_isakmp(void)
3017 {
3018   module_t *isakmp_module;
3019
3020   static hf_register_info hf[] = {
3021     { &hf_isakmp_icookie,
3022       { "Initiator cookie", "isakmp.icookie",
3023         FT_BYTES, BASE_HEX, NULL, 0x0,
3024         "ISAKMP Initiator Cookie", HFILL }},
3025     { &hf_isakmp_rcookie,
3026       { "Responder cookie", "isakmp.rcookie",
3027         FT_BYTES, BASE_HEX, NULL, 0x0,
3028         "ISAKMP Responder Cookie", HFILL }},
3029     { &hf_isakmp_nextpayload,
3030       { "Next payload", "isakmp.nextpayload",
3031         FT_UINT8, BASE_DEC, NULL, 0x0,
3032         "ISAKMP Next Payload", HFILL }},
3033     { &hf_isakmp_version,
3034       { "Version", "isakmp.version",
3035         FT_UINT8, BASE_HEX, NULL, 0x0,
3036         "ISAKMP Version (major + minor)", HFILL }},
3037     { &hf_isakmp_exchangetype,
3038       { "Exchange type", "isakmp.exchangetype",
3039         FT_UINT8, BASE_DEC, NULL, 0x0,
3040         "ISAKMP Exchange Type", HFILL }},
3041     { &hf_isakmp_flags,
3042       { "Flags", "isakmp.flags",
3043         FT_UINT8, BASE_HEX, NULL, 0x0,
3044         "ISAKMP Flags", HFILL }},
3045     { &hf_isakmp_messageid,
3046       { "Message ID", "isakmp.messageid",
3047         FT_UINT32, BASE_HEX, NULL, 0x0,
3048         "ISAKMP Message ID", HFILL }},
3049     { &hf_isakmp_length,
3050       { "Length", "isakmp.length",
3051         FT_UINT32, BASE_DEC, NULL, 0x0,
3052         "ISAKMP Length", HFILL }},
3053     { &hf_isakmp_payloadlen,
3054       { "Payload length", "isakmp.payloadlength",
3055         FT_UINT16, BASE_DEC, NULL, 0x0,
3056         "ISAKMP Payload Length", HFILL }},
3057     { &hf_isakmp_doi,
3058       { "Domain of interpretation", "isakmp.doi",
3059         FT_UINT32, BASE_DEC, NULL, 0x0,
3060         "ISAKMP Domain of Interpretation", HFILL }},
3061     { &hf_isakmp_sa_situation,
3062       { "Situation", "isakmp.sa.situation",
3063         FT_BYTES, BASE_HEX, NULL, 0x0,
3064         "ISAKMP SA Situation", HFILL }},
3065     { &hf_isakmp_prop_number,
3066       { "Proposal number", "isakmp.prop.number",
3067         FT_UINT8, BASE_DEC, NULL, 0x0,
3068         "ISAKMP Proposal Number", HFILL }},
3069     { &hf_isakmp_spisize,
3070       { "SPI Size", "isakmp.spisize",
3071         FT_UINT8, BASE_DEC, NULL, 0x0,
3072         "ISAKMP SPI Size", HFILL }},
3073     { &hf_isakmp_prop_transforms,
3074       { "Proposal transforms", "isakmp.prop.transforms",
3075         FT_UINT8, BASE_DEC, NULL, 0x0,
3076         "ISAKMP Proposal Transforms", HFILL }},
3077     { &hf_isakmp_trans_number,
3078       { "Transform number", "isakmp.trans.number",
3079         FT_UINT8, BASE_DEC, NULL, 0x0,
3080         "ISAKMP Transform Number", HFILL }},
3081     { &hf_isakmp_trans_id,
3082       { "Transform ID", "isakmp.trans.id",
3083         FT_UINT8, BASE_DEC, NULL, 0x0,
3084         "ISAKMP Transform ID", HFILL }},
3085     { &hf_isakmp_id_type,
3086       { "ID type", "isakmp.id.type",
3087         FT_UINT8, BASE_DEC, NULL, 0x0,
3088         "ISAKMP ID Type", HFILL }},
3089     { &hf_isakmp_protoid,
3090       { "Protocol ID", "isakmp.protoid",
3091         FT_UINT8, BASE_DEC, NULL, 0x0,
3092         "ISAKMP Protocol ID", HFILL }},
3093     { &hf_isakmp_id_port,
3094       { "Port", "isakmp.id.port",
3095         FT_UINT16, BASE_DEC, NULL, 0x0,
3096         "ISAKMP ID Port", HFILL }},
3097     { &hf_isakmp_cert_encoding,
3098       { "Port", "isakmp.cert.encoding",
3099         FT_UINT8, BASE_DEC, NULL, 0x0,
3100         "ISAKMP Certificate Encoding", HFILL }},
3101     { &hf_isakmp_certreq_type,
3102       { "Port", "isakmp.certreq.type",
3103         FT_UINT8, BASE_DEC, NULL, 0x0,
3104         "ISAKMP Certificate Request Type", HFILL }},
3105     { &hf_isakmp_notify_msgtype,
3106       { "Port", "isakmp.notify.msgtype",
3107         FT_UINT8, BASE_DEC, NULL, 0x0,
3108         "ISAKMP Notify Message Type", HFILL }},
3109     { &hf_isakmp_num_spis,
3110       { "Port", "isakmp.spinum",
3111         FT_UINT16, BASE_DEC, NULL, 0x0,
3112         "ISAKMP Number of SPIs", HFILL }},
3113
3114     { &hf_ike_certificate_authority,
3115       { "Certificate Authority Distinguished Name", "ike.cert_authority_dn", FT_UINT32, BASE_DEC, NULL, 0x0, "Certificate Authority Distinguished Name", HFILL }
3116     },
3117     { &hf_ike_v2_certificate_authority,
3118       { "Certificate Authority", "ike.cert_authority", FT_BYTES, BASE_HEX, NULL, 0x0, "SHA-1 hash of the Certificate Authority", HFILL }
3119     },
3120     { &hf_ike_nat_keepalive,
3121       { "NAT Keepalive", "ike.nat_keepalive", FT_NONE, BASE_HEX, NULL, 0x0, "NAT Keepalive packet", HFILL }
3122     },
3123   };
3124
3125
3126   static gint *ett[] = {
3127     &ett_isakmp,
3128     &ett_isakmp_flags,
3129     &ett_isakmp_payload,
3130   };
3131
3132   proto_isakmp = proto_register_protocol("Internet Security Association and Key Management Protocol",
3133                                                "ISAKMP", "isakmp");
3134   proto_register_field_array(proto_isakmp, hf, array_length(hf));
3135   proto_register_subtree_array(ett, array_length(ett));
3136   register_init_routine(&isakmp_init_protocol);
3137
3138   register_dissector("isakmp", dissect_isakmp, proto_isakmp);
3139
3140   isakmp_module = prefs_register_protocol(proto_isakmp, isakmp_prefs_apply_cb);
3141 #ifdef HAVE_LIBNETTLE
3142   prefs_register_string_preference(isakmp_module, "log",
3143     "Log Filename",
3144     "Path to a pluto log file containing DH secret information",
3145     &pluto_log_path);
3146 #endif /* HAVE_LIBNETTLE */
3147 }
3148
3149 void
3150 proto_reg_handoff_isakmp(void)
3151 {
3152   dissector_handle_t isakmp_handle;
3153
3154   isakmp_handle = find_dissector("isakmp");
3155   dissector_add("udp.port", UDP_PORT_ISAKMP, isakmp_handle);
3156   dissector_add("tcp.port", TCP_PORT_ISAKMP, isakmp_handle);
3157 }