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