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