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