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