Import tcpdump-3.9.8:
[dragonfly.git] / contrib / tcpdump-3.8.3 / print-isakmp.c
1 /*
2  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30
31 #ifndef lint
32 static const char rcsid[] _U_ =
33     "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.36.2.11 2004/03/24 01:32:42 guy Exp $ (LBL)";
34 #endif
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <tcpdump-stdinc.h>
41
42 #include <string.h>
43
44 #include <stdio.h>
45
46 #include "isakmp.h"
47 #include "ipsec_doi.h"
48 #include "oakley.h"
49 #include "interface.h"
50 #include "addrtoname.h"
51 #include "extract.h"                    /* must come after interface.h */
52
53 #include "ip.h"
54 #ifdef INET6
55 #include "ip6.h"
56 #endif
57
58 #ifndef HAVE_SOCKADDR_STORAGE
59 #define sockaddr_storage sockaddr
60 #endif
61
62 static const u_char *isakmp_sa_print(const struct isakmp_gen *,
63         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
64 static const u_char *isakmp_p_print(const struct isakmp_gen *,
65         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
66 static const u_char *isakmp_t_print(const struct isakmp_gen *,
67         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
68 static const u_char *isakmp_ke_print(const struct isakmp_gen *,
69         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
70 static const u_char *isakmp_id_print(const struct isakmp_gen *,
71         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
72 static const u_char *isakmp_cert_print(const struct isakmp_gen *,
73         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
74 static const u_char *isakmp_cr_print(const struct isakmp_gen *,
75         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
76 static const u_char *isakmp_sig_print(const struct isakmp_gen *,
77         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
78 static const u_char *isakmp_hash_print(const struct isakmp_gen *,
79         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
80 static const u_char *isakmp_nonce_print(const struct isakmp_gen *,
81         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
82 static const u_char *isakmp_n_print(const struct isakmp_gen *,
83         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
84 static const u_char *isakmp_d_print(const struct isakmp_gen *,
85         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
86 static const u_char *isakmp_vid_print(const struct isakmp_gen *,
87         u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
88 static const u_char *isakmp_sub0_print(u_char, const struct isakmp_gen *,
89         const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
90 static const u_char *isakmp_sub_print(u_char, const struct isakmp_gen *,
91         const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
92 static char *numstr(int);
93 static void safememcpy(void *, const void *, size_t);
94
95 #define MAXINITIATORS   20
96 int ninitiator = 0;
97 struct {
98         cookie_t initiator;
99         struct sockaddr_storage iaddr;
100         struct sockaddr_storage raddr;
101 } cookiecache[MAXINITIATORS];
102
103 /* protocol id */
104 static const char *protoidstr[] = {
105         NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
106 };
107
108 /* isakmp->np */
109 static const char *npstr[] = {
110         "none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash",
111         "sig", "nonce", "n", "d", "vid"
112 };
113
114 /* isakmp->np */
115 static const u_char *(*npfunc[])(const struct isakmp_gen *, u_int,
116                 const u_char *, u_int32_t, u_int32_t, u_int32_t, int) = {
117         NULL,
118         isakmp_sa_print,
119         isakmp_p_print,
120         isakmp_t_print,
121         isakmp_ke_print,
122         isakmp_id_print,
123         isakmp_cert_print,
124         isakmp_cr_print,
125         isakmp_hash_print,
126         isakmp_sig_print,
127         isakmp_nonce_print,
128         isakmp_n_print,
129         isakmp_d_print,
130         isakmp_vid_print,
131 };
132
133 /* isakmp->etype */
134 static const char *etypestr[] = {
135         "none", "base", "ident", "auth", "agg", "inf", NULL, NULL,
136         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
137         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
138         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
139         "oakley-quick", "oakley-newgroup",
140 };
141
142 #define STR_OR_ID(x, tab) \
143         (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
144 #define PROTOIDSTR(x)   STR_OR_ID(x, protoidstr)
145 #define NPSTR(x)        STR_OR_ID(x, npstr)
146 #define ETYPESTR(x)     STR_OR_ID(x, etypestr)
147
148 #define NPFUNC(x) \
149         (((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
150                 ? npfunc[(x)] : NULL)
151
152 static int
153 iszero(u_char *p, size_t l)
154 {
155         while (l--) {
156                 if (*p++)
157                         return 0;
158         }
159         return 1;
160 }
161
162 /* find cookie from initiator cache */
163 static int
164 cookie_find(cookie_t *in)
165 {
166         int i;
167
168         for (i = 0; i < MAXINITIATORS; i++) {
169                 if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
170                         return i;
171         }
172
173         return -1;
174 }
175
176 /* record initiator */
177 static void
178 cookie_record(cookie_t *in, const u_char *bp2)
179 {
180         int i;
181         struct ip *ip;
182         struct sockaddr_in *sin;
183 #ifdef INET6
184         struct ip6_hdr *ip6;
185         struct sockaddr_in6 *sin6;
186 #endif
187
188         i = cookie_find(in);
189         if (0 <= i) {
190                 ninitiator = (i + 1) % MAXINITIATORS;
191                 return;
192         }
193
194         ip = (struct ip *)bp2;
195         switch (IP_V(ip)) {
196         case 4:
197                 memset(&cookiecache[ninitiator].iaddr, 0,
198                         sizeof(cookiecache[ninitiator].iaddr));
199                 memset(&cookiecache[ninitiator].raddr, 0,
200                         sizeof(cookiecache[ninitiator].raddr));
201
202                 sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr;
203 #ifdef HAVE_SOCKADDR_SA_LEN
204                 sin->sin_len = sizeof(struct sockaddr_in);
205 #endif
206                 sin->sin_family = AF_INET;
207                 memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
208                 sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr;
209 #ifdef HAVE_SOCKADDR_SA_LEN
210                 sin->sin_len = sizeof(struct sockaddr_in);
211 #endif
212                 sin->sin_family = AF_INET;
213                 memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
214                 break;
215 #ifdef INET6
216         case 6:
217                 memset(&cookiecache[ninitiator].iaddr, 0,
218                         sizeof(cookiecache[ninitiator].iaddr));
219                 memset(&cookiecache[ninitiator].raddr, 0,
220                         sizeof(cookiecache[ninitiator].raddr));
221
222                 ip6 = (struct ip6_hdr *)bp2;
223                 sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr;
224 #ifdef HAVE_SOCKADDR_SA_LEN
225                 sin6->sin6_len = sizeof(struct sockaddr_in6);
226 #endif
227                 sin6->sin6_family = AF_INET6;
228                 memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
229                 sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr;
230 #ifdef HAVE_SOCKADDR_SA_LEN
231                 sin6->sin6_len = sizeof(struct sockaddr_in6);
232 #endif
233                 sin6->sin6_family = AF_INET6;
234                 memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
235                 break;
236 #endif
237         default:
238                 return;
239         }
240         memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in));
241         ninitiator = (ninitiator + 1) % MAXINITIATORS;
242 }
243
244 #define cookie_isinitiator(x, y)        cookie_sidecheck((x), (y), 1)
245 #define cookie_isresponder(x, y)        cookie_sidecheck((x), (y), 0)
246 static int
247 cookie_sidecheck(int i, const u_char *bp2, int initiator)
248 {
249         struct sockaddr_storage ss;
250         struct sockaddr *sa;
251         struct ip *ip;
252         struct sockaddr_in *sin;
253 #ifdef INET6
254         struct ip6_hdr *ip6;
255         struct sockaddr_in6 *sin6;
256 #endif
257         int salen;
258
259         memset(&ss, 0, sizeof(ss));
260         ip = (struct ip *)bp2;
261         switch (IP_V(ip)) {
262         case 4:
263                 sin = (struct sockaddr_in *)&ss;
264 #ifdef HAVE_SOCKADDR_SA_LEN
265                 sin->sin_len = sizeof(struct sockaddr_in);
266 #endif
267                 sin->sin_family = AF_INET;
268                 memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
269                 break;
270 #ifdef INET6
271         case 6:
272                 ip6 = (struct ip6_hdr *)bp2;
273                 sin6 = (struct sockaddr_in6 *)&ss;
274 #ifdef HAVE_SOCKADDR_SA_LEN
275                 sin6->sin6_len = sizeof(struct sockaddr_in6);
276 #endif
277                 sin6->sin6_family = AF_INET6;
278                 memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
279                 break;
280 #endif
281         default:
282                 return 0;
283         }
284
285         sa = (struct sockaddr *)&ss;
286         if (initiator) {
287                 if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].iaddr)->sa_family)
288                         return 0;
289 #ifdef HAVE_SOCKADDR_SA_LEN
290                 salen = sa->sa_len;
291 #else
292 #ifdef INET6
293                 if (sa->sa_family == AF_INET6)
294                         salen = sizeof(struct sockaddr_in6);
295                 else
296                         salen = sizeof(struct sockaddr);
297 #else
298                 salen = sizeof(struct sockaddr);
299 #endif
300 #endif
301                 if (memcmp(&ss, &cookiecache[i].iaddr, salen) == 0)
302                         return 1;
303         } else {
304                 if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].raddr)->sa_family)
305                         return 0;
306 #ifdef HAVE_SOCKADDR_SA_LEN
307                 salen = sa->sa_len;
308 #else
309 #ifdef INET6
310                 if (sa->sa_family == AF_INET6)
311                         salen = sizeof(struct sockaddr_in6);
312                 else
313                         salen = sizeof(struct sockaddr);
314 #else
315                 salen = sizeof(struct sockaddr);
316 #endif
317 #endif
318                 if (memcmp(&ss, &cookiecache[i].raddr, salen) == 0)
319                         return 1;
320         }
321         return 0;
322 }
323
324 static int
325 rawprint(caddr_t loc, size_t len)
326 {
327         static u_char *p;
328         size_t i;
329
330         TCHECK2(*loc, len);
331         
332         p = (u_char *)loc;
333         for (i = 0; i < len; i++)
334                 printf("%02x", p[i] & 0xff);
335         return 1;
336 trunc:
337         return 0;
338 }
339
340 struct attrmap {
341         const char *type;
342         u_int nvalue;
343         const char *value[30];  /*XXX*/
344 };
345
346 static const u_char *
347 isakmp_attrmap_print(const u_char *p, const u_char *ep,
348         const struct attrmap *map, size_t nmap)
349 {
350         u_int16_t *q;
351         int totlen;
352         u_int32_t t, v;
353
354         q = (u_int16_t *)p;
355         if (p[0] & 0x80)
356                 totlen = 4;
357         else
358                 totlen = 4 + EXTRACT_16BITS(&q[1]);
359         if (ep < p + totlen) {
360                 printf("[|attr]");
361                 return ep + 1;
362         }
363
364         printf("(");
365         t = EXTRACT_16BITS(&q[0]) & 0x7fff;
366         if (map && t < nmap && map[t].type)
367                 printf("type=%s ", map[t].type);
368         else
369                 printf("type=#%d ", t);
370         if (p[0] & 0x80) {
371                 printf("value=");
372                 v = EXTRACT_16BITS(&q[1]);
373                 if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
374                         printf("%s", map[t].value[v]);
375                 else
376                         rawprint((caddr_t)&q[1], 2);
377         } else {
378                 printf("len=%d value=", EXTRACT_16BITS(&q[1]));
379                 rawprint((caddr_t)&p[4], EXTRACT_16BITS(&q[1]));
380         }
381         printf(")");
382         return p + totlen;
383 }
384
385 static const u_char *
386 isakmp_attr_print(const u_char *p, const u_char *ep)
387 {
388         u_int16_t *q;
389         int totlen;
390         u_int32_t t;
391
392         q = (u_int16_t *)p;
393         if (p[0] & 0x80)
394                 totlen = 4;
395         else
396                 totlen = 4 + EXTRACT_16BITS(&q[1]);
397         if (ep < p + totlen) {
398                 printf("[|attr]");
399                 return ep + 1;
400         }
401
402         printf("(");
403         t = EXTRACT_16BITS(&q[0]) & 0x7fff;
404         printf("type=#%d ", t);
405         if (p[0] & 0x80) {
406                 printf("value=");
407                 t = q[1];
408                 rawprint((caddr_t)&q[1], 2);
409         } else {
410                 printf("len=%d value=", EXTRACT_16BITS(&q[1]));
411                 rawprint((caddr_t)&p[2], EXTRACT_16BITS(&q[1]));
412         }
413         printf(")");
414         return p + totlen;
415 }
416
417 static const u_char *
418 isakmp_sa_print(const struct isakmp_gen *ext, u_int item_len,
419         const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
420         u_int32_t proto0, int depth)
421 {
422         const struct isakmp_pl_sa *p;
423         struct isakmp_pl_sa sa;
424         const u_int32_t *q;
425         u_int32_t doi, sit, ident;
426         const u_char *cp, *np;
427         int t;
428
429         printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
430
431         p = (struct isakmp_pl_sa *)ext;
432         TCHECK(*p);
433         safememcpy(&sa, ext, sizeof(sa));
434         doi = ntohl(sa.doi);
435         sit = ntohl(sa.sit);
436         if (doi != 1) {
437                 printf(" doi=%d", doi);
438                 printf(" situation=%u", (u_int32_t)ntohl(sa.sit));
439                 return (u_char *)(p + 1);
440         }
441
442         printf(" doi=ipsec");
443         q = (u_int32_t *)&sa.sit;
444         printf(" situation=");
445         t = 0;
446         if (sit & 0x01) {
447                 printf("identity");
448                 t++;
449         }
450         if (sit & 0x02) {
451                 printf("%ssecrecy", t ? "+" : "");
452                 t++;
453         }
454         if (sit & 0x04)
455                 printf("%sintegrity", t ? "+" : "");
456
457         np = (u_char *)ext + sizeof(sa);
458         if (sit != 0x01) {
459                 TCHECK2(*(ext + 1), sizeof(ident));
460                 safememcpy(&ident, ext + 1, sizeof(ident));
461                 printf(" ident=%u", (u_int32_t)ntohl(ident));
462                 np += sizeof(ident);
463         }
464
465         ext = (struct isakmp_gen *)np;
466         TCHECK(*ext);
467
468         cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
469                 depth);
470
471         return cp;
472 trunc:
473         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
474         return NULL;
475 }
476
477 static const u_char *
478 isakmp_p_print(const struct isakmp_gen *ext, u_int item_len,
479         const u_char *ep, u_int32_t phase, u_int32_t doi0,
480         u_int32_t proto0 _U_, int depth)
481 {
482         const struct isakmp_pl_p *p;
483         struct isakmp_pl_p prop;
484         const u_char *cp;
485
486         printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
487
488         p = (struct isakmp_pl_p *)ext;
489         TCHECK(*p);
490         safememcpy(&prop, ext, sizeof(prop));
491         printf(" #%d protoid=%s transform=%d",
492                 prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
493         if (prop.spi_size) {
494                 printf(" spi=");
495                 if (!rawprint((caddr_t)(p + 1), prop.spi_size))
496                         goto trunc;
497         }
498
499         ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
500         TCHECK(*ext);
501
502         cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
503                 prop.prot_id, depth);
504
505         return cp;
506 trunc:
507         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
508         return NULL;
509 }
510
511 static const char *isakmp_p_map[] = {
512         NULL, "ike",
513 };
514
515 static const char *ah_p_map[] = {
516         NULL, "(reserved)", "md5", "sha", "1des",
517         "sha2-256", "sha2-384", "sha2-512",
518 };
519
520 static const char *esp_p_map[] = {
521         NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
522         "blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
523 };
524
525 static const char *ipcomp_p_map[] = {
526         NULL, "oui", "deflate", "lzs",
527 };
528
529 const struct attrmap ipsec_t_map[] = {
530         { NULL, 0, { NULL } },
531         { "lifetype", 3, { NULL, "sec", "kb", }, },
532         { "life", 0, { NULL } },
533         { "group desc", 5,      { NULL, "modp768", "modp1024", "EC2N 2^155",
534                                   "EC2N 2^185", }, },
535         { "enc mode", 3, { NULL, "tunnel", "transport", }, },
536         { "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
537         { "keylen", 0, { NULL } },
538         { "rounds", 0, { NULL } },
539         { "dictsize", 0, { NULL } },
540         { "privalg", 0, { NULL } },
541 };
542
543 const struct attrmap oakley_t_map[] = {
544         { NULL, 0, { NULL } },
545         { "enc", 8,     { NULL, "1des", "idea", "blowfish", "rc5",
546                           "3des", "cast", "aes", }, },
547         { "hash", 7,    { NULL, "md5", "sha1", "tiger",
548                           "sha2-256", "sha2-384", "sha2-512", }, },
549         { "auth", 6,    { NULL, "preshared", "dss", "rsa sig", "rsa enc",
550                           "rsa enc revised", }, },
551         { "group desc", 5,      { NULL, "modp768", "modp1024", "EC2N 2^155",
552                                   "EC2N 2^185", }, },
553         { "group type", 4,      { NULL, "MODP", "ECP", "EC2N", }, },
554         { "group prime", 0, { NULL } },
555         { "group gen1", 0, { NULL } },
556         { "group gen2", 0, { NULL } },
557         { "group curve A", 0, { NULL } },
558         { "group curve B", 0, { NULL } },
559         { "lifetype", 3,        { NULL, "sec", "kb", }, },
560         { "lifeduration", 0, { NULL } },
561         { "prf", 0, { NULL } },
562         { "keylen", 0, { NULL } },
563         { "field", 0, { NULL } },
564         { "order", 0, { NULL } },
565 };
566
567 static const u_char *
568 isakmp_t_print(const struct isakmp_gen *ext, u_int item_len,
569         const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
570         u_int32_t proto, int depth _U_)
571 {
572         const struct isakmp_pl_t *p;
573         struct isakmp_pl_t t;
574         const u_char *cp;
575         const char *idstr;
576         const struct attrmap *map;
577         size_t nmap;
578         const u_char *ep2;
579
580         printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
581
582         p = (struct isakmp_pl_t *)ext;
583         TCHECK(*p);
584         safememcpy(&t, ext, sizeof(t));
585
586         switch (proto) {
587         case 1:
588                 idstr = STR_OR_ID(t.t_id, isakmp_p_map);
589                 map = oakley_t_map;
590                 nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
591                 break;
592         case 2:
593                 idstr = STR_OR_ID(t.t_id, ah_p_map);
594                 map = ipsec_t_map;
595                 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
596                 break;
597         case 3:
598                 idstr = STR_OR_ID(t.t_id, esp_p_map);
599                 map = ipsec_t_map;
600                 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
601                 break;
602         case 4:
603                 idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
604                 map = ipsec_t_map;
605                 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
606                 break;
607         default:
608                 idstr = NULL;
609                 map = NULL;
610                 nmap = 0;
611                 break;
612         }
613
614         if (idstr)
615                 printf(" #%d id=%s ", t.t_no, idstr);
616         else
617                 printf(" #%d id=%d ", t.t_no, t.t_id);
618         cp = (u_char *)(p + 1);
619         ep2 = (u_char *)p + item_len;
620         while (cp < ep && cp < ep2) {
621                 if (map && nmap) {
622                         cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
623                                 map, nmap);
624                 } else
625                         cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
626         }
627         if (ep < ep2)
628                 printf("...");
629         return cp;
630 trunc:
631         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
632         return NULL;
633 }
634
635 static const u_char *
636 isakmp_ke_print(const struct isakmp_gen *ext, u_int item_len,
637         const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
638         u_int32_t proto _U_, int depth _U_)
639 {
640         struct isakmp_gen e;
641
642         printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
643
644         TCHECK(*ext);
645         safememcpy(&e, ext, sizeof(e));
646         printf(" key len=%d", ntohs(e.len) - 4);
647         if (2 < vflag && 4 < ntohs(e.len)) {
648                 printf(" ");
649                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
650                         goto trunc;
651         }
652         return (u_char *)ext + ntohs(e.len);
653 trunc:
654         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
655         return NULL;
656 }
657
658 static const u_char *
659 isakmp_id_print(const struct isakmp_gen *ext, u_int item_len,
660         const u_char *ep, u_int32_t phase, u_int32_t doi _U_,
661         u_int32_t proto _U_, int depth _U_)
662 {
663 #define USE_IPSECDOI_IN_PHASE1  1
664         const struct isakmp_pl_id *p;
665         struct isakmp_pl_id id;
666         static const char *idtypestr[] = {
667                 "IPv4", "IPv4net", "IPv6", "IPv6net",
668         };
669         static const char *ipsecidtypestr[] = {
670                 NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
671                 "IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
672                 "keyid",
673         };
674         int len;
675         const u_char *data;
676
677         printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
678
679         p = (struct isakmp_pl_id *)ext;
680         TCHECK(*p);
681         safememcpy(&id, ext, sizeof(id));
682         if (sizeof(*p) < item_len) {
683                 data = (u_char *)(p + 1);
684                 len = item_len - sizeof(*p);
685         } else {
686                 data = NULL;
687                 len = 0;
688         }
689
690 #if 0 /*debug*/
691         printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
692 #endif
693         switch (phase) {
694 #ifndef USE_IPSECDOI_IN_PHASE1
695         case 1:
696 #endif
697         default:
698                 printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr));
699                 printf(" doi_data=%u",
700                         (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff));
701                 break;
702
703 #ifdef USE_IPSECDOI_IN_PHASE1
704         case 1:
705 #endif
706         case 2:
707             {
708                 const struct ipsecdoi_id *p;
709                 struct ipsecdoi_id id;
710                 struct protoent *pe;
711
712                 p = (struct ipsecdoi_id *)ext;
713                 TCHECK(*p);
714                 safememcpy(&id, ext, sizeof(id));
715                 printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
716                 if (id.proto_id) {
717 #ifndef WIN32
718                         setprotoent(1);
719 #endif /* WIN32 */
720                         pe = getprotobynumber(id.proto_id);
721                         if (pe)
722                                 printf(" protoid=%s", pe->p_name);
723 #ifndef WIN32
724                         endprotoent();
725 #endif /* WIN32 */
726                 } else {
727                         /* it DOES NOT mean IPPROTO_IP! */
728                         printf(" protoid=%s", "0");
729                 }
730                 printf(" port=%d", ntohs(id.port));
731                 if (!len)
732                         break;
733                 if (data == NULL)
734                         goto trunc;
735                 TCHECK2(*data, len);
736                 switch (id.type) {
737                 case IPSECDOI_ID_IPV4_ADDR:
738                         if (len < 4)
739                                 printf(" len=%d [bad: < 4]", len);
740                         else
741                                 printf(" len=%d %s", len, ipaddr_string(data));
742                         len = 0;
743                         break;
744                 case IPSECDOI_ID_FQDN:
745                 case IPSECDOI_ID_USER_FQDN:
746                     {
747                         int i;
748                         printf(" len=%d ", len);
749                         for (i = 0; i < len; i++)
750                                 safeputchar(data[i]);
751                         len = 0;
752                         break;
753                     }
754                 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
755                     {
756                         const u_char *mask;
757                         if (len < 8)
758                                 printf(" len=%d [bad: < 8]", len);
759                         else {
760                                 mask = data + sizeof(struct in_addr);
761                                 printf(" len=%d %s/%u.%u.%u.%u", len,
762                                         ipaddr_string(data),
763                                         mask[0], mask[1], mask[2], mask[3]);
764                         }
765                         len = 0;
766                         break;
767                     }
768 #ifdef INET6
769                 case IPSECDOI_ID_IPV6_ADDR:
770                         if (len < 16)
771                                 printf(" len=%d [bad: < 16]", len);
772                         else
773                                 printf(" len=%d %s", len, ip6addr_string(data));
774                         len = 0;
775                         break;
776                 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
777                     {
778                         const u_int32_t *mask;
779                         if (len < 20)
780                                 printf(" len=%d [bad: < 20]", len);
781                         else {
782                                 mask = (u_int32_t *)(data + sizeof(struct in6_addr));
783                                 /*XXX*/
784                                 printf(" len=%d %s/0x%08x%08x%08x%08x", len,
785                                         ip6addr_string(data),
786                                         mask[0], mask[1], mask[2], mask[3]);
787                         }
788                         len = 0;
789                         break;
790                     }
791 #endif /*INET6*/
792                 case IPSECDOI_ID_IPV4_ADDR_RANGE:
793                         if (len < 8)
794                                 printf(" len=%d [bad: < 8]", len);
795                         else {
796                                 printf(" len=%d %s-%s", len,
797                                         ipaddr_string(data),
798                                         ipaddr_string(data + sizeof(struct in_addr)));
799                         }
800                         len = 0;
801                         break;
802 #ifdef INET6
803                 case IPSECDOI_ID_IPV6_ADDR_RANGE:
804                         if (len < 32)
805                                 printf(" len=%d [bad: < 32]", len);
806                         else {
807                                 printf(" len=%d %s-%s", len,
808                                         ip6addr_string(data),
809                                         ip6addr_string(data + sizeof(struct in6_addr)));
810                         }
811                         len = 0;
812                         break;
813 #endif /*INET6*/
814                 case IPSECDOI_ID_DER_ASN1_DN:
815                 case IPSECDOI_ID_DER_ASN1_GN:
816                 case IPSECDOI_ID_KEY_ID:
817                         break;
818                 }
819                 break;
820             }
821         }
822         if (data && len) {
823                 printf(" len=%d", len);
824                 if (2 < vflag) {
825                         printf(" ");
826                         if (!rawprint((caddr_t)data, len))
827                                 goto trunc;
828                 }
829         }
830         return (u_char *)ext + item_len;
831 trunc:
832         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
833         return NULL;
834 }
835
836 static const u_char *
837 isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len,
838         const u_char *ep, u_int32_t phase _U_, u_int32_t doi0 _U_,
839         u_int32_t proto0 _U_, int depth _U_)
840 {
841         const struct isakmp_pl_cert *p;
842         struct isakmp_pl_cert cert;
843         static const char *certstr[] = {
844                 "none", "pkcs7", "pgp", "dns",
845                 "x509sign", "x509ke", "kerberos", "crl",
846                 "arl", "spki", "x509attr",
847         };
848
849         printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
850
851         p = (struct isakmp_pl_cert *)ext;
852         TCHECK(*p);
853         safememcpy(&cert, ext, sizeof(cert));
854         printf(" len=%d", item_len - 4);
855         printf(" type=%s", STR_OR_ID((cert.encode), certstr));
856         if (2 < vflag && 4 < item_len) {
857                 printf(" ");
858                 if (!rawprint((caddr_t)(ext + 1), item_len - 4))
859                         goto trunc;
860         }
861         return (u_char *)ext + item_len;
862 trunc:
863         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
864         return NULL;
865 }
866
867 static const u_char *
868 isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len,
869         const u_char *ep, u_int32_t phase _U_, u_int32_t doi0 _U_,
870         u_int32_t proto0 _U_, int depth _U_)
871 {
872         const struct isakmp_pl_cert *p;
873         struct isakmp_pl_cert cert;
874         static const char *certstr[] = {
875                 "none", "pkcs7", "pgp", "dns",
876                 "x509sign", "x509ke", "kerberos", "crl",
877                 "arl", "spki", "x509attr",
878         };
879
880         printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
881
882         p = (struct isakmp_pl_cert *)ext;
883         TCHECK(*p);
884         safememcpy(&cert, ext, sizeof(cert));
885         printf(" len=%d", item_len - 4);
886         printf(" type=%s", STR_OR_ID((cert.encode), certstr));
887         if (2 < vflag && 4 < item_len) {
888                 printf(" ");
889                 if (!rawprint((caddr_t)(ext + 1), item_len - 4))
890                         goto trunc;
891         }
892         return (u_char *)ext + item_len;
893 trunc:
894         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
895         return NULL;
896 }
897
898 static const u_char *
899 isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len,
900         const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
901         u_int32_t proto _U_, int depth _U_)
902 {
903         struct isakmp_gen e;
904
905         printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
906
907         TCHECK(*ext);
908         safememcpy(&e, ext, sizeof(e));
909         printf(" len=%d", ntohs(e.len) - 4);
910         if (2 < vflag && 4 < ntohs(e.len)) {
911                 printf(" ");
912                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
913                         goto trunc;
914         }
915         return (u_char *)ext + ntohs(e.len);
916 trunc:
917         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
918         return NULL;
919 }
920
921 static const u_char *
922 isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len,
923         const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
924         u_int32_t proto _U_, int depth _U_)
925 {
926         struct isakmp_gen e;
927
928         printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
929
930         TCHECK(*ext);
931         safememcpy(&e, ext, sizeof(e));
932         printf(" len=%d", ntohs(e.len) - 4);
933         if (2 < vflag && 4 < ntohs(e.len)) {
934                 printf(" ");
935                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
936                         goto trunc;
937         }
938         return (u_char *)ext + ntohs(e.len);
939 trunc:
940         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
941         return NULL;
942 }
943
944 static const u_char *
945 isakmp_nonce_print(const struct isakmp_gen *ext, u_int item_len,
946         const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
947         u_int32_t proto _U_, int depth _U_)
948 {
949         struct isakmp_gen e;
950
951         printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
952
953         TCHECK(*ext);
954         safememcpy(&e, ext, sizeof(e));
955         printf(" n len=%d", ntohs(e.len) - 4);
956         if (2 < vflag && 4 < ntohs(e.len)) {
957                 printf(" ");
958                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
959                         goto trunc;
960         }
961         return (u_char *)ext + ntohs(e.len);
962 trunc:
963         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
964         return NULL;
965 }
966
967 static const u_char *
968 isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
969         const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
970         u_int32_t proto0 _U_, int depth)
971 {
972         struct isakmp_pl_n *p, n;
973         const u_char *cp;
974         u_char *ep2;
975         u_int32_t doi;
976         u_int32_t proto;
977         static const char *notify_error_str[] = {
978                 NULL,                           "INVALID-PAYLOAD-TYPE",
979                 "DOI-NOT-SUPPORTED",            "SITUATION-NOT-SUPPORTED",
980                 "INVALID-COOKIE",               "INVALID-MAJOR-VERSION",
981                 "INVALID-MINOR-VERSION",        "INVALID-EXCHANGE-TYPE",
982                 "INVALID-FLAGS",                "INVALID-MESSAGE-ID",
983                 "INVALID-PROTOCOL-ID",          "INVALID-SPI",
984                 "INVALID-TRANSFORM-ID",         "ATTRIBUTES-NOT-SUPPORTED",
985                 "NO-PROPOSAL-CHOSEN",           "BAD-PROPOSAL-SYNTAX",
986                 "PAYLOAD-MALFORMED",            "INVALID-KEY-INFORMATION",
987                 "INVALID-ID-INFORMATION",       "INVALID-CERT-ENCODING",
988                 "INVALID-CERTIFICATE",          "CERT-TYPE-UNSUPPORTED",
989                 "INVALID-CERT-AUTHORITY",       "INVALID-HASH-INFORMATION",
990                 "AUTHENTICATION-FAILED",        "INVALID-SIGNATURE",
991                 "ADDRESS-NOTIFICATION",         "NOTIFY-SA-LIFETIME",
992                 "CERTIFICATE-UNAVAILABLE",      "UNSUPPORTED-EXCHANGE-TYPE",
993                 "UNEQUAL-PAYLOAD-LENGTHS",
994         };
995         static const char *ipsec_notify_error_str[] = {
996                 "RESERVED",
997         };
998         static const char *notify_status_str[] = {
999                 "CONNECTED",
1000         };
1001         static const char *ipsec_notify_status_str[] = {
1002                 "RESPONDER-LIFETIME",           "REPLAY-STATUS",
1003                 "INITIAL-CONTACT",
1004         };
1005 /* NOTE: these macro must be called with x in proper range */
1006
1007 /* 0 - 8191 */
1008 #define NOTIFY_ERROR_STR(x) \
1009         STR_OR_ID((x), notify_error_str)
1010
1011 /* 8192 - 16383 */
1012 #define IPSEC_NOTIFY_ERROR_STR(x) \
1013         STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1014
1015 /* 16384 - 24575 */
1016 #define NOTIFY_STATUS_STR(x) \
1017         STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1018
1019 /* 24576 - 32767 */
1020 #define IPSEC_NOTIFY_STATUS_STR(x) \
1021         STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1022
1023         printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
1024
1025         p = (struct isakmp_pl_n *)ext;
1026         TCHECK(*p);
1027         safememcpy(&n, ext, sizeof(n));
1028         doi = ntohl(n.doi);
1029         proto = n.prot_id;
1030         if (doi != 1) {
1031                 printf(" doi=%d", doi);
1032                 printf(" proto=%d", proto);
1033                 if (ntohs(n.type) < 8192)
1034                         printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1035                 else if (ntohs(n.type) < 16384)
1036                         printf(" type=%s", numstr(ntohs(n.type)));
1037                 else if (ntohs(n.type) < 24576)
1038                         printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1039                 else
1040                         printf(" type=%s", numstr(ntohs(n.type)));
1041                 if (n.spi_size) {
1042                         printf(" spi=");
1043                         if (!rawprint((caddr_t)(p + 1), n.spi_size))
1044                                 goto trunc;
1045                 }
1046                 return (u_char *)(p + 1) + n.spi_size;
1047         }
1048
1049         printf(" doi=ipsec");
1050         printf(" proto=%s", PROTOIDSTR(proto));
1051         if (ntohs(n.type) < 8192)
1052                 printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1053         else if (ntohs(n.type) < 16384)
1054                 printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type)));
1055         else if (ntohs(n.type) < 24576)
1056                 printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1057         else if (ntohs(n.type) < 32768)
1058                 printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type)));
1059         else
1060                 printf(" type=%s", numstr(ntohs(n.type)));
1061         if (n.spi_size) {
1062                 printf(" spi=");
1063                 if (!rawprint((caddr_t)(p + 1), n.spi_size))
1064                         goto trunc;
1065         }
1066
1067         cp = (u_char *)(p + 1) + n.spi_size;
1068         ep2 = (u_char *)p + item_len;
1069
1070         if (cp < ep) {
1071                 printf(" orig=(");
1072                 switch (ntohs(n.type)) {
1073                 case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
1074                     {
1075                         const struct attrmap *map = oakley_t_map;
1076                         size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1077                         while (cp < ep && cp < ep2) {
1078                                 cp = isakmp_attrmap_print(cp,
1079                                         (ep < ep2) ? ep : ep2, map, nmap);
1080                         }
1081                         break;
1082                     }
1083                 case IPSECDOI_NTYPE_REPLAY_STATUS:
1084                         printf("replay detection %sabled",
1085                                 (*(u_int32_t *)cp) ? "en" : "dis");
1086                         break;
1087                 case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
1088                         if (isakmp_sub_print(ISAKMP_NPTYPE_SA,
1089                             (struct isakmp_gen *)cp, ep, phase, doi, proto,
1090                             depth) == NULL)
1091                                 return NULL;
1092                         break;
1093                 default:
1094                         /* NULL is dummy */
1095                         isakmp_print(cp, item_len - sizeof(*p) - n.spi_size,
1096                                 NULL);
1097                 }
1098                 printf(")");
1099         }
1100         return (u_char *)ext + item_len;
1101 trunc:
1102         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
1103         return NULL;
1104 }
1105
1106 static const u_char *
1107 isakmp_d_print(const struct isakmp_gen *ext, u_int item_len,
1108         const u_char *ep, u_int32_t phase _U_, u_int32_t doi0 _U_,
1109         u_int32_t proto0 _U_, int depth _U_)
1110 {
1111         const struct isakmp_pl_d *p;
1112         struct isakmp_pl_d d;
1113         const u_int8_t *q;
1114         u_int32_t doi;
1115         u_int32_t proto;
1116         int i;
1117
1118         printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
1119
1120         p = (struct isakmp_pl_d *)ext;
1121         TCHECK(*p);
1122         safememcpy(&d, ext, sizeof(d));
1123         doi = ntohl(d.doi);
1124         proto = d.prot_id;
1125         if (doi != 1) {
1126                 printf(" doi=%u", doi);
1127                 printf(" proto=%u", proto);
1128         } else {
1129                 printf(" doi=ipsec");
1130                 printf(" proto=%s", PROTOIDSTR(proto));
1131         }
1132         printf(" spilen=%u", d.spi_size);
1133         printf(" nspi=%u", ntohs(d.num_spi));
1134         printf(" spi=");
1135         q = (u_int8_t *)(p + 1);
1136         for (i = 0; i < ntohs(d.num_spi); i++) {
1137                 if (i != 0)
1138                         printf(",");
1139                 if (!rawprint((caddr_t)q, d.spi_size))
1140                         goto trunc;
1141                 q += d.spi_size;
1142         }
1143         return q;
1144 trunc:
1145         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
1146         return NULL;
1147 }
1148
1149 static const u_char *
1150 isakmp_vid_print(const struct isakmp_gen *ext, u_int item_len,
1151         const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
1152         u_int32_t proto _U_, int depth _U_)
1153 {
1154         struct isakmp_gen e;
1155
1156         printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1157
1158         TCHECK(*ext);
1159         safememcpy(&e, ext, sizeof(e));
1160         printf(" len=%d", ntohs(e.len) - 4);
1161         if (2 < vflag && 4 < ntohs(e.len)) {
1162                 printf(" ");
1163                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
1164                         goto trunc;
1165         }
1166         return (u_char *)ext + ntohs(e.len);
1167 trunc:
1168         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
1169         return NULL;
1170 }
1171
1172 static const u_char *
1173 isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1174         u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1175 {
1176         const u_char *cp;
1177         struct isakmp_gen e;
1178         u_int item_len;
1179
1180         cp = (u_char *)ext;
1181         TCHECK(*ext);
1182         safememcpy(&e, ext, sizeof(e));
1183
1184         /*
1185          * Since we can't have a payload length of less than 4 bytes,
1186          * we need to bail out here if the generic header is nonsensical
1187          * or truncated, otherwise we could loop forever processing
1188          * zero-length items or otherwise misdissect the packet.
1189          */
1190         item_len = ntohs(e.len);
1191         if (item_len <= 4)
1192                 return NULL;
1193
1194         if (NPFUNC(np)) {
1195                 /*
1196                  * XXX - what if item_len is too short, or too long,
1197                  * for this payload type?
1198                  */
1199                 cp = (*NPFUNC(np))(ext, item_len, ep, phase, doi, proto, depth);
1200         } else {
1201                 printf("%s", NPSTR(np));
1202                 cp += item_len;
1203         }
1204
1205         return cp;
1206 trunc:
1207         printf(" [|isakmp]");
1208         return NULL;
1209 }
1210
1211 static const u_char *
1212 isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1213         u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1214 {
1215         const u_char *cp;
1216         int i;
1217         struct isakmp_gen e;
1218
1219         cp = (const u_char *)ext;
1220
1221         while (np) {
1222                 TCHECK(*ext);
1223                 
1224                 safememcpy(&e, ext, sizeof(e));
1225
1226                 TCHECK2(*ext, ntohs(e.len));
1227
1228                 depth++;
1229                 printf("\n");
1230                 for (i = 0; i < depth; i++)
1231                         printf("    ");
1232                 printf("(");
1233                 cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth);
1234                 printf(")");
1235                 depth--;
1236
1237                 if (cp == NULL) {
1238                         /* Zero-length subitem */
1239                         return NULL;
1240                 }
1241
1242                 np = e.np;
1243                 ext = (struct isakmp_gen *)cp;
1244         }
1245         return cp;
1246 trunc:
1247         printf(" [|%s]", NPSTR(np));
1248         return NULL;
1249 }
1250
1251 static char *
1252 numstr(int x)
1253 {
1254         static char buf[20];
1255         snprintf(buf, sizeof(buf), "#%d", x);
1256         return buf;
1257 }
1258
1259 /*
1260  * some compiler tries to optimize memcpy(), using the alignment constraint
1261  * on the argument pointer type.  by using this function, we try to avoid the
1262  * optimization.
1263  */
1264 static void
1265 safememcpy(void *p, const void *q, size_t l)
1266 {
1267         memcpy(p, q, l);
1268 }
1269
1270 void
1271 isakmp_print(const u_char *bp, u_int length, const u_char *bp2)
1272 {
1273         const struct isakmp *p;
1274         struct isakmp base;
1275         const u_char *ep;
1276         u_char np;
1277         int i;
1278         int phase;
1279         int major, minor;
1280
1281         p = (const struct isakmp *)bp;
1282         ep = snapend;
1283
1284         if ((struct isakmp *)ep < p + 1) {
1285                 printf("[|isakmp]");
1286                 return;
1287         }
1288
1289         safememcpy(&base, p, sizeof(base));
1290
1291         printf("isakmp");
1292         if (vflag) {
1293                 major = (base.vers & ISAKMP_VERS_MAJOR)
1294                                 >> ISAKMP_VERS_MAJOR_SHIFT;
1295                 minor = (base.vers & ISAKMP_VERS_MINOR)
1296                                 >> ISAKMP_VERS_MINOR_SHIFT;
1297                 printf(" %d.%d", major, minor);
1298         }
1299
1300         if (vflag) {
1301                 printf(" msgid ");
1302                 rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
1303         }
1304
1305         if (1 < vflag) {
1306                 printf(" cookie ");
1307                 rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
1308                 printf("->");
1309                 rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
1310         }
1311         printf(":");
1312
1313         phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
1314         if (phase == 1)
1315                 printf(" phase %d", phase);
1316         else
1317                 printf(" phase %d/others", phase);
1318
1319         i = cookie_find(&base.i_ck);
1320         if (i < 0) {
1321                 if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
1322                         /* the first packet */
1323                         printf(" I");
1324                         if (bp2)
1325                                 cookie_record(&base.i_ck, bp2);
1326                 } else
1327                         printf(" ?");
1328         } else {
1329                 if (bp2 && cookie_isinitiator(i, bp2))
1330                         printf(" I");
1331                 else if (bp2 && cookie_isresponder(i, bp2))
1332                         printf(" R");
1333                 else
1334                         printf(" ?");
1335         }
1336
1337         printf(" %s", ETYPESTR(base.etype));
1338         if (base.flags) {
1339                 printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
1340                         base.flags & ISAKMP_FLAG_C ? "C" : "");
1341         }
1342
1343         if (vflag) {
1344                 const struct isakmp_gen *ext;
1345                 int nparen;
1346
1347 #define CHECKLEN(p, np) \
1348                 if (ep < (u_char *)(p)) {                               \
1349                         printf(" [|%s]", NPSTR(np));                    \
1350                         goto done;                                      \
1351                 }
1352
1353                 printf(":");
1354
1355                 /* regardless of phase... */
1356                 if (base.flags & ISAKMP_FLAG_E) {
1357                         /*
1358                          * encrypted, nothing we can do right now.
1359                          * we hope to decrypt the packet in the future...
1360                          */
1361                         printf(" [encrypted %s]", NPSTR(base.np));
1362                         goto done;
1363                 }
1364
1365                 nparen = 0;
1366                 CHECKLEN(p + 1, base.np)
1367
1368                 np = base.np;
1369                 ext = (struct isakmp_gen *)(p + 1);
1370                 isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
1371         }
1372
1373 done:
1374         if (vflag) {
1375                 if (ntohl(base.len) != length) {
1376                         printf(" (len mismatch: isakmp %u/ip %u)",
1377                                 (u_int32_t)ntohl(base.len), length);
1378                 }
1379         }
1380 }