Wildcard matching is tricky - you have to try wildcarding both the
[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.29 2000/10/07 06:58:24 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_add_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), "Message ID");
419     offset += sizeof(hdr->message_id);
420     
421     proto_tree_add_text(isakmp_tree, NullTVB, offset, sizeof(hdr->length),
422                         "Length: %u", len);
423     offset += sizeof(hdr->length);
424
425     if (hdr->flags & E_FLAG) {
426       if (IS_DATA_IN_FRAME(offset) && isakmp_tree) {
427         proto_tree_add_text(isakmp_tree, NullTVB, offset, END_OF_FRAME,
428                         "Encrypted payload (%d byte%s)",
429                         END_OF_FRAME, plurality(END_OF_FRAME, "", "s"));
430       }
431     } else {
432       if (hdr->next_payload < NUM_LOAD_TYPES) {
433         if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
434           dissect_transform(pd, offset, fd, isakmp_tree, 0);    /* XXX - protocol ID? */
435         else
436           (*strfuncs[hdr->next_payload].func)(pd, offset, fd, isakmp_tree);
437       }
438       else
439         old_dissect_data(pd, offset, fd, isakmp_tree);
440     }
441   }
442 }
443
444 static void
445 dissect_none(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
446 }
447
448 static void
449 dissect_sa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
450
451   struct sa_hdr *       hdr       = (struct sa_hdr *)(pd + offset);
452   guint16               length    = pntohs(&hdr->length);
453   guint32               doi       = pntohl(&hdr->doi);
454   guint32               situation = pntohl(&hdr->situation);
455   proto_item *          ti        = proto_tree_add_text(tree, NullTVB, offset, length, "Security Association payload");
456   proto_tree *          ntree;
457
458   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
459   
460   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
461                       "Next payload: %s (%u)",
462                       payloadtype2str(hdr->next_payload), hdr->next_payload);
463   offset += sizeof(hdr->next_payload) * 2;
464   
465   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
466                       "Length: %u", length);
467   offset += sizeof(length);
468   
469   proto_tree_add_text(ntree, NullTVB, offset, sizeof(doi),
470                       "Domain of interpretation: %s (%u)",
471                       doitype2str(doi), doi);
472   offset += sizeof(doi);
473   
474   proto_tree_add_text(ntree, NullTVB, offset, sizeof(situation),
475                       "Situation: %s (%u)",
476                       situation2str(situation), situation);
477   offset += sizeof(situation);
478   
479   dissect_proposal(pd, offset, fd, ntree);
480   offset += (length - sizeof(*hdr));
481   
482   if (hdr->next_payload < NUM_LOAD_TYPES) {
483     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
484       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
485     else
486       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
487   }
488   else
489     old_dissect_data(pd, offset, fd, tree);
490 }
491
492 static void
493 dissect_proposal(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
494
495   struct proposal_hdr * hdr     = (struct proposal_hdr *)(pd + offset);
496   guint16               length  = pntohs(&hdr->length);
497   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Proposal payload");
498   proto_tree *          ntree;
499
500   int                   next_hdr_offset = offset + length;
501
502   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
503   
504   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
505                       "Next payload: %s (%u)",
506                       payloadtype2str(hdr->next_payload), hdr->next_payload);
507   offset += sizeof(hdr->next_payload) * 2;
508   
509   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
510                       "Length: %u", length);
511   offset += sizeof(length);
512   
513   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->proposal_num),
514                       "Proposal number: %u", hdr->proposal_num);
515   offset += sizeof(hdr->proposal_num);
516   
517   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->protocol_id),
518                       "Protocol ID: %s (%u)",
519                       proto2str(hdr->protocol_id), hdr->protocol_id);
520   offset += sizeof(hdr->protocol_id);
521   
522   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->spi_size),
523                       "SPI size: %u", hdr->spi_size);
524   offset += sizeof(hdr->spi_size);
525
526   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->num_transforms),
527                       "Number of transforms: %u", hdr->num_transforms);
528   offset += sizeof(hdr->num_transforms);
529
530   if (hdr->spi_size) {
531     proto_tree_add_text(ntree, NullTVB, offset, hdr->spi_size, "SPI");
532     offset += hdr->spi_size;
533   }
534
535   if (hdr->num_transforms > 0)
536     dissect_transform(pd, offset, fd, ntree, hdr->protocol_id);
537
538   if (hdr->next_payload < NUM_LOAD_TYPES) {
539     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
540       dissect_transform(pd, next_hdr_offset, fd, tree, 0);      /* XXX - protocol ID? */
541     else
542       (*strfuncs[hdr->next_payload].func)(pd, next_hdr_offset, fd, tree);
543   }
544   else
545     old_dissect_data(pd, next_hdr_offset, fd, tree);
546 }
547
548 static void
549 dissect_transform(const u_char *pd, int offset, frame_data *fd,
550                 proto_tree *tree, guint8 protocol_id)
551 {
552
553   struct trans_hdr *    hdr     = (struct trans_hdr *)(pd + offset);
554   guint16               length  = pntohs(&hdr->length);
555   int                   slength = length;
556   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Transform payload");
557   proto_tree *          ntree;
558
559   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
560   
561   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
562                       "Next payload: %s (%u)",
563                       payloadtype2str(hdr->next_payload), hdr->next_payload);
564   offset += sizeof(hdr->next_payload) * 2;
565   
566   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
567                       "Length: %u", length);
568   offset += sizeof(length);
569   
570   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->transform_num),
571                       "Transform number: %u", hdr->transform_num);
572   offset += sizeof(hdr->transform_num);
573
574   switch (protocol_id) {
575   default:
576   case 1:       /* ISAKMP */
577     proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->transform_id),
578                         "Transform ID: %s (%u)",
579                         trans2str(hdr->transform_id), hdr->transform_id);
580     break;
581   case 2:       /* AH */
582     proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->transform_id),
583                         "Transform ID: %s (%u)",
584                         ah_trans2str(hdr->transform_id), hdr->transform_id);
585     break;
586   case 3:       /* ESP */
587     proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->transform_id),
588                         "Transform ID: %s (%u)",
589                         esp_trans2str(hdr->transform_id), hdr->transform_id);
590     break;
591   }
592   offset += sizeof(hdr->transform_id) + sizeof(hdr->reserved2);
593   
594   slength -= sizeof(*hdr);
595   while (slength>0) {
596     const char *str = NULL;
597     int ike_phase1 = 0;
598     guint16 type    = pntohs(pd + offset) & 0x7fff;
599     guint16 val_len = pntohs(pd + offset + 2);
600
601     if (protocol_id == 1 && hdr->transform_id == 1) {
602       ike_phase1 = 1;
603       str = p1_atttype2str(type);
604     }
605     else {
606       str = atttype2str(type);
607     }
608
609     if (pd[offset] & 0x80) {
610       proto_tree_add_text(ntree, NullTVB, offset, 4,
611                           "%s (%u): %s (%u)",
612                           str, type,
613                           value2str(ike_phase1, type, val_len), val_len);
614       offset += 4;
615       slength -= 4;
616     }
617     else {
618       guint16   pack_len = 4 + val_len;
619       
620       proto_tree_add_text(ntree, NullTVB, offset, pack_len,
621                           "%s (%u): %s",
622                           str, type,
623                           num2str(pd + offset + 4, val_len));
624       offset += pack_len;
625       slength -= pack_len;
626     }
627     if (!IS_DATA_IN_FRAME(offset)) {
628             proto_tree_add_text(ntree, NullTVB, 0, 0,
629                             "Bad Offset: %u", offset);
630             return;
631     }
632   }
633
634   if (hdr->next_payload < NUM_LOAD_TYPES) {
635     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
636       dissect_transform(pd, offset, fd, tree, protocol_id);
637     else
638       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
639   }
640   else
641     old_dissect_data(pd, offset, fd, tree);
642 }
643
644 static void
645 dissect_key_exch(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
646
647   struct ke_hdr *       hdr     = (struct ke_hdr *)(pd + offset);
648   guint16               length  = pntohs(&hdr->length);
649   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Key Exchange payload");
650   proto_tree *          ntree;
651
652   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
653   
654   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
655                       "Next payload: %s (%u)",
656                       payloadtype2str(hdr->next_payload), hdr->next_payload);
657   offset += sizeof(hdr->next_payload) * 2;
658   
659   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
660                       "Length: %u", length);
661   offset += sizeof(length);
662   
663   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Key Exchange Data");
664   offset += (length - sizeof(*hdr));
665   
666   if (hdr->next_payload < NUM_LOAD_TYPES) {
667     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
668       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
669     else
670       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
671   }
672   else
673     old_dissect_data(pd, offset, fd, tree);
674 }
675
676 static void
677 dissect_id(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
678
679   struct id_hdr *       hdr     = (struct id_hdr *)(pd + offset);
680   guint16               length  = pntohs(&hdr->length);
681   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Identification payload");
682   proto_tree *          ntree;
683
684   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
685   
686   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
687                       "Next payload: %s (%u)",
688                       payloadtype2str(hdr->next_payload), hdr->next_payload);
689   offset += sizeof(hdr->next_payload) * 2;
690   
691   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
692                       "Length: %u", length);
693   offset += sizeof(length);
694   
695   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->id_type),
696                       "ID type: %s (%u)", id2str(hdr->id_type), hdr->id_type);
697   offset += sizeof(hdr->id_type);
698
699   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->protocol_id),
700                       "Protocol ID: %u", hdr->protocol_id);
701   offset += sizeof(hdr->protocol_id);
702   
703   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->port),
704                       "Port: %u", pntohs(&hdr->port));
705   offset += sizeof(hdr->port);
706   
707   switch (hdr->id_type) {
708     case 1:
709     case 4:
710       proto_tree_add_text(ntree, NullTVB, offset, length-sizeof(*hdr),
711                           "Identification data: %s", ip_to_str(pd+offset));
712       break;
713     case 2:
714     case 3:
715       proto_tree_add_text(ntree, NullTVB, offset, length-sizeof(*hdr),
716                           "Identification data: %s", (char *)(pd+offset));
717       break;
718     default:
719       proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Identification Data");
720   }
721   offset += (length - sizeof(*hdr));
722   
723   if (hdr->next_payload < NUM_LOAD_TYPES) {
724     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
725       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
726     else
727       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
728   }
729   else
730     old_dissect_data(pd, offset, fd, tree);
731 }
732
733 static void
734 dissect_cert(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
735
736   struct cert_hdr *     hdr     = (struct cert_hdr *)(pd + offset);
737   guint16               length  = pntohs(&hdr->length);
738   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Certificate payload");
739   proto_tree *          ntree;
740
741   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
742   
743   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
744                       "Next payload: %s (%u)",
745                       payloadtype2str(hdr->next_payload), hdr->next_payload);
746   offset += sizeof(hdr->next_payload) * 2;
747   
748   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
749                       "Length: %u", length);
750   offset += sizeof(length);
751   
752   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->cert_enc),
753                       "Certificate encoding: %u", hdr->cert_enc);
754   offset += sizeof(hdr->cert_enc);
755
756   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Certificate Data");
757   offset += (length - sizeof(*hdr));
758   
759   if (hdr->next_payload < NUM_LOAD_TYPES) {
760     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
761       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
762     else
763       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
764   }
765   else
766     old_dissect_data(pd, offset, fd, tree);
767 }
768
769 static void
770 dissect_certreq(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
771
772   struct certreq_hdr *  hdr     = (struct certreq_hdr *)(pd + offset);
773   guint16               length  = pntohs(&hdr->length);
774   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Certificate Request payload");
775   proto_tree *          ntree;
776
777   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
778   
779   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
780                       "Next payload: %s (%u)",
781                       payloadtype2str(hdr->next_payload), hdr->next_payload);
782   offset += sizeof(hdr->next_payload) * 2;
783   
784   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
785                       "Length: %u", length);
786   offset += sizeof(length);
787   
788   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->cert_type),
789                       "Certificate type: %u", hdr->cert_type);
790   offset += sizeof(hdr->cert_type);
791
792   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Certificate Authority");
793   offset += (length - sizeof(*hdr));
794   
795   if (hdr->next_payload < NUM_LOAD_TYPES) {
796     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
797       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
798     else
799       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
800   }
801   else
802     old_dissect_data(pd, offset, fd, tree);
803 }
804
805 static void
806 dissect_hash(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
807
808   struct hash_hdr *     hdr     = (struct hash_hdr *)(pd + offset);
809   guint16               length  = pntohs(&hdr->length);
810   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Hash payload");
811   proto_tree *          ntree;
812
813   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
814   
815   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
816                       "Next payload: %s (%u)",
817                       payloadtype2str(hdr->next_payload), hdr->next_payload);
818   offset += sizeof(hdr->next_payload) * 2;
819   
820   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
821                       "Length: %u", length);
822   offset += sizeof(length);
823   
824   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Hash Data");
825   offset += (length - sizeof(*hdr));
826   
827   if (hdr->next_payload < NUM_LOAD_TYPES) {
828     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
829       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
830     else
831       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
832   }
833   else
834     old_dissect_data(pd, offset, fd, tree);
835 }
836
837 static void
838 dissect_sig(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
839
840   struct sig_hdr *      hdr     = (struct sig_hdr *)(pd + offset);
841   guint16               length  = pntohs(&hdr->length);
842   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Signature payload");
843   proto_tree *          ntree;
844
845   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
846   
847   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
848                       "Next payload: %s (%u)",
849                       payloadtype2str(hdr->next_payload), hdr->next_payload);
850   offset += sizeof(hdr->next_payload) * 2;
851   
852   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
853                       "Length: %u", length);
854   offset += sizeof(length);
855   
856   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Signature Data");
857   offset += (length - sizeof(*hdr));
858   
859   if (hdr->next_payload < NUM_LOAD_TYPES) {
860     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
861       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
862     else
863       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
864   }
865   else
866     old_dissect_data(pd, offset, fd, tree);
867 }
868
869 static void
870 dissect_nonce(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
871
872   struct nonce_hdr *    hdr     = (struct nonce_hdr *)(pd + offset);
873   guint16               length  = pntohs(&hdr->length);
874   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Nonce payload");
875   proto_tree *          ntree;
876
877   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
878   
879   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
880                       "Next payload: %s (%u)",
881                       payloadtype2str(hdr->next_payload), hdr->next_payload);
882   offset += sizeof(hdr->next_payload) * 2;
883   
884   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
885                       "Length: %u", length);
886   offset += sizeof(length);
887   
888   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Nonce Data");
889   offset += (length - sizeof(*hdr));
890   
891   if (hdr->next_payload < NUM_LOAD_TYPES) {
892     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
893       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
894     else
895       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
896   }
897   else
898     old_dissect_data(pd, offset, fd, tree);
899 }
900
901 static void
902 dissect_notif(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
903
904   struct notif_hdr *    hdr     = (struct notif_hdr *)(pd + offset);
905   guint16               length  = pntohs(&hdr->length);
906   guint32               doi     = pntohl(&hdr->doi);
907   guint16               msgtype = pntohs(&hdr->msgtype);
908   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Notification payload");
909   proto_tree *          ntree;
910
911   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
912   
913   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
914                       "Next payload: %s (%u)",
915                       payloadtype2str(hdr->next_payload), hdr->next_payload);
916   offset += sizeof(hdr->next_payload) * 2;
917   
918   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
919                       "Length: %u", length);
920   offset += sizeof(length);
921   
922   proto_tree_add_text(ntree, NullTVB, offset, sizeof(doi),
923                       "Domain of Interpretation: %s (%u)", doitype2str(doi), doi);
924   offset += sizeof(doi);
925
926   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->protocol_id),
927                       "Protocol ID: %s (%u)",
928                       proto2str(hdr->protocol_id), hdr->protocol_id);
929   offset += sizeof(hdr->protocol_id);
930   
931   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->spi_size),
932                       "SPI size: %u", hdr->spi_size);
933   offset += sizeof(hdr->spi_size);
934   
935   proto_tree_add_text(ntree, NullTVB, offset, sizeof(msgtype),
936                       "Message type: %s (%u)", msgtype2str(msgtype), msgtype);
937   offset += sizeof(msgtype);
938
939   if (hdr->spi_size) {
940     proto_tree_add_text(ntree, NullTVB, offset, hdr->spi_size, "Security Parameter Index");
941     offset += hdr->spi_size;
942   }
943
944   if (((int)length - sizeof(*hdr)) > 0) {
945     proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr) - hdr->spi_size,
946                         "Notification Data");
947     offset += (length - sizeof(*hdr) - hdr->spi_size);
948   }
949   
950   if (hdr->next_payload < NUM_LOAD_TYPES) {
951     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
952       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
953     else
954       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
955   }
956   else
957     old_dissect_data(pd, offset, fd, tree);
958 }
959
960 static void
961 dissect_delete(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
962
963   struct delete_hdr *   hdr      = (struct delete_hdr *)(pd + offset);
964   guint16               length   = pntohs(&hdr->length);
965   guint32               doi      = pntohl(&hdr->doi);
966   guint16               num_spis = pntohs(&hdr->num_spis);
967   proto_item *          ti       = proto_tree_add_text(tree, NullTVB, offset, length, "Delete payload");
968   proto_tree *          ntree;
969   guint16               i;
970   
971   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
972   
973   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
974                       "Next payload: %s (%u)",
975                       payloadtype2str(hdr->next_payload), hdr->next_payload);
976   offset += sizeof(hdr->next_payload) * 2;
977   
978   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
979                       "Length: %u", length);
980   offset += sizeof(length);
981   
982   proto_tree_add_text(ntree, NullTVB, offset, sizeof(doi),
983                       "Domain of Interpretation: %s (%u)", doitype2str(doi), doi);
984   offset += sizeof(doi);
985
986   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->protocol_id),
987                       "Protocol ID: %s (%u)",
988                       proto2str(hdr->protocol_id), hdr->protocol_id);
989   offset += sizeof(hdr->protocol_id);
990   
991   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->spi_size),
992                       "SPI size: %u", hdr->spi_size);
993   offset += sizeof(hdr->spi_size);
994   
995   proto_tree_add_text(ntree, NullTVB, offset, num_spis,
996                       "Number of SPIs: %u", num_spis);
997   offset += sizeof(hdr->num_spis);
998   
999   for (i = 0; i < num_spis; ++i) {
1000     proto_tree_add_text(ntree, NullTVB, offset, hdr->spi_size,
1001                         "SPI (%d)", i);
1002     offset += hdr->spi_size;
1003   }
1004
1005   if (hdr->next_payload < NUM_LOAD_TYPES) {
1006     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
1007       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
1008     else
1009       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
1010   }
1011   else
1012     old_dissect_data(pd, offset, fd, tree);
1013 }
1014
1015 static void
1016 dissect_vid(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1017
1018   struct vid_hdr *      hdr     = (struct vid_hdr *)(pd + offset);
1019   guint16               length  = pntohs(&hdr->length);
1020   proto_item *          ti      = proto_tree_add_text(tree, NullTVB, offset, length, "Vendor ID payload");
1021   proto_tree *          ntree;
1022
1023   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
1024   
1025   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
1026                       "Next payload: %s (%u)",
1027                       payloadtype2str(hdr->next_payload), hdr->next_payload);
1028   offset += sizeof(hdr->next_payload) * 2;
1029   
1030   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
1031                       "Length: %u", length);
1032   offset += sizeof(length);
1033   
1034   proto_tree_add_text(ntree, NullTVB, offset, length - sizeof(*hdr), "Vendor ID");
1035   offset += (length - sizeof(*hdr));
1036   
1037   if (hdr->next_payload < NUM_LOAD_TYPES) {
1038     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
1039       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
1040     else
1041       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
1042   }
1043   else
1044     old_dissect_data(pd, offset, fd, tree);
1045 }
1046
1047 static void
1048 dissect_config(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1049
1050   struct cfg_hdr *      hdr      = (struct cfg_hdr *)(pd + offset);
1051   guint16               length   = pntohs(&hdr->length);
1052   int                   slength  = length;
1053   proto_item *          ti       = proto_tree_add_text(tree, NullTVB, offset, length, "Attribute payload");
1054   proto_tree *          ntree;
1055
1056   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
1057
1058   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->next_payload),
1059                       "Next payload: %s (%u)",
1060                       payloadtype2str(hdr->next_payload), hdr->next_payload);
1061   offset += sizeof(hdr->next_payload) *2;
1062   
1063   proto_tree_add_text(ntree, NullTVB, offset, sizeof(length),
1064                      "Length: %u", length);
1065   offset += sizeof(length);
1066   
1067   proto_tree_add_text(ntree,NullTVB, offset, sizeof(hdr->type),
1068                       "Type %s (%u)",attrtype2str(hdr->type),hdr->type);
1069   
1070   offset += (sizeof(hdr->type) + sizeof(hdr->reserved2));
1071   
1072   proto_tree_add_text(ntree, NullTVB, offset, sizeof(hdr->identifier),
1073                       "Identifier: %u", pntohs(&hdr->identifier));
1074   offset += sizeof(hdr->identifier);
1075   slength -= sizeof(*hdr);
1076   
1077   while(slength>0) {
1078     guint16 type = pntohs(pd + offset) & 0x7fff;
1079     guint16 val_len = pntohs(pd + offset + 2);
1080     
1081     if(pd[offset] & 0x80) {
1082       proto_tree_add_text(ntree, NullTVB, offset, 4,
1083                           "%s (%u)",cfgattrident2str(type),val_len);
1084       offset += 4;
1085       slength -= 4;
1086     }
1087     else {
1088       guint pack_len = 4 + val_len;
1089
1090       proto_tree_add_text(ntree, NullTVB, offset, 4,
1091                           "%s (%se)", cfgattrident2str(type), num2str(pd + offset + 4, val_len));
1092       offset += pack_len;
1093       slength -= pack_len;
1094     }
1095   }
1096
1097   if (hdr->next_payload < NUM_LOAD_TYPES) {
1098     if (hdr->next_payload == LOAD_TYPE_TRANSFORM)
1099       dissect_transform(pd, offset, fd, tree, 0);       /* XXX - protocol ID? */
1100     else
1101       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
1102   }
1103   else
1104     old_dissect_data(pd, offset, fd, tree);
1105  
1106 }
1107
1108 static const char *
1109 payloadtype2str(guint8 type) {
1110
1111   if (type < NUM_LOAD_TYPES) return strfuncs[type].str;
1112   if (type < 128)            return "RESERVED";
1113   if (type < 256)            return "Private USE";
1114
1115   return "Huh? You should never see this! Shame on you!";
1116 }
1117
1118 static const char *
1119 exchtype2str(guint8 type) {
1120
1121 #define NUM_EXCHSTRS    7
1122   static const char * exchstrs[NUM_EXCHSTRS] = {
1123     "NONE",
1124     "Base",
1125     "Identity Protection (Main Mode)",
1126     "Authentication Only",
1127     "Aggressive",
1128     "Informational",
1129     "Transaction (Config Mode)"
1130   };
1131   
1132   if (type < NUM_EXCHSTRS) return exchstrs[type];
1133   if (type < 32)           return "ISAKMP Future Use";
1134   switch (type) {
1135   case 32:
1136     return "Quick Mode";
1137   case 33:
1138     return "New Group Mode";
1139   }
1140   if (type < 240)          return "DOI Specific Use";
1141   if (type < 256)          return "Private Use";
1142   
1143   return "Huh? You should never see this! Shame on you!";
1144 }
1145
1146 static const char *
1147 doitype2str(guint32 type) {
1148   if (type == 1) return "IPSEC";
1149   return "Unknown DOI Type";
1150 }
1151
1152 static const char *
1153 msgtype2str(guint16 type) {
1154
1155 #define NUM_PREDEFINED  31
1156   static const char *msgs[NUM_PREDEFINED] = {
1157     "<UNKNOWN>",
1158     "INVALID-PAYLOAD-TYPE",
1159     "DOI-NOT-SUPPORTED",
1160     "SITUATION-NOT-SUPPORTED",
1161     "INVALID-COOKIE",
1162     "INVALID-MAJOR-VERSION",
1163     "INVALID-MINOR-VERSION",
1164     "INVALID-EXCHANGE-TYPE",
1165     "INVALID-FLAGS",
1166     "INVALID-MESSAGE-ID",
1167     "INVALID-PROTOCOL-ID",
1168     "INVALID-SPI",
1169     "INVALID-TRANSFORM-ID",
1170     "ATTRIBUTES-NOT-SUPPORTED",
1171     "NO-PROPOSAL-CHOSEN",
1172     "BAD-PROPOSAL-SYNTAX",
1173     "PAYLOAD-MALFORMED",
1174     "INVALID-KEY-INFORMATION",
1175     "INVALID-ID-INFORMATION",
1176     "INVALID-CERT-ENCODING",
1177     "INVALID-CERTIFICATE",
1178     "CERT-TYPE-UNSUPPORTED",
1179     "INVALID-CERT-AUTHORITY",
1180     "INVALID-HASH-INFORMATION",
1181     "AUTHENTICATION-FAILED",
1182     "INVALID-SIGNATURE",
1183     "ADDRESS-NOTIFICATION",
1184     "NOTIFY-SA-LIFETIME",
1185     "CERTIFICATE-UNAVAILABLE",
1186     "UNSUPPORTED-EXCHANGE-TYPE",
1187     "UNEQUAL-PAYLOAD-LENGTHS"
1188   };
1189
1190   if (type < NUM_PREDEFINED) return msgs[type];
1191   if (type < 8192)           return "RESERVED (Future Use)";
1192   if (type < 16384)          return "Private Use";
1193   if (type < 16385)          return "CONNECTED";
1194   if (type < 24576)          return "RESERVED (Future Use) - status";
1195   if (type < 24577)          return "RESPONDER-LIFETIME";
1196   if (type < 24578)          return "REPLAY-STATUS";
1197   if (type < 24579)          return "INITIAL-CONTACT";
1198   if (type < 32768)          return "DOI-specific codes";
1199   if (type < 40960)          return "Private Use - status";
1200   if (type < 65535)          return "RESERVED (Future Use) - status (2)";
1201
1202   return "Huh? You should never see this! Shame on you!";
1203 }
1204
1205 static const char *
1206 situation2str(guint32 type) {
1207
1208 #define SIT_MSG_NUM     1024
1209 #define SIT_IDENTITY    0x01
1210 #define SIT_SECRECY     0x02
1211 #define SIT_INTEGRITY   0x04
1212
1213   static char   msg[SIT_MSG_NUM];
1214   int           n = 0;
1215   char *        sep = "";
1216   
1217   if (type & SIT_IDENTITY) {
1218     n += snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep);
1219     sep = " & ";
1220   }
1221   if (type & SIT_SECRECY) {
1222     n += snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep);
1223     sep = " & ";
1224   }
1225   if (type & SIT_INTEGRITY) {
1226     n += snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep);
1227     sep = " & ";
1228   }
1229
1230   return msg;
1231 }
1232
1233 static const char *
1234 value2str(int ike_p1, guint16 att_type, guint16 value) {
1235   
1236   if (value == 0) return "RESERVED";
1237   
1238   if (!ike_p1) {
1239   switch (att_type) {
1240     case 1:
1241       switch (value) {
1242         case 1:  return "Seconds";
1243         case 2:  return "Kilobytes";
1244         default: return "UNKNOWN-SA-VALUE";
1245       }
1246     case 2:
1247       return "Duration-Value";
1248     case 3:
1249       return "Group-Value";
1250     case 4:
1251       switch (value) {
1252         case 1:  return "Tunnel";
1253         case 2:  return "Transport";
1254         default: return "UNKNOWN-ENCAPSULATION-VALUE";
1255       }
1256     case 5:
1257       switch (value) {
1258         case 1:  return "HMAC-MD5";
1259         case 2:  return "HMAC-SHA";
1260         case 3:  return "DES-MAC";
1261         case 4:  return "KPDK";
1262         case 5:  return "HMAC-SHA2-256";
1263         case 6:  return "HMAC-SHA2-384";
1264         case 7:  return "HMAC-SHA2-512";
1265         default: return "UNKNOWN-AUTHENTICATION-VALUE";
1266       }
1267     case 6:
1268       return "Key-Length";
1269     case 7:
1270       return "Key-Rounds";
1271     case 8:
1272       return "log2-size";
1273     default: return "UNKNOWN-ATTRIBUTE-TYPE";
1274   }
1275   }
1276   else {
1277     switch (att_type) {
1278       case 1:
1279         switch (value) {
1280           case 1:  return "DES-CBC";
1281           case 2:  return "IDEA-CBC";
1282           case 3:  return "BLOWFISH-CBC";
1283           case 4:  return "RC5-R16-B64-CBC";
1284           case 5:  return "3DES-CBC";
1285           case 6:  return "CAST-CBC";
1286           case 7:  return "AES-CBC";
1287           default: return "UNKNOWN-ENCRYPTION-ALG";
1288         }
1289       case 2:
1290         switch (value) {
1291           case 1:  return "MD5";
1292           case 2:  return "SHA";
1293           case 3:  return "TIGER";
1294           case 4:  return "SHA2-256";
1295           case 5:  return "SHA2-384";
1296           case 6:  return "SHA2-512";
1297           default: return "UNKNOWN-HASH-ALG";
1298         }
1299       case 3:
1300         switch (value) {
1301           case 1:  return "PSK";
1302           case 2:  return "DSS-SIG";
1303           case 3:  return "RSA-SIG";
1304           case 4:  return "RSA-ENC";
1305           case 5:  return "RSA-Revised-ENC";
1306           case 64221: return "HybridInitRSA";
1307           case 64222: return "HybridRespRSA";
1308           case 64223: return "HybridInitDSS";
1309           case 64224: return "HybridRespDSS";
1310           case 65001: return "XAUTHInitPreShared";
1311           case 65002: return "XAUTHRespPreShared";
1312           case 65003: return "XAUTHInitDSS";
1313           case 65004: return "XAUTHRespDSS";
1314           case 65005: return "XAUTHInitRSA";
1315           case 65006: return "XAUTHRespRSA";
1316           case 65007: return "XAUTHInitRSAEncryption";
1317           case 65008: return "XAUTHRespRSAEncryption";
1318           case 65009: return "XAUTHInitRSARevisedEncryption";
1319           case 65010: return "XAUTHRespRSARevisedEncryption";
1320           default: return "UNKNOWN-AUTH-METHOD";
1321         }
1322       case 4:
1323       case 6:
1324       case 7:
1325       case 8:
1326       case 9:
1327       case 10:
1328       case 16:
1329         return "Group-Value";
1330       case 5:
1331         switch (value) {
1332           case 1:  return "MODP";
1333           case 2:  return "ECP";
1334           case 3:  return "EC2N";
1335           default: return "UNKNOWN-GROUPT-TYPE";
1336         }
1337       case 11:
1338         switch (value) {
1339           case 1:  return "Seconds";
1340           case 2:  return "Kilobytes";
1341           default: return "UNKNOWN-SA-VALUE";
1342         }
1343       case 12:
1344         return "Duration-Value";
1345       case 13:
1346         return "PRF-Value";
1347       case 14:
1348         return "Key-Length";
1349       case 15:
1350         return "Field-Size";
1351       default: return "UNKNOWN-ATTRIBUTE-TYPE";
1352     }
1353   }
1354 }
1355
1356 static const char * 
1357 attrtype2str(guint8 type) {
1358   switch (type) {
1359   case 0: return "Reserved";
1360   case 1: return "ISAKMP_CFG_REQUEST";
1361   case 2: return "ISAKMP_CFG_REPLY";
1362   case 3: return "ISAKMP_CFG_SET";
1363   case 4: return "ISAKMP_CFG_ACK";
1364   }
1365   if(type < 127)
1366     return "Future use";
1367   return "Private use";
1368 }
1369
1370 static const char * 
1371 cfgattrident2str(guint16 ident) {
1372 #define NUM_ATTR_DEFINED        12
1373   static const char *msgs[NUM_PREDEFINED] = {
1374     "RESERVED",
1375     "INTERNAL_IP4_ADDRESS",
1376     "INTERNAL_IP4_NETMASK",
1377     "INTERNAL_IP4_DNS",
1378     "INTERNAL_IP4_NBNS",
1379     "INTERNAL_ADDRESS_EXPIREY",
1380     "INTERNAL_IP4_DHCP",
1381     "APPLICATION_VERSION"
1382     "INTERNAL_IP6_ADDRESS",
1383     "INTERNAL_IP6_NETMASK",
1384     "INTERNAL_IP6_DNS",
1385     "INTERNAL_IP6_NBNS",
1386     "INTERNAL_IP6_DHCP",
1387   }; 
1388   if(ident < NUM_ATTR_DEFINED)
1389     return msgs[ident];
1390   if(ident < 16383)
1391     return "Future use";
1392   switch(ident) {
1393   case 16520: return "XAUTH_TYPE";
1394   case 16521: return "XAUTH_USER_NAME";
1395   case 16522: return "XAUTH_USER_PASSWORD";
1396   case 16523: return "XAUTH_PASSCODE";
1397   case 16524: return "XAUTH_MESSAGE";
1398   case 16525: return "XAUTH_CHALLANGE";
1399   case 16526: return "XAUTH_DOMAIN";
1400   case 16527: return "XAUTH_STATUS";
1401   default: return "Private use";
1402   }
1403 }
1404
1405 static const char *
1406 num2str(const guint8 *pd, guint16 len) {
1407
1408 #define NUMSTR_LEN      1024
1409   static char           numstr[NUMSTR_LEN];
1410   
1411   switch (len) {
1412   case 1:
1413     snprintf(numstr, NUMSTR_LEN, "%u", *pd);
1414     break;
1415   case 2:
1416     snprintf(numstr, NUMSTR_LEN, "%u", pntohs(pd));
1417     break;
1418   case 3:
1419     snprintf(numstr, NUMSTR_LEN, "%u", pntohl(pd) & 0x0fff);
1420     break;
1421   case 4:
1422     snprintf(numstr, NUMSTR_LEN, "%u", pntohl(pd));
1423     break;
1424   default:
1425     snprintf(numstr, NUMSTR_LEN, "<too big>");
1426   }
1427
1428   return numstr;
1429 }
1430
1431 void
1432 proto_register_isakmp(void)
1433 {
1434 /*        static hf_register_info hf[] = {
1435                 { &variable,
1436                 { "Name",           "isakmp.abbreviation", TYPE, VALS_POINTER }},
1437         };*/
1438         static gint *ett[] = {
1439                 &ett_isakmp,
1440                 &ett_isakmp_flags,
1441                 &ett_isakmp_payload,
1442         };
1443
1444         proto_isakmp = proto_register_protocol("Internet Security Association and Key Management Protocol", "isakmp");
1445  /*       proto_register_field_array(proto_isakmp, hf, array_length(hf));*/
1446         proto_register_subtree_array(ett, array_length(ett));
1447 }
1448
1449 void
1450 proto_reg_handoff_isakmp(void)
1451 {
1452         old_dissector_add("udp.port", UDP_PORT_ISAKMP, dissect_isakmp);
1453 }