Remove old versions of tcpdump.
[dragonfly.git] / contrib / tcpdump-3.9 / 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.51 2005/04/07 00:28:17 mcr 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,
419                 u_int item_len _U_,
420                 const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
421                 u_int32_t proto0, int depth)
422 {
423         const struct isakmp_pl_sa *p;
424         struct isakmp_pl_sa sa;
425         const u_int32_t *q;
426         u_int32_t doi, sit, ident;
427         const u_char *cp, *np;
428         int t;
429
430         printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
431
432         p = (struct isakmp_pl_sa *)ext;
433         TCHECK(*p);
434         safememcpy(&sa, ext, sizeof(sa));
435         doi = ntohl(sa.doi);
436         sit = ntohl(sa.sit);
437         if (doi != 1) {
438                 printf(" doi=%d", doi);
439                 printf(" situation=%u", (u_int32_t)ntohl(sa.sit));
440                 return (u_char *)(p + 1);
441         }
442
443         printf(" doi=ipsec");
444         q = (u_int32_t *)&sa.sit;
445         printf(" situation=");
446         t = 0;
447         if (sit & 0x01) {
448                 printf("identity");
449                 t++;
450         }
451         if (sit & 0x02) {
452                 printf("%ssecrecy", t ? "+" : "");
453                 t++;
454         }
455         if (sit & 0x04)
456                 printf("%sintegrity", t ? "+" : "");
457
458         np = (u_char *)ext + sizeof(sa);
459         if (sit != 0x01) {
460                 TCHECK2(*(ext + 1), sizeof(ident));
461                 safememcpy(&ident, ext + 1, sizeof(ident));
462                 printf(" ident=%u", (u_int32_t)ntohl(ident));
463                 np += sizeof(ident);
464         }
465
466         ext = (struct isakmp_gen *)np;
467         TCHECK(*ext);
468
469         cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
470                 depth);
471
472         return cp;
473 trunc:
474         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
475         return NULL;
476 }
477
478 static const u_char *
479 isakmp_p_print(const struct isakmp_gen *ext, u_int item_len _U_,
480                const u_char *ep, u_int32_t phase, u_int32_t doi0,
481                u_int32_t proto0 _U_, int depth)
482 {
483         const struct isakmp_pl_p *p;
484         struct isakmp_pl_p prop;
485         const u_char *cp;
486
487         printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
488
489         p = (struct isakmp_pl_p *)ext;
490         TCHECK(*p);
491         safememcpy(&prop, ext, sizeof(prop));
492         printf(" #%d protoid=%s transform=%d",
493                 prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
494         if (prop.spi_size) {
495                 printf(" spi=");
496                 if (!rawprint((caddr_t)(p + 1), prop.spi_size))
497                         goto trunc;
498         }
499
500         ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
501         TCHECK(*ext);
502
503         cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
504                 prop.prot_id, depth);
505
506         return cp;
507 trunc:
508         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
509         return NULL;
510 }
511
512 static const char *isakmp_p_map[] = {
513         NULL, "ike",
514 };
515
516 static const char *ah_p_map[] = {
517         NULL, "(reserved)", "md5", "sha", "1des",
518         "sha2-256", "sha2-384", "sha2-512",
519 };
520
521 static const char *esp_p_map[] = {
522         NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
523         "blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
524 };
525
526 static const char *ipcomp_p_map[] = {
527         NULL, "oui", "deflate", "lzs",
528 };
529
530 const struct attrmap ipsec_t_map[] = {
531         { NULL, 0, { NULL } },
532         { "lifetype", 3, { NULL, "sec", "kb", }, },
533         { "life", 0, { NULL } },
534         { "group desc", 5,      { NULL, "modp768", "modp1024", "EC2N 2^155",
535                                   "EC2N 2^185", }, },
536         { "enc mode", 3, { NULL, "tunnel", "transport", }, },
537         { "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
538         { "keylen", 0, { NULL } },
539         { "rounds", 0, { NULL } },
540         { "dictsize", 0, { NULL } },
541         { "privalg", 0, { NULL } },
542 };
543
544 const struct attrmap oakley_t_map[] = {
545         { NULL, 0, { NULL } },
546         { "enc", 8,     { NULL, "1des", "idea", "blowfish", "rc5",
547                           "3des", "cast", "aes", }, },
548         { "hash", 7,    { NULL, "md5", "sha1", "tiger",
549                           "sha2-256", "sha2-384", "sha2-512", }, },
550         { "auth", 6,    { NULL, "preshared", "dss", "rsa sig", "rsa enc",
551                           "rsa enc revised", }, },
552         { "group desc", 5,      { NULL, "modp768", "modp1024", "EC2N 2^155",
553                                   "EC2N 2^185", }, },
554         { "group type", 4,      { NULL, "MODP", "ECP", "EC2N", }, },
555         { "group prime", 0, { NULL } },
556         { "group gen1", 0, { NULL } },
557         { "group gen2", 0, { NULL } },
558         { "group curve A", 0, { NULL } },
559         { "group curve B", 0, { NULL } },
560         { "lifetype", 3,        { NULL, "sec", "kb", }, },
561         { "lifeduration", 0, { NULL } },
562         { "prf", 0, { NULL } },
563         { "keylen", 0, { NULL } },
564         { "field", 0, { NULL } },
565         { "order", 0, { NULL } },
566 };
567
568 static const u_char *
569 isakmp_t_print(const struct isakmp_gen *ext, u_int item_len,
570         const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
571         u_int32_t proto, int depth _U_)
572 {
573         const struct isakmp_pl_t *p;
574         struct isakmp_pl_t t;
575         const u_char *cp;
576         const char *idstr;
577         const struct attrmap *map;
578         size_t nmap;
579         const u_char *ep2;
580
581         printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
582
583         p = (struct isakmp_pl_t *)ext;
584         TCHECK(*p);
585         safememcpy(&t, ext, sizeof(t));
586
587         switch (proto) {
588         case 1:
589                 idstr = STR_OR_ID(t.t_id, isakmp_p_map);
590                 map = oakley_t_map;
591                 nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
592                 break;
593         case 2:
594                 idstr = STR_OR_ID(t.t_id, ah_p_map);
595                 map = ipsec_t_map;
596                 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
597                 break;
598         case 3:
599                 idstr = STR_OR_ID(t.t_id, esp_p_map);
600                 map = ipsec_t_map;
601                 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
602                 break;
603         case 4:
604                 idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
605                 map = ipsec_t_map;
606                 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
607                 break;
608         default:
609                 idstr = NULL;
610                 map = NULL;
611                 nmap = 0;
612                 break;
613         }
614
615         if (idstr)
616                 printf(" #%d id=%s ", t.t_no, idstr);
617         else
618                 printf(" #%d id=%d ", t.t_no, t.t_id);
619         cp = (u_char *)(p + 1);
620         ep2 = (u_char *)p + item_len;
621         while (cp < ep && cp < ep2) {
622                 if (map && nmap) {
623                         cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
624                                 map, nmap);
625                 } else
626                         cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
627         }
628         if (ep < ep2)
629                 printf("...");
630         return cp;
631 trunc:
632         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
633         return NULL;
634 }
635
636 static const u_char *
637 isakmp_ke_print(const struct isakmp_gen *ext, u_int item_len _U_,
638                 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
639                 u_int32_t proto _U_, int depth _U_)
640 {
641         struct isakmp_gen e;
642
643         printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
644
645         TCHECK(*ext);
646         safememcpy(&e, ext, sizeof(e));
647         printf(" key len=%d", ntohs(e.len) - 4);
648         if (2 < vflag && 4 < ntohs(e.len)) {
649                 printf(" ");
650                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
651                         goto trunc;
652         }
653         return (u_char *)ext + ntohs(e.len);
654 trunc:
655         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
656         return NULL;
657 }
658
659 static const u_char *
660 isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
661                 const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
662                 u_int32_t proto _U_, int depth _U_)
663 {
664 #define USE_IPSECDOI_IN_PHASE1  1
665         const struct isakmp_pl_id *p;
666         struct isakmp_pl_id id;
667         static const char *idtypestr[] = {
668                 "IPv4", "IPv4net", "IPv6", "IPv6net",
669         };
670         static const char *ipsecidtypestr[] = {
671                 NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
672                 "IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
673                 "keyid",
674         };
675         int len;
676         const u_char *data;
677
678         printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
679
680         p = (struct isakmp_pl_id *)ext;
681         TCHECK(*p);
682         safememcpy(&id, ext, sizeof(id));
683         if (sizeof(*p) < item_len) {
684                 data = (u_char *)(p + 1);
685                 len = item_len - sizeof(*p);
686         } else {
687                 data = NULL;
688                 len = 0;
689         }
690
691 #if 0 /*debug*/
692         printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
693 #endif
694         switch (phase) {
695 #ifndef USE_IPSECDOI_IN_PHASE1
696         case 1:
697 #endif
698         default:
699                 printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr));
700                 printf(" doi_data=%u",
701                         (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff));
702                 break;
703
704 #ifdef USE_IPSECDOI_IN_PHASE1
705         case 1:
706 #endif
707         case 2:
708             {
709                 const struct ipsecdoi_id *p;
710                 struct ipsecdoi_id id;
711                 struct protoent *pe;
712
713                 p = (struct ipsecdoi_id *)ext;
714                 TCHECK(*p);
715                 safememcpy(&id, ext, sizeof(id));
716                 printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
717                 if (id.proto_id) {
718 #ifndef WIN32
719                         setprotoent(1);
720 #endif /* WIN32 */
721                         pe = getprotobynumber(id.proto_id);
722                         if (pe)
723                                 printf(" protoid=%s", pe->p_name);
724 #ifndef WIN32
725                         endprotoent();
726 #endif /* WIN32 */
727                 } else {
728                         /* it DOES NOT mean IPPROTO_IP! */
729                         printf(" protoid=%s", "0");
730                 }
731                 printf(" port=%d", ntohs(id.port));
732                 if (!len)
733                         break;
734                 if (data == NULL)
735                         goto trunc;
736                 TCHECK2(*data, len);
737                 switch (id.type) {
738                 case IPSECDOI_ID_IPV4_ADDR:
739                         if (len < 4)
740                                 printf(" len=%d [bad: < 4]", len);
741                         else
742                                 printf(" len=%d %s", len, ipaddr_string(data));
743                         len = 0;
744                         break;
745                 case IPSECDOI_ID_FQDN:
746                 case IPSECDOI_ID_USER_FQDN:
747                     {
748                         int i;
749                         printf(" len=%d ", len);
750                         for (i = 0; i < len; i++)
751                                 safeputchar(data[i]);
752                         len = 0;
753                         break;
754                     }
755                 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
756                     {
757                         const u_char *mask;
758                         if (len < 8)
759                                 printf(" len=%d [bad: < 8]", len);
760                         else {
761                                 mask = data + sizeof(struct in_addr);
762                                 printf(" len=%d %s/%u.%u.%u.%u", len,
763                                         ipaddr_string(data),
764                                         mask[0], mask[1], mask[2], mask[3]);
765                         }
766                         len = 0;
767                         break;
768                     }
769 #ifdef INET6
770                 case IPSECDOI_ID_IPV6_ADDR:
771                         if (len < 16)
772                                 printf(" len=%d [bad: < 16]", len);
773                         else
774                                 printf(" len=%d %s", len, ip6addr_string(data));
775                         len = 0;
776                         break;
777                 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
778                     {
779                         const u_int32_t *mask;
780                         if (len < 20)
781                                 printf(" len=%d [bad: < 20]", len);
782                         else {
783                                 mask = (u_int32_t *)(data + sizeof(struct in6_addr));
784                                 /*XXX*/
785                                 printf(" len=%d %s/0x%08x%08x%08x%08x", len,
786                                         ip6addr_string(data),
787                                         mask[0], mask[1], mask[2], mask[3]);
788                         }
789                         len = 0;
790                         break;
791                     }
792 #endif /*INET6*/
793                 case IPSECDOI_ID_IPV4_ADDR_RANGE:
794                         if (len < 8)
795                                 printf(" len=%d [bad: < 8]", len);
796                         else {
797                                 printf(" len=%d %s-%s", len,
798                                         ipaddr_string(data),
799                                         ipaddr_string(data + sizeof(struct in_addr)));
800                         }
801                         len = 0;
802                         break;
803 #ifdef INET6
804                 case IPSECDOI_ID_IPV6_ADDR_RANGE:
805                         if (len < 32)
806                                 printf(" len=%d [bad: < 32]", len);
807                         else {
808                                 printf(" len=%d %s-%s", len,
809                                         ip6addr_string(data),
810                                         ip6addr_string(data + sizeof(struct in6_addr)));
811                         }
812                         len = 0;
813                         break;
814 #endif /*INET6*/
815                 case IPSECDOI_ID_DER_ASN1_DN:
816                 case IPSECDOI_ID_DER_ASN1_GN:
817                 case IPSECDOI_ID_KEY_ID:
818                         break;
819                 }
820                 break;
821             }
822         }
823         if (data && len) {
824                 printf(" len=%d", len);
825                 if (2 < vflag) {
826                         printf(" ");
827                         if (!rawprint((caddr_t)data, len))
828                                 goto trunc;
829                 }
830         }
831         return (u_char *)ext + item_len;
832 trunc:
833         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
834         return NULL;
835 }
836
837 static const u_char *
838 isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_,
839                   const u_char *ep _U_, u_int32_t phase _U_,
840                   u_int32_t doi0 _U_,
841                   u_int32_t proto0 _U_, int depth _U_)
842 {
843         const struct isakmp_pl_cert *p;
844         struct isakmp_pl_cert cert;
845         static const char *certstr[] = {
846                 "none", "pkcs7", "pgp", "dns",
847                 "x509sign", "x509ke", "kerberos", "crl",
848                 "arl", "spki", "x509attr",
849         };
850
851         printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
852
853         p = (struct isakmp_pl_cert *)ext;
854         TCHECK(*p);
855         safememcpy(&cert, ext, sizeof(cert));
856         printf(" len=%d", item_len - 4);
857         printf(" type=%s", STR_OR_ID((cert.encode), certstr));
858         if (2 < vflag && 4 < item_len) {
859                 printf(" ");
860                 if (!rawprint((caddr_t)(ext + 1), item_len - 4))
861                         goto trunc;
862         }
863         return (u_char *)ext + item_len;
864 trunc:
865         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
866         return NULL;
867 }
868
869 static const u_char *
870 isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_,
871                 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
872                 u_int32_t proto0 _U_, int depth _U_)
873 {
874         const struct isakmp_pl_cert *p;
875         struct isakmp_pl_cert cert;
876         static const char *certstr[] = {
877                 "none", "pkcs7", "pgp", "dns",
878                 "x509sign", "x509ke", "kerberos", "crl",
879                 "arl", "spki", "x509attr",
880         };
881
882         printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
883
884         p = (struct isakmp_pl_cert *)ext;
885         TCHECK(*p);
886         safememcpy(&cert, ext, sizeof(cert));
887         printf(" len=%d", item_len - 4);
888         printf(" type=%s", STR_OR_ID((cert.encode), certstr));
889         if (2 < vflag && 4 < item_len) {
890                 printf(" ");
891                 if (!rawprint((caddr_t)(ext + 1), item_len - 4))
892                         goto trunc;
893         }
894         return (u_char *)ext + item_len;
895 trunc:
896         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
897         return NULL;
898 }
899
900 static const u_char *
901 isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_,
902                   const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
903                   u_int32_t proto _U_, int depth _U_)
904 {
905         struct isakmp_gen e;
906
907         printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
908
909         TCHECK(*ext);
910         safememcpy(&e, ext, sizeof(e));
911         printf(" len=%d", ntohs(e.len) - 4);
912         if (2 < vflag && 4 < ntohs(e.len)) {
913                 printf(" ");
914                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
915                         goto trunc;
916         }
917         return (u_char *)ext + ntohs(e.len);
918 trunc:
919         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
920         return NULL;
921 }
922
923 static const u_char *
924 isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_,
925                  const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
926                  u_int32_t proto _U_, int depth _U_)
927 {
928         struct isakmp_gen e;
929
930         printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
931
932         TCHECK(*ext);
933         safememcpy(&e, ext, sizeof(e));
934         printf(" len=%d", ntohs(e.len) - 4);
935         if (2 < vflag && 4 < ntohs(e.len)) {
936                 printf(" ");
937                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
938                         goto trunc;
939         }
940         return (u_char *)ext + ntohs(e.len);
941 trunc:
942         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
943         return NULL;
944 }
945
946 static const u_char *
947 isakmp_nonce_print(const struct isakmp_gen *ext,
948                    u_int item_len _U_,
949                    const u_char *ep _U_,
950                    u_int32_t phase _U_, u_int32_t doi _U_,
951                    u_int32_t proto _U_, int depth _U_)
952 {
953         struct isakmp_gen e;
954
955         printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
956
957         TCHECK(*ext);
958         safememcpy(&e, ext, sizeof(e));
959         printf(" n len=%d", ntohs(e.len) - 4);
960         if (2 < vflag && 4 < ntohs(e.len)) {
961                 printf(" ");
962                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
963                         goto trunc;
964         }
965         return (u_char *)ext + ntohs(e.len);
966 trunc:
967         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
968         return NULL;
969 }
970
971 static const u_char *
972 isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
973         const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
974         u_int32_t proto0 _U_, int depth)
975 {
976         struct isakmp_pl_n *p, n;
977         const u_char *cp;
978         u_char *ep2;
979         u_int32_t doi;
980         u_int32_t proto;
981         static const char *notify_error_str[] = {
982                 NULL,                           "INVALID-PAYLOAD-TYPE",
983                 "DOI-NOT-SUPPORTED",            "SITUATION-NOT-SUPPORTED",
984                 "INVALID-COOKIE",               "INVALID-MAJOR-VERSION",
985                 "INVALID-MINOR-VERSION",        "INVALID-EXCHANGE-TYPE",
986                 "INVALID-FLAGS",                "INVALID-MESSAGE-ID",
987                 "INVALID-PROTOCOL-ID",          "INVALID-SPI",
988                 "INVALID-TRANSFORM-ID",         "ATTRIBUTES-NOT-SUPPORTED",
989                 "NO-PROPOSAL-CHOSEN",           "BAD-PROPOSAL-SYNTAX",
990                 "PAYLOAD-MALFORMED",            "INVALID-KEY-INFORMATION",
991                 "INVALID-ID-INFORMATION",       "INVALID-CERT-ENCODING",
992                 "INVALID-CERTIFICATE",          "CERT-TYPE-UNSUPPORTED",
993                 "INVALID-CERT-AUTHORITY",       "INVALID-HASH-INFORMATION",
994                 "AUTHENTICATION-FAILED",        "INVALID-SIGNATURE",
995                 "ADDRESS-NOTIFICATION",         "NOTIFY-SA-LIFETIME",
996                 "CERTIFICATE-UNAVAILABLE",      "UNSUPPORTED-EXCHANGE-TYPE",
997                 "UNEQUAL-PAYLOAD-LENGTHS",
998         };
999         static const char *ipsec_notify_error_str[] = {
1000                 "RESERVED",
1001         };
1002         static const char *notify_status_str[] = {
1003                 "CONNECTED",
1004         };
1005         static const char *ipsec_notify_status_str[] = {
1006                 "RESPONDER-LIFETIME",           "REPLAY-STATUS",
1007                 "INITIAL-CONTACT",
1008         };
1009 /* NOTE: these macro must be called with x in proper range */
1010
1011 /* 0 - 8191 */
1012 #define NOTIFY_ERROR_STR(x) \
1013         STR_OR_ID((x), notify_error_str)
1014
1015 /* 8192 - 16383 */
1016 #define IPSEC_NOTIFY_ERROR_STR(x) \
1017         STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1018
1019 /* 16384 - 24575 */
1020 #define NOTIFY_STATUS_STR(x) \
1021         STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1022
1023 /* 24576 - 32767 */
1024 #define IPSEC_NOTIFY_STATUS_STR(x) \
1025         STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1026
1027         printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
1028
1029         p = (struct isakmp_pl_n *)ext;
1030         TCHECK(*p);
1031         safememcpy(&n, ext, sizeof(n));
1032         doi = ntohl(n.doi);
1033         proto = n.prot_id;
1034         if (doi != 1) {
1035                 printf(" doi=%d", doi);
1036                 printf(" proto=%d", proto);
1037                 if (ntohs(n.type) < 8192)
1038                         printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1039                 else if (ntohs(n.type) < 16384)
1040                         printf(" type=%s", numstr(ntohs(n.type)));
1041                 else if (ntohs(n.type) < 24576)
1042                         printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1043                 else
1044                         printf(" type=%s", numstr(ntohs(n.type)));
1045                 if (n.spi_size) {
1046                         printf(" spi=");
1047                         if (!rawprint((caddr_t)(p + 1), n.spi_size))
1048                                 goto trunc;
1049                 }
1050                 return (u_char *)(p + 1) + n.spi_size;
1051         }
1052
1053         printf(" doi=ipsec");
1054         printf(" proto=%s", PROTOIDSTR(proto));
1055         if (ntohs(n.type) < 8192)
1056                 printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1057         else if (ntohs(n.type) < 16384)
1058                 printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type)));
1059         else if (ntohs(n.type) < 24576)
1060                 printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1061         else if (ntohs(n.type) < 32768)
1062                 printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type)));
1063         else
1064                 printf(" type=%s", numstr(ntohs(n.type)));
1065         if (n.spi_size) {
1066                 printf(" spi=");
1067                 if (!rawprint((caddr_t)(p + 1), n.spi_size))
1068                         goto trunc;
1069         }
1070
1071         cp = (u_char *)(p + 1) + n.spi_size;
1072         ep2 = (u_char *)p + item_len;
1073
1074         if (cp < ep) {
1075                 printf(" orig=(");
1076                 switch (ntohs(n.type)) {
1077                 case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
1078                     {
1079                         const struct attrmap *map = oakley_t_map;
1080                         size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1081                         while (cp < ep && cp < ep2) {
1082                                 cp = isakmp_attrmap_print(cp,
1083                                         (ep < ep2) ? ep : ep2, map, nmap);
1084                         }
1085                         break;
1086                     }
1087                 case IPSECDOI_NTYPE_REPLAY_STATUS:
1088                         printf("replay detection %sabled",
1089                                 (*(u_int32_t *)cp) ? "en" : "dis");
1090                         break;
1091                 case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
1092                         if (isakmp_sub_print(ISAKMP_NPTYPE_SA,
1093                             (struct isakmp_gen *)cp, ep, phase, doi, proto,
1094                             depth) == NULL)
1095                                 return NULL;
1096                         break;
1097                 default:
1098                         /* NULL is dummy */
1099                         isakmp_print(gndo, cp,
1100                                      item_len - sizeof(*p) - n.spi_size,
1101                                      NULL);
1102                 }
1103                 printf(")");
1104         }
1105         return (u_char *)ext + item_len;
1106 trunc:
1107         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
1108         return NULL;
1109 }
1110
1111 static const u_char *
1112 isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_,
1113                const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1114                u_int32_t proto0 _U_, int depth _U_)
1115 {
1116         const struct isakmp_pl_d *p;
1117         struct isakmp_pl_d d;
1118         const u_int8_t *q;
1119         u_int32_t doi;
1120         u_int32_t proto;
1121         int i;
1122
1123         printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
1124
1125         p = (struct isakmp_pl_d *)ext;
1126         TCHECK(*p);
1127         safememcpy(&d, ext, sizeof(d));
1128         doi = ntohl(d.doi);
1129         proto = d.prot_id;
1130         if (doi != 1) {
1131                 printf(" doi=%u", doi);
1132                 printf(" proto=%u", proto);
1133         } else {
1134                 printf(" doi=ipsec");
1135                 printf(" proto=%s", PROTOIDSTR(proto));
1136         }
1137         printf(" spilen=%u", d.spi_size);
1138         printf(" nspi=%u", ntohs(d.num_spi));
1139         printf(" spi=");
1140         q = (u_int8_t *)(p + 1);
1141         for (i = 0; i < ntohs(d.num_spi); i++) {
1142                 if (i != 0)
1143                         printf(",");
1144                 if (!rawprint((caddr_t)q, d.spi_size))
1145                         goto trunc;
1146                 q += d.spi_size;
1147         }
1148         return q;
1149 trunc:
1150         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
1151         return NULL;
1152 }
1153
1154 static const u_char *
1155 isakmp_vid_print(const struct isakmp_gen *ext,
1156                  u_int item_len _U_, const u_char *ep _U_,
1157                  u_int32_t phase _U_, u_int32_t doi _U_,
1158                  u_int32_t proto _U_, int depth _U_)
1159 {
1160         struct isakmp_gen e;
1161
1162         printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1163
1164         TCHECK(*ext);
1165         safememcpy(&e, ext, sizeof(e));
1166         printf(" len=%d", ntohs(e.len) - 4);
1167         if (2 < vflag && 4 < ntohs(e.len)) {
1168                 printf(" ");
1169                 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
1170                         goto trunc;
1171         }
1172         return (u_char *)ext + ntohs(e.len);
1173 trunc:
1174         printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
1175         return NULL;
1176 }
1177
1178 static const u_char *
1179 isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1180         u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1181 {
1182         const u_char *cp;
1183         struct isakmp_gen e;
1184         u_int item_len;
1185
1186         cp = (u_char *)ext;
1187         TCHECK(*ext);
1188         safememcpy(&e, ext, sizeof(e));
1189
1190         /*
1191          * Since we can't have a payload length of less than 4 bytes,
1192          * we need to bail out here if the generic header is nonsensical
1193          * or truncated, otherwise we could loop forever processing
1194          * zero-length items or otherwise misdissect the packet.
1195          */
1196         item_len = ntohs(e.len);
1197         if (item_len <= 4)
1198                 return NULL;
1199
1200         if (NPFUNC(np)) {
1201                 /*
1202                  * XXX - what if item_len is too short, or too long,
1203                  * for this payload type?
1204                  */
1205                 cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth);
1206         } else {
1207                 printf("%s", NPSTR(np));
1208                 cp += item_len;
1209         }
1210
1211         return cp;
1212 trunc:
1213         printf(" [|isakmp]");
1214         return NULL;
1215 }
1216
1217 static const u_char *
1218 isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1219         u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1220 {
1221         const u_char *cp;
1222         int i;
1223         struct isakmp_gen e;
1224
1225         cp = (const u_char *)ext;
1226
1227         while (np) {
1228                 TCHECK(*ext);
1229                 
1230                 safememcpy(&e, ext, sizeof(e));
1231
1232                 TCHECK2(*ext, ntohs(e.len));
1233
1234                 depth++;
1235                 printf("\n");
1236                 for (i = 0; i < depth; i++)
1237                         printf("    ");
1238                 printf("(");
1239                 cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth);
1240                 printf(")");
1241                 depth--;
1242
1243                 if (cp == NULL) {
1244                         /* Zero-length subitem */
1245                         return NULL;
1246                 }
1247
1248                 np = e.np;
1249                 ext = (struct isakmp_gen *)cp;
1250         }
1251         return cp;
1252 trunc:
1253         printf(" [|%s]", NPSTR(np));
1254         return NULL;
1255 }
1256
1257 static char *
1258 numstr(int x)
1259 {
1260         static char buf[20];
1261         snprintf(buf, sizeof(buf), "#%d", x);
1262         return buf;
1263 }
1264
1265 /*
1266  * some compiler tries to optimize memcpy(), using the alignment constraint
1267  * on the argument pointer type.  by using this function, we try to avoid the
1268  * optimization.
1269  */
1270 static void
1271 safememcpy(void *p, const void *q, size_t l)
1272 {
1273         memcpy(p, q, l);
1274 }
1275
1276 void
1277 isakmp_print(netdissect_options *ndo,
1278              const u_char *bp, u_int length,
1279              const u_char *bp2)
1280 {
1281         const struct isakmp *p;
1282         struct isakmp base;
1283         const u_char *ep;
1284         u_char np;
1285         int i;
1286         int phase;
1287         int major, minor;
1288
1289         p = (const struct isakmp *)bp;
1290         ep = ndo->ndo_snapend;
1291
1292         if ((struct isakmp *)ep < p + 1) {
1293                 printf("[|isakmp]");
1294                 return;
1295         }
1296
1297         safememcpy(&base, p, sizeof(base));
1298
1299         printf("isakmp");
1300         if (vflag) {
1301                 major = (base.vers & ISAKMP_VERS_MAJOR)
1302                                 >> ISAKMP_VERS_MAJOR_SHIFT;
1303                 minor = (base.vers & ISAKMP_VERS_MINOR)
1304                                 >> ISAKMP_VERS_MINOR_SHIFT;
1305                 printf(" %d.%d", major, minor);
1306         }
1307
1308         if (vflag) {
1309                 printf(" msgid ");
1310                 rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
1311         }
1312
1313         if (1 < vflag) {
1314                 printf(" cookie ");
1315                 rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
1316                 printf("->");
1317                 rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
1318         }
1319         printf(":");
1320
1321         phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
1322         if (phase == 1)
1323                 printf(" phase %d", phase);
1324         else
1325                 printf(" phase %d/others", phase);
1326
1327         i = cookie_find(&base.i_ck);
1328         if (i < 0) {
1329                 if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
1330                         /* the first packet */
1331                         printf(" I");
1332                         if (bp2)
1333                                 cookie_record(&base.i_ck, bp2);
1334                 } else
1335                         printf(" ?");
1336         } else {
1337                 if (bp2 && cookie_isinitiator(i, bp2))
1338                         printf(" I");
1339                 else if (bp2 && cookie_isresponder(i, bp2))
1340                         printf(" R");
1341                 else
1342                         printf(" ?");
1343         }
1344
1345         printf(" %s", ETYPESTR(base.etype));
1346         if (base.flags) {
1347                 printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
1348                         base.flags & ISAKMP_FLAG_C ? "C" : "");
1349         }
1350
1351         if (vflag) {
1352                 const struct isakmp_gen *ext;
1353                 int nparen;
1354
1355 #define CHECKLEN(p, np) \
1356                 if (ep < (u_char *)(p)) {                               \
1357                         printf(" [|%s]", NPSTR(np));                    \
1358                         goto done;                                      \
1359                 }
1360
1361                 printf(":");
1362
1363                 /* regardless of phase... */
1364                 if (base.flags & ISAKMP_FLAG_E) {
1365                         /*
1366                          * encrypted, nothing we can do right now.
1367                          * we hope to decrypt the packet in the future...
1368                          */
1369                         printf(" [encrypted %s]", NPSTR(base.np));
1370                         goto done;
1371                 }
1372
1373                 nparen = 0;
1374                 CHECKLEN(p + 1, base.np)
1375
1376                 np = base.np;
1377                 ext = (struct isakmp_gen *)(p + 1);
1378                 isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
1379         }
1380
1381 done:
1382         if (vflag) {
1383                 if (ntohl(base.len) != length) {
1384                         printf(" (len mismatch: isakmp %u/ip %u)",
1385                                 (u_int32_t)ntohl(base.len), length);
1386                 }
1387         }
1388 }
1389
1390 void
1391 isakmp_rfc3948_print(netdissect_options *ndo,
1392                      const u_char *bp, u_int length,
1393                      const u_char *bp2)
1394 {
1395         const u_char *ep;
1396         ep = ndo->ndo_snapend;
1397
1398         if(length == 1 && bp[0]==0xff) {
1399                 ND_PRINT((ndo, "isakmp-nat-keep-alive"));
1400                 return;
1401         }
1402
1403         if(length < 4) {
1404                 goto trunc;
1405         }
1406
1407         /*
1408          * see if this is an IKE packet
1409          */
1410         if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
1411                 ND_PRINT((ndo, "NONESP-encap: "));
1412                 isakmp_print(ndo, bp+4, length-4, bp2);
1413                 return;
1414         }
1415
1416         /* must be an ESP packet */
1417         {
1418                 int nh, enh, padlen;
1419                 int advance;
1420
1421                 ND_PRINT((ndo, "UDP-encap: "));
1422
1423                 advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
1424                 if(advance <= 0)
1425                         return;
1426
1427                 bp += advance;
1428                 length -= advance + padlen;
1429                 nh = enh & 0xff;
1430              
1431                 ip_print_inner(ndo, bp, length, nh, bp2);
1432                 return;
1433         }
1434
1435 trunc:
1436         printf("[|isakmp]");
1437         return;
1438 }
1439
1440 /*
1441  * Local Variables:
1442  * c-style: whitesmith
1443  * c-basic-offset: 8
1444  * End:
1445  */
1446
1447
1448   
1449