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