7abecf39f6bb703f7a882c2210032f5937b5b00f
[obnox/wireshark/wip.git] / packet-isakmp.c
1 /* packet-isakmp.c
2  * Routines for the Internet Security Association and Key Management Protocol
3  * (ISAKMP) (RFC 2408)
4  * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
5  *
6  * $Id: packet-isakmp.c,v 1.33 2001/01/03 06:55:29 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #include <stdio.h>
37
38 #ifdef HAVE_NETINET_IN_H
39 #include <netinet/in.h>
40 #endif
41
42 #include <glib.h>
43
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
46 #endif
47
48 #include "packet.h"
49
50 static int proto_isakmp = -1;
51
52 static gint ett_isakmp = -1;
53 static gint ett_isakmp_flags = -1;
54 static gint ett_isakmp_payload = -1;
55
56 #define UDP_PORT_ISAKMP 500
57
58 #define NUM_PROTO_TYPES 5
59 #define proto2str(t)    \
60   ((t < NUM_PROTO_TYPES) ? prototypestr[t] : "UNKNOWN-PROTO-TYPE")
61
62 static const char *prototypestr[NUM_PROTO_TYPES] = {
63   "RESERVED",
64   "ISAKMP",
65   "IPSEC_AH",
66   "IPSEC_ESP",
67   "IPCOMP"
68 };
69
70 #define NUM_P1_ATT_TYPES        17
71 #define p1_atttype2str(t)       \
72   ((t < NUM_P1_ATT_TYPES) ? p1_atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE")
73
74 static const char *p1_atttypestr[NUM_P1_ATT_TYPES] = {
75   "UNKNOWN-ATTRIBUTE-TYPE",
76   "Encryption-Algorithm",
77   "Hash-Algorithm",
78   "Authentication-Method",
79   "Group-Description",
80   "Group-Type",
81   "Group-Prime",
82   "Group-Generator-One",
83   "Group-Generator-Two",
84   "Group-Curve-A",
85   "Group-Curve-B",
86   "Life-Type",
87   "Life-Duration",
88   "PRF",
89   "Key-Length",
90   "Field-Size",
91   "Group-Order"
92 };
93
94 #define NUM_ATT_TYPES   11
95 #define atttype2str(t)  \
96   ((t < NUM_ATT_TYPES) ? atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE")
97
98 static const char *atttypestr[NUM_ATT_TYPES] = {
99   "UNKNOWN-ATTRIBUTE-TYPE",
100   "SA-Life-Type",
101   "SA-Life-Duration",
102   "Group-Description",
103   "Encapsulation-Mode",
104   "Authentication-Algorithm",
105   "Key-Length",
106   "Key-Rounds",
107   "Compress-Dictinary-Size",
108   "Compress-Private-Algorithm",
109   "ECN Tunnel"
110 };
111
112 #define NUM_TRANS_TYPES 2
113 #define trans2str(t)    \
114   ((t < NUM_TRANS_TYPES) ? transtypestr[t] : "UNKNOWN-TRANS-TYPE")
115
116 static const char *transtypestr[NUM_TRANS_TYPES] = {
117   "RESERVED",
118   "KEY_IKE"
119 };
120
121 #define NUM_AH_TRANS_TYPES      8
122 #define ah_trans2str(t)         \
123   ((t < NUM_AH_TRANS_TYPES) ? ah_transtypestr[t] : "UNKNOWN-AH-TRANS-TYPE")
124
125 static const char *ah_transtypestr[NUM_AH_TRANS_TYPES] = {
126   "RESERVED",
127   "RESERVED",
128   "MD5",
129   "SHA",
130   "DES",
131   "SHA2-256",
132   "SHA2-384",
133   "SHA2-512"
134 };
135
136 #define NUM_ESP_TRANS_TYPES     13
137 #define esp_trans2str(t)        \
138   ((t < NUM_ESP_TRANS_TYPES) ? esp_transtypestr[t] : "UNKNOWN-ESP-TRANS-TYPE")
139
140 static const char *esp_transtypestr[NUM_ESP_TRANS_TYPES] = {
141   "RESERVED",
142   "DES-IV64",
143   "DES",
144   "3DES",
145   "RC5",
146   "IDEA",
147   "CAST",
148   "BLOWFISH",
149   "3IDEA",
150   "DES-IV32",
151   "RC4",
152   "NULL",
153   "AES"
154 };
155
156 #define NUM_ID_TYPES    12
157 #define id2str(t)       \
158   ((t < NUM_ID_TYPES) ? idtypestr[t] : "UNKNOWN-ID-TYPE")
159
160 static const char *idtypestr[NUM_ID_TYPES] = {
161   "RESERVED",
162   "IPV4_ADDR",
163   "FQDN",
164   "USER_FQDN",
165   "IPV4_ADDR_SUBNET",
166   "IPV6_ADDR",
167   "IPV6_ADDR_SUBNET",
168   "IPV4_ADDR_RANGE",
169   "IPV6_ADDR_RANGE",
170   "DER_ASN1_DN",
171   "DER_ASN1_GN",
172   "KEY_ID"
173 };
174
175 struct isakmp_hdr {
176   guint8        icookie[8];
177   guint8        rcookie[8];
178   guint8        next_payload;
179   guint8        version;
180   guint8        exch_type;
181   guint8        flags;
182 #define E_FLAG          0x01
183 #define C_FLAG          0x02
184 #define A_FLAG          0x04
185   guint8        message_id[4];
186   guint8        length[4];
187 };
188
189 struct sa_hdr {
190   guint8        next_payload;
191   guint8        reserved;
192   guint8        length[2];
193   guint8        doi[4];
194   guint8        situation[4];
195 };
196
197 struct proposal_hdr {
198   guint8        next_payload;
199   guint8        reserved;
200   guint8        length[2];
201   guint8        proposal_num;
202   guint8        protocol_id;
203   guint8        spi_size;
204   guint8        num_transforms;
205 };
206
207 struct trans_hdr {
208   guint8        next_payload;
209   guint8        reserved;
210   guint8        length[2];
211   guint8        transform_num;
212   guint8        transform_id;
213   guint8        reserved2[2];
214 };
215
216 #define TRANS_LEN(p)    (pntohs(&((struct trans_hdr *)(p))->length))
217
218 struct ke_hdr {
219   guint8        next_payload;
220   guint8        reserved;
221   guint8        length[2];
222 };
223
224 struct id_hdr {
225   guint8        next_payload;
226   guint8        reserved;
227   guint8        length[2];
228   guint8        id_type;
229   guint8        protocol_id;
230   guint8        port[2];
231 };
232
233 struct cert_hdr {
234   guint8        next_payload;
235   guint8        reserved;
236   guint8        length[2];
237   guint8        cert_enc;
238 };
239
240 struct certreq_hdr {
241   guint8        next_payload;
242   guint8        reserved;
243   guint8        length[2];
244   guint8        cert_type;
245 };
246
247 struct hash_hdr {
248   guint8        next_payload;
249   guint8        reserved;
250   guint8        length[2];
251 };
252
253 struct sig_hdr {
254   guint8        next_payload;
255   guint8        reserved;
256   guint8        length[2];
257 };
258
259 struct nonce_hdr {
260   guint8        next_payload;
261   guint8        reserved;
262   guint8        length[2];
263 };
264
265 struct notif_hdr {
266   guint8        next_payload;
267   guint8        reserved;
268   guint8        length[2];
269   guint8        doi[4];
270   guint8        protocol_id;
271   guint8        spi_size;
272   guint8        msgtype[2];
273 };
274
275 struct delete_hdr {
276   guint8        next_payload;
277   guint8        reserved;
278   guint8        length[2];
279   guint8        doi[4];
280   guint8        protocol_id;
281   guint8        spi_size;
282   guint8        num_spis[2];
283 };
284
285 struct vid_hdr {
286   guint8        next_payload;
287   guint8        reserved;
288   guint8        length[2];
289 };
290
291 struct cfg_hdr {
292   guint8        next_payload;
293   guint8        reserved;
294   guint8        length[2];
295   guint8        type;
296   guint8        reserved2;
297   guint8        identifier[2];
298 };
299
300 static void dissect_none(const u_char *, int, frame_data *, proto_tree *);
301 static void dissect_sa(const u_char *, int, frame_data *, proto_tree *);
302 static void dissect_proposal(const u_char *, int, frame_data *, proto_tree *);
303 static void dissect_transform(const u_char *, int, frame_data *, proto_tree *,
304                 guint8);
305 static void dissect_key_exch(const u_char *, int, frame_data *, proto_tree *);
306 static void dissect_id(const u_char *, int, frame_data *, proto_tree *);
307 static void dissect_cert(const u_char *, int, frame_data *, proto_tree *);
308 static void dissect_certreq(const u_char *, int, frame_data *, proto_tree *);
309 static void dissect_hash(const u_char *, int, frame_data *, proto_tree *);
310 static void dissect_sig(const u_char *, int, frame_data *, proto_tree *);
311 static void dissect_nonce(const u_char *, int, frame_data *, proto_tree *);
312 static void dissect_notif(const u_char *, int, frame_data *, proto_tree *);
313 static void dissect_delete(const u_char *, int, frame_data *, proto_tree *);
314 static void dissect_vid(const u_char *, int, frame_data *, proto_tree *);
315 static void dissect_config(const u_char *, int, frame_data *, proto_tree *);
316
317 static const char *payloadtype2str(guint8);
318 static const char *exchtype2str(guint8);
319 static const char *doitype2str(guint32);
320 static const char *msgtype2str(guint16);
321 static const char *situation2str(guint32);
322 static const char *value2str(int, guint16, guint16);
323 static const char *num2str(const guint8 *, guint16);
324 static const char *attrtype2str(guint8);
325 static const char *cfgattrident2str(guint16);
326
327 #define NUM_LOAD_TYPES          15
328 #define loadtype2str(t) \
329   ((t < NUM_LOAD_TYPES) ? strfuncs[t].str : "Unknown payload type")
330 #define LOAD_TYPE_TRANSFORM     3
331
332 static struct strfunc {
333   const char *  str;
334   void          (*func)(const u_char *, int, frame_data *, proto_tree *);
335 } strfuncs[NUM_LOAD_TYPES] = {
336   {"NONE",                      dissect_none      },
337   {"Security Association",      dissect_sa        },
338   {"Proposal",                  dissect_proposal  },
339   {"Transform",                 NULL },
340   {"Key Exchange",              dissect_key_exch  },
341   {"Identification",            dissect_id        },
342   {"Certificate",               dissect_cert      },
343   {"Certificate Request",       dissect_certreq   },
344   {"Hash",                      dissect_hash      },
345   {"Signature",                 dissect_sig       },
346   {"Nonce",                     dissect_nonce     },
347   {"Notification",              dissect_notif     },
348   {"Delete",                    dissect_delete    },
349   {"Vendor ID",                 dissect_vid       },
350   {"Attrib",                    dissect_config    }
351 };
352
353 static void
354 dissect_isakmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
355   
356   struct isakmp_hdr *   hdr = (struct isakmp_hdr *)(pd + offset);
357   guint32               len;
358
359   OLD_CHECK_DISPLAY_AS_DATA(proto_isakmp, pd, offset, fd, tree);
360   
361   if (check_col(fd, COL_PROTOCOL))
362     col_set_str(fd, COL_PROTOCOL, "ISAKMP");
363   
364   len = pntohl(&hdr->length);
365   
366   if (check_col(fd, COL_INFO))
367     col_add_fstr(fd, COL_INFO, "%s", exchtype2str(hdr->exch_type));
368   
369   if (IS_DATA_IN_FRAME(offset) && tree) {
370     proto_item *        ti;
371     proto_tree *        isakmp_tree;
372     
373     ti = proto_tree_add_item(tree, proto_isakmp, NullTVB, offset, len, FALSE);
374     isakmp_tree = proto_item_add_subtree(ti, ett_isakmp);
375     
376     proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->icookie),
377                         "Initiator cookie");
378     offset += sizeof(hdr->icookie);
379     
380     proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->rcookie),
381                         "Responder cookie");
382     offset += sizeof(hdr->rcookie);
383
384     proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->next_payload),
385                         "Next payload: %s (%u)",
386                         payloadtype2str(hdr->next_payload), hdr->next_payload);
387     offset += sizeof(hdr->next_payload);
388
389     proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->version),
390                         "Version: %u.%u",
391                         hi_nibble(hdr->version), lo_nibble(hdr->version));
392     offset += sizeof(hdr->version);
393     
394     proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->exch_type),
395                         "Exchange type: %s (%u)",
396                         exchtype2str(hdr->exch_type), hdr->exch_type);
397     offset += sizeof(hdr->exch_type);
398     
399     {
400       proto_item *      fti;
401       proto_tree *      ftree;
402       
403       fti   = proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->flags), "Flags");
404       ftree = proto_item_add_subtree(fti, ett_isakmp_flags);
405       
406       proto_tree_add_text(ftree, NullTVB, offset, 1, "%s",
407                           decode_boolean_bitfield(hdr->flags, E_FLAG, sizeof(hdr->flags)*8,
408                                                   "Encryption", "No encryption"));
409       proto_tree_add_text(ftree, NullTVB, offset, 1, "%s",
410                           decode_boolean_bitfield(hdr->flags, C_FLAG, sizeof(hdr->flags)*8,
411                                                   "Commit", "No commit"));
412       proto_tree_add_text(ftree, NullTVB, offset, 1, "%s",
413                           decode_boolean_bitfield(hdr->flags, A_FLAG, sizeof(hdr->flags)*8,
414                                                   "Authentication", "No authentication"));
415       offset += sizeof(hdr->flags);
416     }
417
418     proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->message_id),
419         "Message ID: 0x%02x%02x%02x%02x", hdr->message_id[0],
420         hdr->message_id[1], hdr->message_id[2], hdr->message_id[3]);
421     offset += sizeof(hdr->message_id);
422     
423     proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->length),
424                         "Length: %u", len);
425     offset += sizeof(hdr->length);
426
427     if (hdr->flags & E_FLAG) {
428       if (IS_DATA_IN_FRAME(offset) && isakmp_tree) {
429         proto_tree_add_text(isakmp_tree, NullTVB, offset, END_OF_FRAME,
430                         "Encrypted payload (%d byte%s)",
431                         END_OF_FRAME, plurality(END_OF_FRAME, "", "s"));
432       }
433     } else {
434       if (hdr->next_payload < NUM_LOAD_TYPES) {
435         if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
436           dissect_transform(pd, offset, fd, isakmp_tree, 0);    /* XXX - protocol ID? */
437         else
438           (*strfuncs[hdr->next_payload].func)(pd, offset, fd, isakmp_tree);
439       }
440       else
441         old_dissect_data(pd, offset, fd, isakmp_tree);
442     }
443   }
444 }
445
446 static void
447 dissect_none(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
448 }
449
450 static void
451 dissect_sa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
452
453   struct sa_hdr *       hdr       = (struct sa_hdr *)(pd + offset);
454   guint16               length    = pntohs(&hdr->length);
455   guint32               doi       = pntohl(&hdr->doi);
456   guint32               situation = pntohl(&hdr->situation);
457   proto_item *          ti        = proto_tree_add_text(tree, NullTVB, offset, length, "Security Association payload");
458   proto_tree *          ntree;
459
460   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
461   
462   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
463                       "Next payload: %s (%u)",
464                       payloadtype2str(hdr->next_payload), hdr->next_payload);
465   offset += sizeof(hdr->next_payload) * 2;
466   
467   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
468                       "Length: %u", length);
469   offset += sizeof(length);
470   
471   proto_tree_add_text(ntree, NullTVB, offset, sizeof(doi),
472                       "Domain of interpretation: %s (%u)",
473                       doitype2str(doi), doi);
474   offset += sizeof(doi);
475   
476   proto_tree_add_text(ntree, NullTVB, offset, sizeof(situation),
477                       "Situation: %s (%u)",
478                       situation2str(situation), situation);
479   offset += sizeof(situation);
480   
481   dissect_proposal(pd, offset, fd, ntree);
482   offset += (length - sizeof(*hdr));
483   
484   if (hdr->next_payload < NUM_LOAD_TYPES) {
485     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
486       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
487     else
488       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
489   }
490   else
491     old_dissect_data(pd, offset, fd, tree);
492 }
493
494 static void
495 dissect_proposal(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
496
497   struct proposal_hdr * hdr     = (struct proposal_hdr *)(pd + offset);
498   guint16               length  = pntohs(&hdr->length);
499   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Proposal payload");
500   proto_tree *          ntree;
501
502   int                   next_hdr_offset = offset + length;
503
504   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
505   
506   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
507                       "Next payload: %s (%u)",
508                       payloadtype2str(hdr->next_payload), hdr->next_payload);
509   offset += sizeof(hdr->next_payload) * 2;
510   
511   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
512                       "Length: %u", length);
513   offset += sizeof(length);
514   
515   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->proposal_num),
516                       "Proposal number: %u", hdr->proposal_num);
517   offset += sizeof(hdr->proposal_num);
518   
519   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->protocol_id),
520                       "Protocol ID: %s (%u)",
521                       proto2str(hdr->protocol_id), hdr->protocol_id);
522   offset += sizeof(hdr->protocol_id);
523   
524   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->spi_size),
525                       "SPI size: %u", hdr->spi_size);
526   offset += sizeof(hdr->spi_size);
527
528   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->num_transforms),
529                       "Number of transforms: %u", hdr->num_transforms);
530   offset += sizeof(hdr->num_transforms);
531
532   if (hdr->spi_size) {
533     proto_tree_add_text(ntree, NullTVB, offset, hdr->spi_size, "SPI");
534     offset += hdr->spi_size;
535   }
536
537   if (hdr->num_transforms > 0)
538     dissect_transform(pd, offset, fd, ntree, hdr->protocol_id);
539
540   if (hdr->next_payload < NUM_LOAD_TYPES) {
541     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
542       dissect_transform(pd, next_hdr_offset, fd, tree, 0);      /* XXX - protocol ID? */
543     else
544       (*strfuncs[hdr->next_payload].func)(pd, next_hdr_offset, fd, tree);
545   }
546   else
547     old_dissect_data(pd, next_hdr_offset, fd, tree);
548 }
549
550 static void
551 dissect_transform(const u_char *pd, int offset, frame_data *fd,
552                 proto_tree *tree, guint8 protocol_id)
553 {
554
555   struct trans_hdr *    hdr     = (struct trans_hdr *)(pd + offset);
556   guint16               length  = pntohs(&hdr->length);
557   int                   slength = length;
558   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Transform payload");
559   proto_tree *          ntree;
560
561   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
562   
563   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
564                       "Next payload: %s (%u)",
565                       payloadtype2str(hdr->next_payload), hdr->next_payload);
566   offset += sizeof(hdr->next_payload) * 2;
567   
568   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
569                       "Length: %u", length);
570   offset += sizeof(length);
571   
572   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->transform_num),
573                       "Transform number: %u", hdr->transform_num);
574   offset += sizeof(hdr->transform_num);
575
576   switch (protocol_id) {
577   default:
578   case 1:       /* ISAKMP */
579     proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->transform_id),
580                         "Transform ID: %s (%u)",
581                         trans2str(hdr->transform_id), hdr->transform_id);
582     break;
583   case 2:       /* AH */
584     proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->transform_id),
585                         "Transform ID: %s (%u)",
586                         ah_trans2str(hdr->transform_id), hdr->transform_id);
587     break;
588   case 3:       /* ESP */
589     proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->transform_id),
590                         "Transform ID: %s (%u)",
591                         esp_trans2str(hdr->transform_id), hdr->transform_id);
592     break;
593   }
594   offset += sizeof(hdr->transform_id) + sizeof(hdr->reserved2);
595   
596   slength -= sizeof(*hdr);
597   while (slength>0) {
598     const char *str = NULL;
599     int ike_phase1 = 0;
600     guint16 type    = pntohs(pd + offset) & 0x7fff;
601     guint16 val_len = pntohs(pd + offset + 2);
602
603     if (protocol_id == 1 && hdr->transform_id == 1) {
604       ike_phase1 = 1;
605       str = p1_atttype2str(type);
606     }
607     else {
608       str = atttype2str(type);
609     }
610
611     if (pd[offset] & 0x80) {
612       proto_tree_add_text(ntree, NullTVB, offset, 4,
613                           "%s (%u): %s (%u)",
614                           str, type,
615                           value2str(ike_phase1, type, val_len), val_len);
616       offset += 4;
617       slength -= 4;
618     }
619     else {
620       guint16   pack_len = 4 + val_len;
621       
622       proto_tree_add_text(ntree, NullTVB, offset, pack_len,
623                           "%s (%u): %s",
624                           str, type,
625                           num2str(pd + offset + 4, val_len));
626       offset += pack_len;
627       slength -= pack_len;
628     }
629 #if 0 /* the last byte will fail with this test */
630     if (!IS_DATA_IN_FRAME(offset)) {
631             proto_tree_add_text(ntree, NullTVB, 0, 0,
632                             "Bad Offset: %u", offset);
633             return;
634     }
635 #endif
636   }
637
638   if (hdr->next_payload < NUM_LOAD_TYPES) {
639     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
640       dissect_transform(pd, offset, fd, tree, protocol_id);
641     else
642       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
643   }
644   else
645     old_dissect_data(pd, offset, fd, tree);
646 }
647
648 static void
649 dissect_key_exch(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
650
651   struct ke_hdr *       hdr     = (struct ke_hdr *)(pd + offset);
652   guint16               length  = pntohs(&hdr->length);
653   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Key Exchange payload");
654   proto_tree *          ntree;
655
656   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
657   
658   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
659                       "Next payload: %s (%u)",
660                       payloadtype2str(hdr->next_payload), hdr->next_payload);
661   offset += sizeof(hdr->next_payload) * 2;
662   
663   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
664                       "Length: %u", length);
665   offset += sizeof(length);
666   
667   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Key Exchange Data");
668   offset += (length - sizeof(*hdr));
669   
670   if (hdr->next_payload < NUM_LOAD_TYPES) {
671     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
672       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
673     else
674       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
675   }
676   else
677     old_dissect_data(pd, offset, fd, tree);
678 }
679
680 static void
681 dissect_id(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
682
683   struct id_hdr *       hdr     = (struct id_hdr *)(pd + offset);
684   guint16               length  = pntohs(&hdr->length);
685   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Identification payload");
686   proto_tree *          ntree;
687
688   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
689   
690   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
691                       "Next payload: %s (%u)",
692                       payloadtype2str(hdr->next_payload), hdr->next_payload);
693   offset += sizeof(hdr->next_payload) * 2;
694   
695   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
696                       "Length: %u", length);
697   offset += sizeof(length);
698   
699   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->id_type),
700                       "ID type: %s (%u)", id2str(hdr->id_type), hdr->id_type);
701   offset += sizeof(hdr->id_type);
702
703   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->protocol_id),
704                       "Protocol ID: %u", hdr->protocol_id);
705   offset += sizeof(hdr->protocol_id);
706   
707   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->port),
708                       "Port: %u", pntohs(&hdr->port));
709   offset += sizeof(hdr->port);
710   
711   switch (hdr->id_type) {
712     case 1:
713     case 4:
714       proto_tree_add_text(ntree, NullTVB, offset, length-sizeof(*hdr),
715                           "Identification data: %s", ip_to_str(pd+offset));
716       break;
717     case 2:
718     case 3:
719       proto_tree_add_text(ntree, NullTVB, offset, length-sizeof(*hdr),
720                           "Identification data: %s", (char *)(pd+offset));
721       break;
722     default:
723       proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Identification Data");
724   }
725   offset += (length - sizeof(*hdr));
726   
727   if (hdr->next_payload < NUM_LOAD_TYPES) {
728     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
729       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
730     else
731       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
732   }
733   else
734     old_dissect_data(pd, offset, fd, tree);
735 }
736
737 static void
738 dissect_cert(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
739
740   struct cert_hdr *     hdr     = (struct cert_hdr *)(pd + offset);
741   guint16               length  = pntohs(&hdr->length);
742   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Certificate payload");
743   proto_tree *          ntree;
744
745   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
746   
747   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
748                       "Next payload: %s (%u)",
749                       payloadtype2str(hdr->next_payload), hdr->next_payload);
750   offset += sizeof(hdr->next_payload) * 2;
751   
752   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
753                       "Length: %u", length);
754   offset += sizeof(length);
755   
756   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->cert_enc),
757                       "Certificate encoding: %u", hdr->cert_enc);
758   offset += sizeof(hdr->cert_enc);
759
760   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Certificate Data");
761   offset += (length - sizeof(*hdr));
762   
763   if (hdr->next_payload < NUM_LOAD_TYPES) {
764     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
765       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
766     else
767       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
768   }
769   else
770     old_dissect_data(pd, offset, fd, tree);
771 }
772
773 static void
774 dissect_certreq(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
775
776   struct certreq_hdr *  hdr     = (struct certreq_hdr *)(pd + offset);
777   guint16               length  = pntohs(&hdr->length);
778   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Certificate Request payload");
779   proto_tree *          ntree;
780
781   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
782   
783   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
784                       "Next payload: %s (%u)",
785                       payloadtype2str(hdr->next_payload), hdr->next_payload);
786   offset += sizeof(hdr->next_payload) * 2;
787   
788   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
789                       "Length: %u", length);
790   offset += sizeof(length);
791   
792   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->cert_type),
793                       "Certificate type: %u", hdr->cert_type);
794   offset += sizeof(hdr->cert_type);
795
796   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Certificate Authority");
797   offset += (length - sizeof(*hdr));
798   
799   if (hdr->next_payload < NUM_LOAD_TYPES) {
800     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
801       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
802     else
803       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
804   }
805   else
806     old_dissect_data(pd, offset, fd, tree);
807 }
808
809 static void
810 dissect_hash(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
811
812   struct hash_hdr *     hdr     = (struct hash_hdr *)(pd + offset);
813   guint16               length  = pntohs(&hdr->length);
814   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Hash payload");
815   proto_tree *          ntree;
816
817   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
818   
819   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
820                       "Next payload: %s (%u)",
821                       payloadtype2str(hdr->next_payload), hdr->next_payload);
822   offset += sizeof(hdr->next_payload) * 2;
823   
824   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
825                       "Length: %u", length);
826   offset += sizeof(length);
827   
828   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Hash Data");
829   offset += (length - sizeof(*hdr));
830   
831   if (hdr->next_payload < NUM_LOAD_TYPES) {
832     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
833       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
834     else
835       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
836   }
837   else
838     old_dissect_data(pd, offset, fd, tree);
839 }
840
841 static void
842 dissect_sig(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
843
844   struct sig_hdr *      hdr     = (struct sig_hdr *)(pd + offset);
845   guint16               length  = pntohs(&hdr->length);
846   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Signature payload");
847   proto_tree *          ntree;
848
849   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
850   
851   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
852                       "Next payload: %s (%u)",
853                       payloadtype2str(hdr->next_payload), hdr->next_payload);
854   offset += sizeof(hdr->next_payload) * 2;
855   
856   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
857                       "Length: %u", length);
858   offset += sizeof(length);
859   
860   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Signature Data");
861   offset += (length - sizeof(*hdr));
862   
863   if (hdr->next_payload < NUM_LOAD_TYPES) {
864     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
865       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
866     else
867       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
868   }
869   else
870     old_dissect_data(pd, offset, fd, tree);
871 }
872
873 static void
874 dissect_nonce(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
875
876   struct nonce_hdr *    hdr     = (struct nonce_hdr *)(pd + offset);
877   guint16               length  = pntohs(&hdr->length);
878   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Nonce payload");
879   proto_tree *          ntree;
880
881   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
882   
883   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
884                       "Next payload: %s (%u)",
885                       payloadtype2str(hdr->next_payload), hdr->next_payload);
886   offset += sizeof(hdr->next_payload) * 2;
887   
888   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
889                       "Length: %u", length);
890   offset += sizeof(length);
891   
892   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Nonce Data");
893   offset += (length - sizeof(*hdr));
894   
895   if (hdr->next_payload < NUM_LOAD_TYPES) {
896     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
897       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
898     else
899       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
900   }
901   else
902     old_dissect_data(pd, offset, fd, tree);
903 }
904
905 static void
906 dissect_notif(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
907
908   struct notif_hdr *    hdr     = (struct notif_hdr *)(pd + offset);
909   guint16               length  = pntohs(&hdr->length);
910   guint32               doi     = pntohl(&hdr->doi);
911   guint16               msgtype = pntohs(&hdr->msgtype);
912   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Notification payload");
913   proto_tree *          ntree;
914
915   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
916   
917   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
918                       "Next payload: %s (%u)",
919                       payloadtype2str(hdr->next_payload), hdr->next_payload);
920   offset += sizeof(hdr->next_payload) * 2;
921   
922   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
923                       "Length: %u", length);
924   offset += sizeof(length);
925   
926   proto_tree_add_text(ntree, NullTVB, offset, sizeof(doi),
927                       "Domain of Interpretation: %s (%u)", doitype2str(doi), doi);
928   offset += sizeof(doi);
929
930   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->protocol_id),
931                       "Protocol ID: %s (%u)",
932                       proto2str(hdr->protocol_id), hdr->protocol_id);
933   offset += sizeof(hdr->protocol_id);
934   
935   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->spi_size),
936                       "SPI size: %u", hdr->spi_size);
937   offset += sizeof(hdr->spi_size);
938   
939   proto_tree_add_text(ntree, NullTVB, offset, sizeof(msgtype),
940                       "Message type: %s (%u)", msgtype2str(msgtype), msgtype);
941   offset += sizeof(msgtype);
942
943   if (hdr->spi_size) {
944     proto_tree_add_text(ntree, NullTVB, offset, hdr->spi_size, "Security Parameter Index");
945     offset += hdr->spi_size;
946   }
947
948   if (((int)length - sizeof(*hdr)) > 0) {
949     proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr) - hdr->spi_size,
950                         "Notification Data");
951     offset += (length - sizeof(*hdr) - hdr->spi_size);
952   }
953   
954   if (hdr->next_payload < NUM_LOAD_TYPES) {
955     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
956       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
957     else
958       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
959   }
960   else
961     old_dissect_data(pd, offset, fd, tree);
962 }
963
964 static void
965 dissect_delete(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
966
967   struct delete_hdr *   hdr      = (struct delete_hdr *)(pd + offset);
968   guint16               length   = pntohs(&hdr->length);
969   guint32               doi      = pntohl(&hdr->doi);
970   guint16               num_spis = pntohs(&hdr->num_spis);
971   proto_item *          ti       = proto_tree_add_text(tree, NullTVB, offset, length, "Delete payload");
972   proto_tree *          ntree;
973   guint16               i;
974   
975   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
976   
977   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
978                       "Next payload: %s (%u)",
979                       payloadtype2str(hdr->next_payload), hdr->next_payload);
980   offset += sizeof(hdr->next_payload) * 2;
981   
982   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
983                       "Length: %u", length);
984   offset += sizeof(length);
985   
986   proto_tree_add_text(ntree, NullTVB, offset, sizeof(doi),
987                       "Domain of Interpretation: %s (%u)", doitype2str(doi), doi);
988   offset += sizeof(doi);
989
990   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->protocol_id),
991                       "Protocol ID: %s (%u)",
992                       proto2str(hdr->protocol_id), hdr->protocol_id);
993   offset += sizeof(hdr->protocol_id);
994   
995   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->spi_size),
996                       "SPI size: %u", hdr->spi_size);
997   offset += sizeof(hdr->spi_size);
998   
999   proto_tree_add_text(ntree, NullTVB, offset, num_spis,
1000                       "Number of SPIs: %u", num_spis);
1001   offset += sizeof(hdr->num_spis);
1002   
1003   for (i = 0; i < num_spis; ++i) {
1004     proto_tree_add_text(ntree, NullTVB, offset, hdr->spi_size,
1005                         "SPI (%d)", i);
1006     offset += hdr->spi_size;
1007   }
1008
1009   if (hdr->next_payload < NUM_LOAD_TYPES) {
1010     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
1011       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
1012     else
1013       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
1014   }
1015   else
1016     old_dissect_data(pd, offset, fd, tree);
1017 }
1018
1019 static void
1020 dissect_vid(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1021
1022   struct vid_hdr *      hdr     = (struct vid_hdr *)(pd + offset);
1023   guint16               length  = pntohs(&hdr->length);
1024   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Vendor ID payload");
1025   proto_tree *          ntree;
1026
1027   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
1028   
1029   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
1030                       "Next payload: %s (%u)",
1031                       payloadtype2str(hdr->next_payload), hdr->next_payload);
1032   offset += sizeof(hdr->next_payload) * 2;
1033   
1034   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
1035                       "Length: %u", length);
1036   offset += sizeof(length);
1037   
1038   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Vendor ID");
1039   offset += (length - sizeof(*hdr));
1040   
1041   if (hdr->next_payload < NUM_LOAD_TYPES) {
1042     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
1043       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
1044     else
1045       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
1046   }
1047   else
1048     old_dissect_data(pd, offset, fd, tree);
1049 }
1050
1051 static void
1052 dissect_config(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1053
1054   struct cfg_hdr *      hdr      = (struct cfg_hdr *)(pd + offset);
1055   guint16               length   = pntohs(&hdr->length);
1056   int                   slength  = length;
1057   proto_item *          ti       = proto_tree_add_text(tree, NullTVB, offset, length, "Attribute payload");
1058   proto_tree *          ntree;
1059
1060   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
1061
1062   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
1063                       "Next payload: %s (%u)",
1064                       payloadtype2str(hdr->next_payload), hdr->next_payload);
1065   offset += sizeof(hdr->next_payload) *2;
1066   
1067   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
1068                      "Length: %u", length);
1069   offset += sizeof(length);
1070   
1071   proto_tree_add_text(ntree,NullTVB, offset, sizeof(hdr->type),
1072                       "Type %s (%u)",attrtype2str(hdr->type),hdr->type);
1073   
1074   offset += (sizeof(hdr->type) + sizeof(hdr->reserved2));
1075   
1076   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->identifier),
1077                       "Identifier: %u", pntohs(&hdr->identifier));
1078   offset += sizeof(hdr->identifier);
1079   slength -= sizeof(*hdr);
1080   
1081   while(slength>0) {
1082     guint16 type = pntohs(pd + offset) & 0x7fff;
1083     guint16 val_len = pntohs(pd + offset + 2);
1084     
1085     if(pd[offset] & 0x80) {
1086       proto_tree_add_text(ntree, NullTVB, offset, 4,
1087                           "%s (%u)",cfgattrident2str(type),val_len);
1088       offset += 4;
1089       slength -= 4;
1090     }
1091     else {
1092       guint pack_len = 4 + val_len;
1093
1094       proto_tree_add_text(ntree, NullTVB, offset, 4,
1095                           "%s (%se)", cfgattrident2str(type), num2str(pd + offset + 4, val_len));
1096       offset += pack_len;
1097       slength -= pack_len;
1098     }
1099   }
1100
1101   if (hdr->next_payload < NUM_LOAD_TYPES) {
1102     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
1103       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
1104     else
1105       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
1106   }
1107   else
1108     old_dissect_data(pd, offset, fd, tree);
1109  
1110 }
1111
1112 static const char *
1113 payloadtype2str(guint8 type) {
1114
1115   if (type < NUM_LOAD_TYPES) return strfuncs[type].str;
1116   if (type < 128)            return "RESERVED";
1117   if (type < 256)            return "Private USE";
1118
1119   return "Huh? You should never see this! Shame on you!";
1120 }
1121
1122 static const char *
1123 exchtype2str(guint8 type) {
1124
1125 #define NUM_EXCHSTRS    7
1126   static const char * exchstrs[NUM_EXCHSTRS] = {
1127     "NONE",
1128     "Base",
1129     "Identity Protection (Main Mode)",
1130     "Authentication Only",
1131     "Aggressive",
1132     "Informational",
1133     "Transaction (Config Mode)"
1134   };
1135   
1136   if (type < NUM_EXCHSTRS) return exchstrs[type];
1137   if (type < 32)           return "ISAKMP Future Use";
1138   switch (type) {
1139   case 32:
1140     return "Quick Mode";
1141   case 33:
1142     return "New Group Mode";
1143   }
1144   if (type < 240)          return "DOI Specific Use";
1145   if (type < 256)          return "Private Use";
1146   
1147   return "Huh? You should never see this! Shame on you!";
1148 }
1149
1150 static const char *
1151 doitype2str(guint32 type) {
1152   if (type == 1) return "IPSEC";
1153   return "Unknown DOI Type";
1154 }
1155
1156 static const char *
1157 msgtype2str(guint16 type) {
1158
1159 #define NUM_PREDEFINED  31
1160   static const char *msgs[NUM_PREDEFINED] = {
1161     "<UNKNOWN>",
1162     "INVALID-PAYLOAD-TYPE",
1163     "DOI-NOT-SUPPORTED",
1164     "SITUATION-NOT-SUPPORTED",
1165     "INVALID-COOKIE",
1166     "INVALID-MAJOR-VERSION",
1167     "INVALID-MINOR-VERSION",
1168     "INVALID-EXCHANGE-TYPE",
1169     "INVALID-FLAGS",
1170     "INVALID-MESSAGE-ID",
1171     "INVALID-PROTOCOL-ID",
1172     "INVALID-SPI",
1173     "INVALID-TRANSFORM-ID",
1174     "ATTRIBUTES-NOT-SUPPORTED",
1175     "NO-PROPOSAL-CHOSEN",
1176     "BAD-PROPOSAL-SYNTAX",
1177     "PAYLOAD-MALFORMED",
1178     "INVALID-KEY-INFORMATION",
1179     "INVALID-ID-INFORMATION",
1180     "INVALID-CERT-ENCODING",
1181     "INVALID-CERTIFICATE",
1182     "CERT-TYPE-UNSUPPORTED",
1183     "INVALID-CERT-AUTHORITY",
1184     "INVALID-HASH-INFORMATION",
1185     "AUTHENTICATION-FAILED",
1186     "INVALID-SIGNATURE",
1187     "ADDRESS-NOTIFICATION",
1188     "NOTIFY-SA-LIFETIME",
1189     "CERTIFICATE-UNAVAILABLE",
1190     "UNSUPPORTED-EXCHANGE-TYPE",
1191     "UNEQUAL-PAYLOAD-LENGTHS"
1192   };
1193
1194   if (type < NUM_PREDEFINED) return msgs[type];
1195   if (type < 8192)           return "RESERVED (Future Use)";
1196   if (type < 16384)          return "Private Use";
1197   if (type < 16385)          return "CONNECTED";
1198   if (type < 24576)          return "RESERVED (Future Use) - status";
1199   if (type < 24577)          return "RESPONDER-LIFETIME";
1200   if (type < 24578)          return "REPLAY-STATUS";
1201   if (type < 24579)          return "INITIAL-CONTACT";
1202   if (type < 32768)          return "DOI-specific codes";
1203   if (type < 40960)          return "Private Use - status";
1204   if (type < 65535)          return "RESERVED (Future Use) - status (2)";
1205
1206   return "Huh? You should never see this! Shame on you!";
1207 }
1208
1209 static const char *
1210 situation2str(guint32 type) {
1211
1212 #define SIT_MSG_NUM     1024
1213 #define SIT_IDENTITY    0x01
1214 #define SIT_SECRECY     0x02
1215 #define SIT_INTEGRITY   0x04
1216
1217   static char   msg[SIT_MSG_NUM];
1218   int           n = 0;
1219   char *        sep = "";
1220   
1221   if (type & SIT_IDENTITY) {
1222     n += snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep);
1223     sep = " & ";
1224   }
1225   if (type & SIT_SECRECY) {
1226     n += snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep);
1227     sep = " & ";
1228   }
1229   if (type & SIT_INTEGRITY) {
1230     n += snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep);
1231     sep = " & ";
1232   }
1233
1234   return msg;
1235 }
1236
1237 static const char *
1238 value2str(int ike_p1, guint16 att_type, guint16 value) {
1239   
1240   if (value == 0) return "RESERVED";
1241   
1242   if (!ike_p1) {
1243   switch (att_type) {
1244     case 1:
1245       switch (value) {
1246         case 1:  return "Seconds";
1247         case 2:  return "Kilobytes";
1248         default: return "UNKNOWN-SA-VALUE";
1249       }
1250     case 2:
1251       return "Duration-Value";
1252     case 3:
1253       return "Group-Value";
1254     case 4:
1255       switch (value) {
1256         case 1:  return "Tunnel";
1257         case 2:  return "Transport";
1258         default: return "UNKNOWN-ENCAPSULATION-VALUE";
1259       }
1260     case 5:
1261       switch (value) {
1262         case 1:  return "HMAC-MD5";
1263         case 2:  return "HMAC-SHA";
1264         case 3:  return "DES-MAC";
1265         case 4:  return "KPDK";
1266         case 5:  return "HMAC-SHA2-256";
1267         case 6:  return "HMAC-SHA2-384";
1268         case 7:  return "HMAC-SHA2-512";
1269         default: return "UNKNOWN-AUTHENTICATION-VALUE";
1270       }
1271     case 6:
1272       return "Key-Length";
1273     case 7:
1274       return "Key-Rounds";
1275     case 8:
1276       return "log2-size";
1277     default: return "UNKNOWN-ATTRIBUTE-TYPE";
1278   }
1279   }
1280   else {
1281     switch (att_type) {
1282       case 1:
1283         switch (value) {
1284           case 1:  return "DES-CBC";
1285           case 2:  return "IDEA-CBC";
1286           case 3:  return "BLOWFISH-CBC";
1287           case 4:  return "RC5-R16-B64-CBC";
1288           case 5:  return "3DES-CBC";
1289           case 6:  return "CAST-CBC";
1290           case 7:  return "AES-CBC";
1291           default: return "UNKNOWN-ENCRYPTION-ALG";
1292         }
1293       case 2:
1294         switch (value) {
1295           case 1:  return "MD5";
1296           case 2:  return "SHA";
1297           case 3:  return "TIGER";
1298           case 4:  return "SHA2-256";
1299           case 5:  return "SHA2-384";
1300           case 6:  return "SHA2-512";
1301           default: return "UNKNOWN-HASH-ALG";
1302         }
1303       case 3:
1304         switch (value) {
1305           case 1:  return "PSK";
1306           case 2:  return "DSS-SIG";
1307           case 3:  return "RSA-SIG";
1308           case 4:  return "RSA-ENC";
1309           case 5:  return "RSA-Revised-ENC";
1310           case 64221: return "HybridInitRSA";
1311           case 64222: return "HybridRespRSA";
1312           case 64223: return "HybridInitDSS";
1313           case 64224: return "HybridRespDSS";
1314           case 65001: return "XAUTHInitPreShared";
1315           case 65002: return "XAUTHRespPreShared";
1316           case 65003: return "XAUTHInitDSS";
1317           case 65004: return "XAUTHRespDSS";
1318           case 65005: return "XAUTHInitRSA";
1319           case 65006: return "XAUTHRespRSA";
1320           case 65007: return "XAUTHInitRSAEncryption";
1321           case 65008: return "XAUTHRespRSAEncryption";
1322           case 65009: return "XAUTHInitRSARevisedEncryption";
1323           case 65010: return "XAUTHRespRSARevisedEncryption";
1324           default: return "UNKNOWN-AUTH-METHOD";
1325         }
1326       case 4:
1327       case 6:
1328       case 7:
1329       case 8:
1330       case 9:
1331       case 10:
1332       case 16:
1333         return "Group-Value";
1334       case 5:
1335         switch (value) {
1336           case 1:  return "MODP";
1337           case 2:  return "ECP";
1338           case 3:  return "EC2N";
1339           default: return "UNKNOWN-GROUPT-TYPE";
1340         }
1341       case 11:
1342         switch (value) {
1343           case 1:  return "Seconds";
1344           case 2:  return "Kilobytes";
1345           default: return "UNKNOWN-SA-VALUE";
1346         }
1347       case 12:
1348         return "Duration-Value";
1349       case 13:
1350         return "PRF-Value";
1351       case 14:
1352         return "Key-Length";
1353       case 15:
1354         return "Field-Size";
1355       default: return "UNKNOWN-ATTRIBUTE-TYPE";
1356     }
1357   }
1358 }
1359
1360 static const char * 
1361 attrtype2str(guint8 type) {
1362   switch (type) {
1363   case 0: return "Reserved";
1364   case 1: return "ISAKMP_CFG_REQUEST";
1365   case 2: return "ISAKMP_CFG_REPLY";
1366   case 3: return "ISAKMP_CFG_SET";
1367   case 4: return "ISAKMP_CFG_ACK";
1368   }
1369   if(type < 127)
1370     return "Future use";
1371   return "Private use";
1372 }
1373
1374 static const char * 
1375 cfgattrident2str(guint16 ident) {
1376 #define NUM_ATTR_DEFINED        12
1377   static const char *msgs[NUM_PREDEFINED] = {
1378     "RESERVED",
1379     "INTERNAL_IP4_ADDRESS",
1380     "INTERNAL_IP4_NETMASK",
1381     "INTERNAL_IP4_DNS",
1382     "INTERNAL_IP4_NBNS",
1383     "INTERNAL_ADDRESS_EXPIREY",
1384     "INTERNAL_IP4_DHCP",
1385     "APPLICATION_VERSION"
1386     "INTERNAL_IP6_ADDRESS",
1387     "INTERNAL_IP6_NETMASK",
1388     "INTERNAL_IP6_DNS",
1389     "INTERNAL_IP6_NBNS",
1390     "INTERNAL_IP6_DHCP",
1391   }; 
1392   if(ident < NUM_ATTR_DEFINED)
1393     return msgs[ident];
1394   if(ident < 16383)
1395     return "Future use";
1396   switch(ident) {
1397   case 16520: return "XAUTH_TYPE";
1398   case 16521: return "XAUTH_USER_NAME";
1399   case 16522: return "XAUTH_USER_PASSWORD";
1400   case 16523: return "XAUTH_PASSCODE";
1401   case 16524: return "XAUTH_MESSAGE";
1402   case 16525: return "XAUTH_CHALLANGE";
1403   case 16526: return "XAUTH_DOMAIN";
1404   case 16527: return "XAUTH_STATUS";
1405   default: return "Private use";
1406   }
1407 }
1408
1409 static const char *
1410 num2str(const guint8 *pd, guint16 len) {
1411
1412 #define NUMSTR_LEN      1024
1413   static char           numstr[NUMSTR_LEN];
1414   
1415   switch (len) {
1416   case 1:
1417     snprintf(numstr, NUMSTR_LEN, "%u", *pd);
1418     break;
1419   case 2:
1420     snprintf(numstr, NUMSTR_LEN, "%u", pntohs(pd));
1421     break;
1422   case 3:
1423     snprintf(numstr, NUMSTR_LEN, "%u", pntohl(pd) & 0x0fff);
1424     break;
1425   case 4:
1426     snprintf(numstr, NUMSTR_LEN, "%u", pntohl(pd));
1427     break;
1428   default:
1429     snprintf(numstr, NUMSTR_LEN, "<too big>");
1430   }
1431
1432   return numstr;
1433 }
1434
1435 void
1436 proto_register_isakmp(void)
1437 {
1438 /*        static hf_register_info hf[] = {
1439                 { &variable,
1440                 { "Name",           "isakmp.abbreviation", TYPE, VALS_POINTER }},
1441         };*/
1442         static gint *ett[] = {
1443                 &ett_isakmp,
1444                 &ett_isakmp_flags,
1445                 &ett_isakmp_payload,
1446         };
1447
1448         proto_isakmp = proto_register_protocol("Internet Security Association and Key Management Protocol",
1449                                                "ISAKMP", "isakmp");
1450  /*       proto_register_field_array(proto_isakmp, hf, array_length(hf));*/
1451         proto_register_subtree_array(ett, array_length(ett));
1452 }
1453
1454 void
1455 proto_reg_handoff_isakmp(void)
1456 {
1457         old_dissector_add("udp.port", UDP_PORT_ISAKMP, dissect_isakmp);
1458 }