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