- bug fixed with user name display
[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.9 1999/09/17 05:56:54 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
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 #define NUM_PROTO_TYPES 5
56 #define proto2str(t)    \
57   ((t < NUM_PROTO_TYPES) ? prototypestr[t] : "UNKNOWN-PROTO-TYPE")
58
59 static const char *prototypestr[NUM_PROTO_TYPES] = {
60   "RESERVED",
61   "ISAKMP",
62   "IPSEC_AH",
63   "IPSEC_ESP",
64   "IPCOMP"
65 };
66
67 #define NUM_ATT_TYPES   13
68 #define atttype2str(t)  \
69   ((t < NUM_ATT_TYPES) ? atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE")
70
71 static const char *atttypestr[NUM_ATT_TYPES] = {
72   "UNKNOWN-ATTRIBUTE-TYPE",
73   "SA-Life-Type",
74   "SA-Life-Duration",
75   "Group-Description",
76   "Encapsulation-Mode",
77   "Authentication-Algorithm",
78   "Key-Length",
79   "Key-Rounds",
80   "Compress-Dictinary-Size",
81   "Compress-Private-Algorithm"
82   "UNKNOWN-ATTRIBUTE-TYPE",
83   "Oakley-Life",
84   "Oakley-Value",
85   "Oakley-Life-Duration"
86 };
87
88 #define NUM_TRANS_TYPES 2
89 #define trans2str(t)    \
90   ((t < NUM_TRANS_TYPES) ? transtypestr[t] : "UNKNOWN-TRANS-TYPE")
91
92 static const char *transtypestr[NUM_TRANS_TYPES] = {
93   "RESERVED",
94   "KEY_IKE"
95 };
96
97 #define NUM_ID_TYPES    12
98 #define id2str(t)       \
99   ((t < NUM_ID_TYPES) ? idtypestr[t] : "UNKNOWN-ID-TYPE")
100
101 static const char *idtypestr[NUM_ID_TYPES] = {
102   "RESERVED",
103   "IPV4_ADDR",
104   "FQDN",
105   "USER_FQDN",
106   "IPV4_ADDR_SUBNET",
107   "IPV6_ADDR",
108   "IPV6_ADDR_SUBNET",
109   "IPV4_ADDR_RANGE",
110   "IPV6_ADDR_RANGE",
111   "DER_ASN1_DN",
112   "DER_ASN1_GN",
113   "KEY_ID"
114 };
115
116 struct isakmp_hdr {
117   guint8        icookie[8];
118   guint8        rcookie[8];
119   guint8        next_payload;
120   guint8        version;
121   guint8        exch_type;
122   guint8        flags;
123 #define E_FLAG          0x01
124 #define C_FLAG          0x02
125 #define A_FLAG          0x04
126   guint32       message_id;
127   guint32       length;
128 };
129
130 struct sa_hdr {
131   guint8        next_payload;
132   guint8        reserved;
133   guint16       length;
134   guint32       doi;
135   guint32       situation;
136 };
137
138 struct proposal_hdr {
139   guint8        next_payload;
140   guint8        reserved;
141   guint16       length;
142   guint8        proposal_num;
143   guint8        protocol_id;
144   guint8        spi_size;
145   guint8        num_transforms;
146 };
147
148 struct trans_hdr {
149   guint8        next_payload;
150   guint8        reserved;
151   guint16       length;
152   guint8        transform_num;
153   guint8        transform_id;
154   guint16       reserved2;
155 };
156
157 #define TRANS_LEN(p)    (pntohs(&((struct trans_hdr *)(p))->length))
158
159 struct ke_hdr {
160   guint8        next_payload;
161   guint8        reserved;
162   guint16       length;
163 };
164
165 struct id_hdr {
166   guint8        next_payload;
167   guint8        reserved;
168   guint16       length;
169   guint8        id_type;
170   guint8        protocol_id;
171   guint16       port;
172 };
173
174 struct cert_hdr {
175   guint8        next_payload;
176   guint8        reserved;
177   guint16       length;
178   guint8        cert_enc;
179 };
180
181 struct certreq_hdr {
182   guint8        next_payload;
183   guint8        reserved;
184   guint16       length;
185   guint8        cert_type;
186 };
187
188 struct hash_hdr {
189   guint8        next_payload;
190   guint8        reserved;
191   guint16       length;
192 };
193
194 struct sig_hdr {
195   guint8        next_payload;
196   guint8        reserved;
197   guint16       length;
198 };
199
200 struct nonce_hdr {
201   guint8        next_payload;
202   guint8        reserved;
203   guint16       length;
204 };
205
206 struct notif_hdr {
207   guint8        next_payload;
208   guint8        reserved;
209   guint16       length;
210   guint32       doi;
211   guint8        protocol_id;
212   guint8        spi_size;
213   guint16       msgtype;
214 };
215
216 struct delete_hdr {
217   guint8        next_payload;
218   guint8        reserved;
219   guint16       length;
220   guint32       doi;
221   guint8        protocol_id;
222   guint8        spi_size;
223   guint16       num_spis;
224 };
225
226 struct vid_hdr {
227   guint8        next_payload;
228   guint8        reserved;
229   guint16       length;
230 };
231
232 static void dissect_none(const u_char *, int, frame_data *, proto_tree *);
233 static void dissect_sa(const u_char *, int, frame_data *, proto_tree *);
234 static void dissect_proposal(const u_char *, int, frame_data *, proto_tree *);
235 static void dissect_transform(const u_char *, int, frame_data *, proto_tree *);
236 static void dissect_key_exch(const u_char *, int, frame_data *, proto_tree *);
237 static void dissect_id(const u_char *, int, frame_data *, proto_tree *);
238 static void dissect_cert(const u_char *, int, frame_data *, proto_tree *);
239 static void dissect_certreq(const u_char *, int, frame_data *, proto_tree *);
240 static void dissect_hash(const u_char *, int, frame_data *, proto_tree *);
241 static void dissect_sig(const u_char *, int, frame_data *, proto_tree *);
242 static void dissect_nonce(const u_char *, int, frame_data *, proto_tree *);
243 static void dissect_notif(const u_char *, int, frame_data *, proto_tree *);
244 static void dissect_delete(const u_char *, int, frame_data *, proto_tree *);
245 static void dissect_vid(const u_char *, int, frame_data *, proto_tree *);
246
247 static const char *payloadtype2str(guint8);
248 static const char *exchtype2str(guint8);
249 static const char *doitype2str(guint32);
250 static const char *msgtype2str(guint16);
251 static const char *situation2str(guint32);
252 static const char *value2str(guint16, guint16);
253 static const char *num2str(const guint8 *, guint16);
254
255 #define NUM_LOAD_TYPES          14
256 #define loadtype2str(t) \
257   ((t < NUM_LOAD_TYPES) ? strfuncs[t].str : "Unknown payload type")
258
259 static struct strfunc {
260   const char *  str;
261   void          (*func)(const u_char *, int, frame_data *, proto_tree *);
262 } strfuncs[NUM_LOAD_TYPES] = {
263   {"NONE",                      dissect_none      },
264   {"Security Association",      dissect_sa        },
265   {"Proposal",                  dissect_proposal  },
266   {"Transform",                 dissect_transform },
267   {"Key Exchange",              dissect_key_exch  },
268   {"Identification",            dissect_id        },
269   {"Certificate",               dissect_cert      },
270   {"Certificate Request",       dissect_certreq   },
271   {"Hash",                      dissect_hash      },
272   {"Signature",                 dissect_sig       },
273   {"Nonce",                     dissect_nonce     },
274   {"Notification",              dissect_notif     },
275   {"Delete",                    dissect_delete    },
276   {"Vendor ID",                 dissect_vid       }
277 };
278
279 void dissect_isakmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
280   
281   struct isakmp_hdr *   hdr = (struct isakmp_hdr *)(pd + offset);
282   guint32               len;
283   
284   if (check_col(fd, COL_PROTOCOL))
285     col_add_str(fd, COL_PROTOCOL, "ISAKMP");
286   
287   len = pntohl(&hdr->length);
288   
289   if (check_col(fd, COL_INFO))
290     col_add_fstr(fd, COL_INFO, "%s", exchtype2str(hdr->exch_type));
291   
292   if (IS_DATA_IN_FRAME(offset) && tree) {
293     proto_item *        ti;
294     proto_tree *        isakmp_tree;
295     
296     ti = proto_tree_add_item(tree, proto_isakmp, offset, len, NULL);
297     isakmp_tree = proto_item_add_subtree(ti, ETT_ISAKMP);
298     
299     proto_tree_add_text(isakmp_tree, offset, sizeof(hdr->icookie),
300                         "Initiator cookie");
301     offset += sizeof(hdr->icookie);
302     
303     proto_tree_add_text(isakmp_tree, offset, sizeof(hdr->rcookie),
304                         "Responder cookie");
305     offset += sizeof(hdr->rcookie);
306
307     proto_tree_add_text(isakmp_tree, offset, sizeof(hdr->next_payload),
308                         "Next payload: %s (%u)",
309                         payloadtype2str(hdr->next_payload), hdr->next_payload);
310     offset += sizeof(hdr->next_payload);
311
312     proto_tree_add_text(isakmp_tree, offset, sizeof(hdr->version),
313                         "Version: %u.%u",
314                         hi_nibble(hdr->version), lo_nibble(hdr->version));
315     offset += sizeof(hdr->version);
316     
317     proto_tree_add_text(isakmp_tree, offset, sizeof(hdr->exch_type),
318                         "Exchange type: %s (%u)",
319                         exchtype2str(hdr->exch_type), hdr->exch_type);
320     offset += sizeof(hdr->exch_type);
321     
322     {
323       proto_item *      fti;
324       proto_tree *      ftree;
325       
326       fti   = proto_tree_add_text(isakmp_tree, offset, sizeof(hdr->flags), "Flags");
327       ftree = proto_item_add_subtree(fti, ETT_ISAKMP_FLAGS);
328       
329       proto_tree_add_text(ftree, offset, 1, "%s",
330                           decode_boolean_bitfield(hdr->flags, E_FLAG, sizeof(hdr->flags)*8,
331                                                   "Encryption", "No encryption"));
332       proto_tree_add_text(ftree, offset, 1, "%s",
333                           decode_boolean_bitfield(hdr->flags, C_FLAG, sizeof(hdr->flags)*8,
334                                                   "Commit", "No commit"));
335       proto_tree_add_text(ftree, offset, 1, "%s",
336                           decode_boolean_bitfield(hdr->flags, A_FLAG, sizeof(hdr->flags)*8,
337                                                   "Authentication", "No authentication"));
338       offset += sizeof(hdr->flags);
339     }
340
341     proto_tree_add_text(isakmp_tree, offset, sizeof(hdr->message_id), "Message ID");
342     offset += sizeof(hdr->message_id);
343     
344     proto_tree_add_text(isakmp_tree, offset, sizeof(hdr->length),
345                         "Length: %u", len);
346     offset += sizeof(hdr->length);
347
348     if (hdr->next_payload < NUM_LOAD_TYPES)
349       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, isakmp_tree);
350     else
351       dissect_data(pd, offset, fd, isakmp_tree);
352   }
353 }
354
355 static void
356 dissect_none(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
357 }
358
359 static void
360 dissect_sa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
361
362   struct sa_hdr *       hdr       = (struct sa_hdr *)(pd + offset);
363   guint16               length    = pntohs(&hdr->length);
364   guint32               doi       = pntohl(&hdr->doi);
365   guint32               situation = pntohl(&hdr->situation);
366   proto_item *          ti        = proto_tree_add_text(tree, offset, length, "Security Association payload");
367   proto_tree *          ntree;
368
369   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
370   
371   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
372                       "Next payload: %s (%u)",
373                       payloadtype2str(hdr->next_payload), hdr->next_payload);
374   offset += sizeof(hdr->next_payload) * 2;
375   
376   proto_tree_add_text(ntree, offset, sizeof(length),
377                       "Length: %u", length);
378   offset += sizeof(length);
379   
380   proto_tree_add_text(ntree, offset, sizeof(doi),
381                       "Domain of interpretation: %s (%u)",
382                       doitype2str(doi), doi);
383   offset += sizeof(doi);
384   
385   proto_tree_add_text(ntree, offset, sizeof(situation),
386                       "Situation: %s (%u)",
387                       situation2str(situation), situation);
388   offset += sizeof(situation);
389   
390   dissect_proposal(pd, offset, fd, ntree);
391   offset += (length - sizeof(*hdr));
392   
393   if (hdr->next_payload < NUM_LOAD_TYPES)
394     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
395   else
396     dissect_data(pd, offset, fd, tree);
397 }
398
399 static void
400 dissect_proposal(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
401
402   struct proposal_hdr * hdr     = (struct proposal_hdr *)(pd + offset);
403   guint16               length  = pntohs(&hdr->length);
404   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Proposal payload");
405   proto_tree *          ntree;
406   guint8                i;
407   
408   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
409   
410   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
411                       "Next payload: %s (%u)",
412                       payloadtype2str(hdr->next_payload), hdr->next_payload);
413   offset += sizeof(hdr->next_payload) * 2;
414   
415   proto_tree_add_text(ntree, offset, sizeof(length),
416                       "Length: %u", length);
417   offset += sizeof(length);
418   
419   proto_tree_add_text(ntree, offset, sizeof(hdr->proposal_num),
420                       "Proposal number: %u", hdr->proposal_num);
421   offset += sizeof(hdr->proposal_num);
422   
423   proto_tree_add_text(ntree, offset, sizeof(hdr->protocol_id),
424                       "Protocol ID: %s (%u)",
425                       proto2str(hdr->protocol_id), hdr->protocol_id);
426   offset += sizeof(hdr->protocol_id);
427   
428   proto_tree_add_text(ntree, offset, sizeof(hdr->spi_size),
429                       "SPI size: %u", hdr->spi_size);
430   offset += sizeof(hdr->spi_size);
431   
432   if (hdr->spi_size) {
433     proto_tree_add_text(ntree, offset, hdr->spi_size, "SPI");
434     offset += hdr->spi_size;
435   }
436
437   proto_tree_add_text(ntree, offset, sizeof(hdr->num_transforms),
438                       "Number of transforms: %u", hdr->num_transforms);
439   offset += sizeof(hdr->num_transforms);
440   
441   for (i = 0; i < hdr->num_transforms; ++i) {
442     dissect_transform(pd, offset, fd, ntree);
443     offset += TRANS_LEN(pd+offset);
444   }
445
446   if (hdr->next_payload < NUM_LOAD_TYPES)
447     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
448   else
449     dissect_data(pd, offset, fd, tree);
450 }
451
452 static void
453 dissect_transform(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
454
455   struct trans_hdr *    hdr     = (struct trans_hdr *)(pd + offset);
456   guint16               length  = pntohs(&hdr->length);
457   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Transform payload");
458   proto_tree *          ntree;
459
460   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
461   
462   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
463                       "Next payload: %s (%u)",
464                       payloadtype2str(hdr->next_payload), hdr->next_payload);
465   offset += sizeof(hdr->next_payload) * 2;
466   
467   proto_tree_add_text(ntree, offset, sizeof(length),
468                       "Length: %u", length);
469   offset += sizeof(length);
470   
471   proto_tree_add_text(ntree, offset, sizeof(hdr->transform_num),
472                       "Transform number: %u", hdr->transform_num);
473   offset += sizeof(hdr->transform_num);
474   
475   proto_tree_add_text(ntree, offset, sizeof(hdr->transform_id),
476                       "Transform ID: %s (%u)",
477                       trans2str(hdr->transform_id), hdr->transform_id);
478   offset += sizeof(hdr->transform_id) + sizeof(hdr->reserved2);
479   
480   length -= sizeof(*hdr);
481   while (length) {
482     guint16 type    = pntohs(pd + offset) & 0x7fff;
483     guint16 val_len = pntohs(pd + offset + 2);
484     
485     if (pd[offset] & 0xf0) {
486       proto_tree_add_text(ntree, offset, 4,
487                           "%s (%u): %s (%u)",
488                           atttype2str(type), type,
489                           value2str(type, val_len), val_len);
490       offset += 4;
491       length -= 4;
492     }
493     else {
494       guint16   pack_len = 4 + val_len;
495       
496       proto_tree_add_text(ntree, offset, pack_len,
497                           "%s (%u): %s",
498                           atttype2str(type), type,
499                           num2str(pd + offset + 4, val_len));
500       offset += pack_len;
501       length -= pack_len;
502     }
503   }
504
505   if (hdr->next_payload < NUM_LOAD_TYPES)
506     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
507   else
508     dissect_data(pd, offset, fd, tree);
509 }
510
511 static void
512 dissect_key_exch(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
513
514   struct ke_hdr *       hdr     = (struct ke_hdr *)(pd + offset);
515   guint16               length  = pntohs(&hdr->length);
516   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Key Exchange payload");
517   proto_tree *          ntree;
518
519   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
520   
521   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
522                       "Next payload: %s (%u)",
523                       payloadtype2str(hdr->next_payload), hdr->next_payload);
524   offset += sizeof(hdr->next_payload) * 2;
525   
526   proto_tree_add_text(ntree, offset, sizeof(length),
527                       "Length: %u", length);
528   offset += sizeof(length);
529   
530   proto_tree_add_text(ntree, offset, length - sizeof(*hdr), "Key Exchange Data");
531   offset += (length - sizeof(*hdr));
532   
533   if (hdr->next_payload < NUM_LOAD_TYPES)
534     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
535   else
536     dissect_data(pd, offset, fd, tree);
537 }
538
539 static void
540 dissect_id(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
541
542   struct id_hdr *       hdr     = (struct id_hdr *)(pd + offset);
543   guint16               length  = pntohs(&hdr->length);
544   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Identification payload");
545   proto_tree *          ntree;
546
547   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
548   
549   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
550                       "Next payload: %s (%u)",
551                       payloadtype2str(hdr->next_payload), hdr->next_payload);
552   offset += sizeof(hdr->next_payload) * 2;
553   
554   proto_tree_add_text(ntree, offset, sizeof(length),
555                       "Length: %u", length);
556   offset += sizeof(length);
557   
558   proto_tree_add_text(ntree, offset, sizeof(hdr->id_type),
559                       "ID type: %s (%u)", id2str(hdr->id_type), hdr->id_type);
560   offset += sizeof(hdr->id_type);
561
562   proto_tree_add_text(ntree, offset, sizeof(hdr->protocol_id),
563                       "Protocol ID: %u", hdr->protocol_id);
564   offset += sizeof(hdr->protocol_id);
565   
566   proto_tree_add_text(ntree, offset, sizeof(hdr->port),
567                       "Port: %u", pntohs(&hdr->port));
568   offset += sizeof(hdr->port);
569   
570   switch (hdr->id_type) {
571     case 1:
572     case 4:
573       proto_tree_add_text(ntree, offset, length-sizeof(*hdr),
574                           "Identification data: %s", ip_to_str(pd+offset));
575       break;
576     case 2:
577     case 3:
578       proto_tree_add_text(ntree, offset, length-sizeof(*hdr),
579                           "Identification data: %s", (char *)(pd+offset));
580       break;
581     default:
582       proto_tree_add_text(ntree, offset, length - sizeof(*hdr), "Identification Data");
583   }
584   offset += (length - sizeof(*hdr));
585   
586   if (hdr->next_payload < NUM_LOAD_TYPES)
587     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
588   else
589     dissect_data(pd, offset, fd, tree);
590 }
591
592 static void
593 dissect_cert(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
594
595   struct cert_hdr *     hdr     = (struct cert_hdr *)(pd + offset);
596   guint16               length  = pntohs(&hdr->length);
597   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Certificate payload");
598   proto_tree *          ntree;
599
600   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
601   
602   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
603                       "Next payload: %s (%u)",
604                       payloadtype2str(hdr->next_payload), hdr->next_payload);
605   offset += sizeof(hdr->next_payload) * 2;
606   
607   proto_tree_add_text(ntree, offset, sizeof(length),
608                       "Length: %u", length);
609   offset += sizeof(length);
610   
611   proto_tree_add_text(ntree, offset, sizeof(hdr->cert_enc),
612                       "Certificate encoding: %u", hdr->cert_enc);
613   offset += sizeof(hdr->cert_enc);
614
615   proto_tree_add_text(ntree, offset, length - sizeof(*hdr), "Certificate Data");
616   offset += (length - sizeof(*hdr));
617   
618   if (hdr->next_payload < NUM_LOAD_TYPES)
619     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
620   else
621     dissect_data(pd, offset, fd, tree);
622 }
623
624 static void
625 dissect_certreq(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
626
627   struct certreq_hdr *  hdr     = (struct certreq_hdr *)(pd + offset);
628   guint16               length  = pntohs(&hdr->length);
629   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Certificate Request payload");
630   proto_tree *          ntree;
631
632   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
633   
634   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
635                       "Next payload: %s (%u)",
636                       payloadtype2str(hdr->next_payload), hdr->next_payload);
637   offset += sizeof(hdr->next_payload) * 2;
638   
639   proto_tree_add_text(ntree, offset, sizeof(length),
640                       "Length: %u", length);
641   offset += sizeof(length);
642   
643   proto_tree_add_text(ntree, offset, sizeof(hdr->cert_type),
644                       "Certificate type: %u", hdr->cert_type);
645   offset += sizeof(hdr->cert_type);
646
647   proto_tree_add_text(ntree, offset, length - sizeof(*hdr), "Certificate Authority");
648   offset += (length - sizeof(*hdr));
649   
650   if (hdr->next_payload < NUM_LOAD_TYPES)
651     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
652   else
653     dissect_data(pd, offset, fd, tree);
654 }
655
656 static void
657 dissect_hash(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
658
659   struct hash_hdr *     hdr     = (struct hash_hdr *)(pd + offset);
660   guint16               length  = pntohs(&hdr->length);
661   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Hash payload");
662   proto_tree *          ntree;
663
664   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
665   
666   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
667                       "Next payload: %s (%u)",
668                       payloadtype2str(hdr->next_payload), hdr->next_payload);
669   offset += sizeof(hdr->next_payload) * 2;
670   
671   proto_tree_add_text(ntree, offset, sizeof(length),
672                       "Length: %u", length);
673   offset += sizeof(length);
674   
675   proto_tree_add_text(ntree, offset, length - sizeof(*hdr), "Hash Data");
676   offset += (length - sizeof(*hdr));
677   
678   if (hdr->next_payload < NUM_LOAD_TYPES)
679     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
680   else
681     dissect_data(pd, offset, fd, tree);
682 }
683
684 static void
685 dissect_sig(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
686
687   struct sig_hdr *      hdr     = (struct sig_hdr *)(pd + offset);
688   guint16               length  = pntohs(&hdr->length);
689   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Signature payload");
690   proto_tree *          ntree;
691
692   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
693   
694   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
695                       "Next payload: %s (%u)",
696                       payloadtype2str(hdr->next_payload), hdr->next_payload);
697   offset += sizeof(hdr->next_payload) * 2;
698   
699   proto_tree_add_text(ntree, offset, sizeof(length),
700                       "Length: %u", length);
701   offset += sizeof(length);
702   
703   proto_tree_add_text(ntree, offset, length - sizeof(*hdr), "Signature Data");
704   offset += (length - sizeof(*hdr));
705   
706   if (hdr->next_payload < NUM_LOAD_TYPES)
707     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
708   else
709     dissect_data(pd, offset, fd, tree);
710 }
711
712 static void
713 dissect_nonce(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
714
715   struct nonce_hdr *    hdr     = (struct nonce_hdr *)(pd + offset);
716   guint16               length  = pntohs(&hdr->length);
717   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Nonce payload");
718   proto_tree *          ntree;
719
720   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
721   
722   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
723                       "Next payload: %s (%u)",
724                       payloadtype2str(hdr->next_payload), hdr->next_payload);
725   offset += sizeof(hdr->next_payload) * 2;
726   
727   proto_tree_add_text(ntree, offset, sizeof(length),
728                       "Length: %u", length);
729   offset += sizeof(length);
730   
731   proto_tree_add_text(ntree, offset, length - sizeof(*hdr), "Nonce Data");
732   offset += (length - sizeof(*hdr));
733   
734   if (hdr->next_payload < NUM_LOAD_TYPES)
735     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
736   else
737     dissect_data(pd, offset, fd, tree);
738 }
739
740 static void
741 dissect_notif(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
742
743   struct notif_hdr *    hdr     = (struct notif_hdr *)(pd + offset);
744   guint16               length  = pntohs(&hdr->length);
745   guint32               doi     = pntohl(&hdr->doi);
746   guint16               msgtype = pntohs(&hdr->msgtype);
747   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Notification payload");
748   proto_tree *          ntree;
749
750   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
751   
752   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
753                       "Next payload: %s (%u)",
754                       payloadtype2str(hdr->next_payload), hdr->next_payload);
755   offset += sizeof(hdr->next_payload) * 2;
756   
757   proto_tree_add_text(ntree, offset, sizeof(length),
758                       "Length: %u", length);
759   offset += sizeof(length);
760   
761   proto_tree_add_text(ntree, offset, sizeof(doi),
762                       "Domain of Interpretation: %s (%u)", doitype2str(doi), doi);
763   offset += sizeof(doi);
764
765   proto_tree_add_text(ntree, offset, sizeof(hdr->protocol_id),
766                       "Protocol ID: %s (%u)",
767                       proto2str(hdr->protocol_id), hdr->protocol_id);
768   offset += sizeof(hdr->protocol_id);
769   
770   proto_tree_add_text(ntree, offset, sizeof(hdr->spi_size),
771                       "SPI size: %u", hdr->spi_size);
772   offset += sizeof(hdr->spi_size);
773   
774   proto_tree_add_text(ntree, offset, sizeof(msgtype),
775                       "Message type: %s (%u)", msgtype2str(msgtype), msgtype);
776   offset += sizeof(msgtype);
777
778   if (hdr->spi_size) {
779     proto_tree_add_text(ntree, offset, hdr->spi_size, "Security Parameter Index");
780     offset += hdr->spi_size;
781   }
782
783   if (length - sizeof(*hdr)) {
784     proto_tree_add_text(ntree, offset, length - sizeof(*hdr) - hdr->spi_size,
785                         "Notification Data");
786     offset += (length - sizeof(*hdr) - hdr->spi_size);
787   }
788   
789   if (hdr->next_payload < NUM_LOAD_TYPES)
790     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
791   else
792     dissect_data(pd, offset, fd, tree);
793 }
794
795 static void
796 dissect_delete(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
797
798   struct delete_hdr *   hdr      = (struct delete_hdr *)(pd + offset);
799   guint16               length   = pntohs(&hdr->length);
800   guint32               doi      = pntohl(&hdr->doi);
801   guint16               num_spis = pntohs(&hdr->num_spis);
802   proto_item *          ti       = proto_tree_add_text(tree, offset, length, "Delete payload");
803   proto_tree *          ntree;
804   guint16               i;
805   
806   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
807   
808   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
809                       "Next payload: %s (%u)",
810                       payloadtype2str(hdr->next_payload), hdr->next_payload);
811   offset += sizeof(hdr->next_payload) * 2;
812   
813   proto_tree_add_text(ntree, offset, sizeof(length),
814                       "Length: %u", length);
815   offset += sizeof(length);
816   
817   proto_tree_add_text(ntree, offset, sizeof(doi),
818                       "Domain of Interpretation: %s (%u)", doitype2str(doi), doi);
819   offset += sizeof(doi);
820
821   proto_tree_add_text(ntree, offset, sizeof(hdr->protocol_id),
822                       "Protocol ID: %s (%u)",
823                       proto2str(hdr->protocol_id), hdr->protocol_id);
824   offset += sizeof(hdr->protocol_id);
825   
826   proto_tree_add_text(ntree, offset, sizeof(hdr->spi_size),
827                       "SPI size: %u", hdr->spi_size);
828   offset += sizeof(hdr->spi_size);
829   
830   proto_tree_add_text(ntree, offset, num_spis,
831                       "Number of SPIs: %u", num_spis);
832   offset += sizeof(hdr->num_spis);
833   
834   for (i = 0; i < num_spis; ++i) {
835     proto_tree_add_text(ntree, offset, hdr->spi_size,
836                         "SPI (%d)", i);
837     offset += hdr->spi_size;
838   }
839
840   if (hdr->next_payload < NUM_LOAD_TYPES)
841     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
842   else
843     dissect_data(pd, offset, fd, tree);
844 }
845
846 static void
847 dissect_vid(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
848
849   struct vid_hdr *      hdr     = (struct vid_hdr *)(pd + offset);
850   guint16               length  = pntohs(&hdr->length);
851   proto_item *          ti      = proto_tree_add_text(tree, offset, length, "Vendor ID payload");
852   proto_tree *          ntree;
853
854   ntree = proto_item_add_subtree(ti, ETT_ISAKMP_PAYLOAD);
855   
856   proto_tree_add_text(ntree, offset, sizeof(hdr->next_payload),
857                       "Next payload: %s (%u)",
858                       payloadtype2str(hdr->next_payload), hdr->next_payload);
859   offset += sizeof(hdr->next_payload) * 2;
860   
861   proto_tree_add_text(ntree, offset, sizeof(length),
862                       "Length: %u", length);
863   offset += sizeof(length);
864   
865   proto_tree_add_text(ntree, offset, length - sizeof(*hdr), "Vendor ID");
866   offset += (length - sizeof(*hdr));
867   
868   if (hdr->next_payload < NUM_LOAD_TYPES)
869     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
870   else
871     dissect_data(pd, offset, fd, tree);
872 }
873
874 static const char *
875 payloadtype2str(guint8 type) {
876
877   if (type < NUM_LOAD_TYPES) return strfuncs[type].str;
878   if (type < 128)            return "RESERVED";
879   if (type < 256)            return "Private USE";
880
881   return "Huh? You should never see this! Shame on you!";
882 }
883
884 static const char *
885 exchtype2str(guint8 type) {
886
887 #define NUM_EXCHSTRS    6
888   static const char * exchstrs[NUM_EXCHSTRS] = {
889     "NONE",
890     "Base",
891     "Identity Protection",
892     "Authentication Only",
893     "Aggressive",
894     "Informational"
895   };
896   
897   if (type < NUM_EXCHSTRS) return exchstrs[type];
898   if (type < 32)           return "ISAKMP Future Use";
899   if (type < 240)          return "DOI Specific Use";
900   if (type < 256)          return "Private Use";
901   
902   return "Huh? You should never see this! Shame on you!";
903 }
904
905 static const char *
906 doitype2str(guint32 type) {
907   if (type == 1) return "IPSEC";
908   return "Unknown DOI Type";
909 }
910
911 static const char *
912 msgtype2str(guint16 type) {
913
914 #define NUM_PREDEFINED  31
915   static const char *msgs[NUM_PREDEFINED] = {
916     "<UNKNOWN>",
917     "INVALID-PAYLOAD-TYPE",
918     "DOI-NOT-SUPPORTED",
919     "SITUATION-NOT-SUPPORTED",
920     "INVALID-COOKIE",
921     "INVALID-MAJOR-VERSION",
922     "INVALID-MINOR-VERSION",
923     "INVALID-EXCHANGE-TYPE",
924     "INVALID-FLAGS",
925     "INVALID-MESSAGE-ID",
926     "INVALID-PROTOCOL-ID",
927     "INVALID-SPI",
928     "INVALID-TRANSFORM-ID",
929     "ATTRIBUTES-NOT-SUPPORTED",
930     "NO-PROPOSAL-CHOSEN",
931     "BAD-PROPOSAL-SYNTAX",
932     "PAYLOAD-MALFORMED",
933     "INVALID-KEY-INFORMATION",
934     "INVALID-ID-INFORMATION",
935     "INVALID-CERT-ENCODING",
936     "INVALID-CERTIFICATE",
937     "CERT-TYPE-UNSUPPORTED",
938     "INVALID-CERT-AUTHORITY",
939     "INVALID-HASH-INFORMATION",
940     "AUTHENTICATION-FAILED",
941     "INVALID-SIGNATURE",
942     "ADDRESS-NOTIFICATION",
943     "NOTIFY-SA-LIFETIME",
944     "CERTIFICATE-UNAVAILABLE",
945     "UNSUPPORTED-EXCHANGE-TYPE",
946     "UNEQUAL-PAYLOAD-LENGTHS"
947   };
948
949   if (type < NUM_PREDEFINED) return msgs[type];
950   if (type < 8192)           return "RESERVED (Future Use)";
951   if (type < 16384)          return "Private Use";
952   if (type < 16385)          return "CONNECTED";
953   if (type < 24576)          return "RESERVED (Future Use) - status";
954   if (type < 24577)          return "RESPONDER-LIFETIME";
955   if (type < 24578)          return "REPLAY-STATUS";
956   if (type < 24579)          return "INITIAL-CONTACT";
957   if (type < 32768)          return "DOI-specific codes";
958   if (type < 40960)          return "Private Use - status";
959   if (type < 65535)          return "RESERVED (Future Use) - status (2)";
960
961   return "Huh? You should never see this! Shame on you!";
962 }
963
964 static const char *
965 situation2str(guint32 type) {
966
967 #define SIT_MSG_NUM     1024
968 #define SIT_IDENTITY    0x01
969 #define SIT_SECRECY     0x02
970 #define SIT_INTEGRITY   0x04
971
972   static char   msg[SIT_MSG_NUM];
973   int           n = 0;
974   char *        sep = "";
975   
976   if (type & SIT_IDENTITY) {
977     n += snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep);
978     sep = " & ";
979   }
980   if (type & SIT_SECRECY) {
981     n += snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep);
982     sep = " & ";
983   }
984   if (type & SIT_INTEGRITY) {
985     n += snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep);
986     sep = " & ";
987   }
988
989   return msg;
990 }
991
992 static const char *
993 value2str(guint16 att_type, guint16 value) {
994   
995   if (value == 0) return "RESERVED";
996   
997   switch (att_type) {
998     case 1:
999     case 2:
1000       switch (value) {
1001         case 1:  return "Seconds";
1002         case 2:  return "Kilobytes";
1003         default: return "UNKNOWN-SA-VALUE";
1004       }
1005     case 3:
1006       return "Group-Value";
1007     case 4:
1008       switch (value) {
1009         case 1:  return "Tunnel";
1010         case 2:  return "Transport";
1011         default: return "UNKNOWN-ENCAPSULATION-VALUE";
1012       }
1013     case 5:
1014       switch (value) {
1015         case 1:  return "HMAC-MD5";
1016         case 2:  return "HMAC-SHA";
1017         case 3:  return "DES-MAC";
1018         case 4:  return "KPDK";
1019         default: return "UNKNOWN-AUTHENTICATION-VALUE";
1020       }
1021     case 11:
1022       return "Life-Type";
1023     default: return "UNKNOWN-ATTRIBUTE-TYPE";
1024   }
1025 }
1026
1027 static const char *
1028 num2str(const guint8 *pd, guint16 len) {
1029
1030 #define NUMSTR_LEN      1024
1031   static char           numstr[NUMSTR_LEN];
1032   
1033   switch (len) {
1034   case 1:
1035     snprintf(numstr, NUMSTR_LEN, "%u", *pd);
1036     break;
1037   case 2:
1038     snprintf(numstr, NUMSTR_LEN, "%u", pntohs(pd));
1039     break;
1040   case 3:
1041     snprintf(numstr, NUMSTR_LEN, "%u", pntohl(pd) & 0x0fff);
1042     break;
1043   case 4:
1044     snprintf(numstr, NUMSTR_LEN, "%u", pntohl(pd));
1045     break;
1046   default:
1047     snprintf(numstr, NUMSTR_LEN, "<too big>");
1048   }
1049
1050   return numstr;
1051 }
1052
1053 void
1054 proto_register_isakmp(void)
1055 {
1056 /*        static hf_register_info hf[] = {
1057                 { &variable,
1058                 { "Name",           "isakmp.abbreviation", TYPE, VALS_POINTER }},
1059         };*/
1060
1061         proto_isakmp = proto_register_protocol("Internet Security Association and Key Management Protocol", "isakmp");
1062  /*       proto_register_field_array(proto_isakmp, hf, array_length(hf));*/
1063 }