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