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