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