Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / tcpdump / print-isakmp.c
blobd3d54a66798fda23cb06a0878814fb4fd3d4e10e
1 /* $NetBSD: print-isakmp.c,v 1.6 2007/07/24 11:53:44 drochner Exp $ */
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 #ifndef lint
35 #if 0
36 static const char rcsid[] _U_ =
37 "@(#) Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.51 2005/04/07 00:28:17 mcr Exp (LBL)";
38 #else
39 __RCSID("$NetBSD: print-isakmp.c,v 1.6 2007/07/24 11:53:44 drochner Exp $");
40 #endif
41 #endif
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
47 #include <tcpdump-stdinc.h>
49 #include <string.h>
51 #include <stdio.h>
53 #include "isakmp.h"
54 #include "ipsec_doi.h"
55 #include "oakley.h"
56 #include "interface.h"
57 #include "addrtoname.h"
58 #include "extract.h" /* must come after interface.h */
60 #include "ip.h"
61 #ifdef INET6
62 #include "ip6.h"
63 #endif
65 #ifndef HAVE_SOCKADDR_STORAGE
66 #define sockaddr_storage sockaddr
67 #endif
69 static const u_char *isakmp_sa_print(const struct isakmp_gen *,
70 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
71 static const u_char *isakmp_p_print(const struct isakmp_gen *,
72 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
73 static const u_char *isakmp_t_print(const struct isakmp_gen *,
74 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
75 static const u_char *isakmp_ke_print(const struct isakmp_gen *,
76 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
77 static const u_char *isakmp_id_print(const struct isakmp_gen *,
78 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
79 static const u_char *isakmp_cert_print(const struct isakmp_gen *,
80 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
81 static const u_char *isakmp_cr_print(const struct isakmp_gen *,
82 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
83 static const u_char *isakmp_sig_print(const struct isakmp_gen *,
84 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
85 static const u_char *isakmp_hash_print(const struct isakmp_gen *,
86 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
87 static const u_char *isakmp_nonce_print(const struct isakmp_gen *,
88 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
89 static const u_char *isakmp_n_print(const struct isakmp_gen *,
90 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
91 static const u_char *isakmp_d_print(const struct isakmp_gen *,
92 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
93 static const u_char *isakmp_vid_print(const struct isakmp_gen *,
94 u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
95 static const u_char *isakmp_sub0_print(u_char, const struct isakmp_gen *,
96 const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
97 static const u_char *isakmp_sub_print(u_char, const struct isakmp_gen *,
98 const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
99 static char *numstr(int);
100 static void safememcpy(void *, const void *, size_t);
102 #define MAXINITIATORS 20
103 int ninitiator = 0;
104 struct {
105 cookie_t initiator;
106 struct sockaddr_storage iaddr;
107 struct sockaddr_storage raddr;
108 } cookiecache[MAXINITIATORS];
110 /* protocol id */
111 static const char *protoidstr[] = {
112 NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
115 /* isakmp->np */
116 static const char *npstr[] = {
117 "none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash",
118 "sig", "nonce", "n", "d", "vid"
121 /* isakmp->np */
122 static const u_char *(*npfunc[])(const struct isakmp_gen *, u_int,
123 const u_char *, u_int32_t, u_int32_t, u_int32_t, int) = {
124 NULL,
125 isakmp_sa_print,
126 isakmp_p_print,
127 isakmp_t_print,
128 isakmp_ke_print,
129 isakmp_id_print,
130 isakmp_cert_print,
131 isakmp_cr_print,
132 isakmp_hash_print,
133 isakmp_sig_print,
134 isakmp_nonce_print,
135 isakmp_n_print,
136 isakmp_d_print,
137 isakmp_vid_print,
140 /* isakmp->etype */
141 static const char *etypestr[] = {
142 "none", "base", "ident", "auth", "agg", "inf", NULL, NULL,
143 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
144 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
145 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
146 "oakley-quick", "oakley-newgroup",
149 #define STR_OR_ID(x, tab) \
150 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
151 #define PROTOIDSTR(x) STR_OR_ID(x, protoidstr)
152 #define NPSTR(x) STR_OR_ID(x, npstr)
153 #define ETYPESTR(x) STR_OR_ID(x, etypestr)
155 #define NPFUNC(x) \
156 (((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
157 ? npfunc[(x)] : NULL)
159 static int
160 iszero(u_char *p, size_t l)
162 while (l--) {
163 if (*p++)
164 return 0;
166 return 1;
169 /* find cookie from initiator cache */
170 static int
171 cookie_find(cookie_t *in)
173 int i;
175 for (i = 0; i < MAXINITIATORS; i++) {
176 if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
177 return i;
180 return -1;
183 /* record initiator */
184 static void
185 cookie_record(cookie_t *in, const u_char *bp2)
187 int i;
188 struct ip *ip;
189 struct sockaddr_in *sin;
190 #ifdef INET6
191 struct ip6_hdr *ip6;
192 struct sockaddr_in6 *sin6;
193 #endif
195 i = cookie_find(in);
196 if (0 <= i) {
197 ninitiator = (i + 1) % MAXINITIATORS;
198 return;
201 ip = (struct ip *)bp2;
202 switch (IP_V(ip)) {
203 case 4:
204 memset(&cookiecache[ninitiator].iaddr, 0,
205 sizeof(cookiecache[ninitiator].iaddr));
206 memset(&cookiecache[ninitiator].raddr, 0,
207 sizeof(cookiecache[ninitiator].raddr));
209 sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr;
210 #ifdef HAVE_SOCKADDR_SA_LEN
211 sin->sin_len = sizeof(struct sockaddr_in);
212 #endif
213 sin->sin_family = AF_INET;
214 memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
215 sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr;
216 #ifdef HAVE_SOCKADDR_SA_LEN
217 sin->sin_len = sizeof(struct sockaddr_in);
218 #endif
219 sin->sin_family = AF_INET;
220 memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
221 break;
222 #ifdef INET6
223 case 6:
224 memset(&cookiecache[ninitiator].iaddr, 0,
225 sizeof(cookiecache[ninitiator].iaddr));
226 memset(&cookiecache[ninitiator].raddr, 0,
227 sizeof(cookiecache[ninitiator].raddr));
229 ip6 = (struct ip6_hdr *)bp2;
230 sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr;
231 #ifdef HAVE_SOCKADDR_SA_LEN
232 sin6->sin6_len = sizeof(struct sockaddr_in6);
233 #endif
234 sin6->sin6_family = AF_INET6;
235 memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
236 sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr;
237 #ifdef HAVE_SOCKADDR_SA_LEN
238 sin6->sin6_len = sizeof(struct sockaddr_in6);
239 #endif
240 sin6->sin6_family = AF_INET6;
241 memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
242 break;
243 #endif
244 default:
245 return;
247 memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in));
248 ninitiator = (ninitiator + 1) % MAXINITIATORS;
251 #define cookie_isinitiator(x, y) cookie_sidecheck((x), (y), 1)
252 #define cookie_isresponder(x, y) cookie_sidecheck((x), (y), 0)
253 static int
254 cookie_sidecheck(int i, const u_char *bp2, int initiator)
256 struct sockaddr_storage ss;
257 struct sockaddr *sa;
258 struct ip *ip;
259 struct sockaddr_in *sin;
260 #ifdef INET6
261 struct ip6_hdr *ip6;
262 struct sockaddr_in6 *sin6;
263 #endif
264 int salen;
266 memset(&ss, 0, sizeof(ss));
267 ip = (struct ip *)bp2;
268 switch (IP_V(ip)) {
269 case 4:
270 sin = (struct sockaddr_in *)&ss;
271 #ifdef HAVE_SOCKADDR_SA_LEN
272 sin->sin_len = sizeof(struct sockaddr_in);
273 #endif
274 sin->sin_family = AF_INET;
275 memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
276 break;
277 #ifdef INET6
278 case 6:
279 ip6 = (struct ip6_hdr *)bp2;
280 sin6 = (struct sockaddr_in6 *)&ss;
281 #ifdef HAVE_SOCKADDR_SA_LEN
282 sin6->sin6_len = sizeof(struct sockaddr_in6);
283 #endif
284 sin6->sin6_family = AF_INET6;
285 memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
286 break;
287 #endif
288 default:
289 return 0;
292 sa = (struct sockaddr *)&ss;
293 if (initiator) {
294 if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].iaddr)->sa_family)
295 return 0;
296 #ifdef HAVE_SOCKADDR_SA_LEN
297 salen = sa->sa_len;
298 #else
299 #ifdef INET6
300 if (sa->sa_family == AF_INET6)
301 salen = sizeof(struct sockaddr_in6);
302 else
303 salen = sizeof(struct sockaddr);
304 #else
305 salen = sizeof(struct sockaddr);
306 #endif
307 #endif
308 if (memcmp(&ss, &cookiecache[i].iaddr, salen) == 0)
309 return 1;
310 } else {
311 if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].raddr)->sa_family)
312 return 0;
313 #ifdef HAVE_SOCKADDR_SA_LEN
314 salen = sa->sa_len;
315 #else
316 #ifdef INET6
317 if (sa->sa_family == AF_INET6)
318 salen = sizeof(struct sockaddr_in6);
319 else
320 salen = sizeof(struct sockaddr);
321 #else
322 salen = sizeof(struct sockaddr);
323 #endif
324 #endif
325 if (memcmp(&ss, &cookiecache[i].raddr, salen) == 0)
326 return 1;
328 return 0;
331 static int
332 rawprint(caddr_t loc, size_t len)
334 static u_char *p;
335 size_t i;
337 TCHECK2(*loc, len);
339 p = (u_char *)loc;
340 for (i = 0; i < len; i++)
341 printf("%02x", p[i] & 0xff);
342 return 1;
343 trunc:
344 return 0;
347 struct attrmap {
348 const char *type;
349 u_int nvalue;
350 const char *value[30]; /*XXX*/
353 static const u_char *
354 isakmp_attrmap_print(const u_char *p, const u_char *ep,
355 const struct attrmap *map, size_t nmap)
357 u_int16_t *q;
358 int totlen;
359 u_int32_t t, v;
361 q = (u_int16_t *)p;
362 if (p[0] & 0x80)
363 totlen = 4;
364 else
365 totlen = 4 + EXTRACT_16BITS(&q[1]);
366 if (ep < p + totlen) {
367 printf("[|attr]");
368 return ep + 1;
371 printf("(");
372 t = EXTRACT_16BITS(&q[0]) & 0x7fff;
373 if (map && t < nmap && map[t].type)
374 printf("type=%s ", map[t].type);
375 else
376 printf("type=#%d ", t);
377 if (p[0] & 0x80) {
378 printf("value=");
379 v = EXTRACT_16BITS(&q[1]);
380 if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
381 printf("%s", map[t].value[v]);
382 else
383 rawprint((caddr_t)&q[1], 2);
384 } else {
385 printf("len=%d value=", EXTRACT_16BITS(&q[1]));
386 rawprint((caddr_t)&p[4], EXTRACT_16BITS(&q[1]));
388 printf(")");
389 return p + totlen;
392 static const u_char *
393 isakmp_attr_print(const u_char *p, const u_char *ep)
395 u_int16_t *q;
396 int totlen;
397 u_int32_t t;
399 q = (u_int16_t *)p;
400 if (p[0] & 0x80)
401 totlen = 4;
402 else
403 totlen = 4 + EXTRACT_16BITS(&q[1]);
404 if (ep < p + totlen) {
405 printf("[|attr]");
406 return ep + 1;
409 printf("(");
410 t = EXTRACT_16BITS(&q[0]) & 0x7fff;
411 printf("type=#%d ", t);
412 if (p[0] & 0x80) {
413 printf("value=");
414 t = q[1];
415 rawprint((caddr_t)&q[1], 2);
416 } else {
417 printf("len=%d value=", EXTRACT_16BITS(&q[1]));
418 rawprint((caddr_t)&p[2], EXTRACT_16BITS(&q[1]));
420 printf(")");
421 return p + totlen;
424 static const u_char *
425 isakmp_sa_print(const struct isakmp_gen *ext,
426 u_int item_len _U_,
427 const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
428 u_int32_t proto0, int depth)
430 const struct isakmp_pl_sa *p;
431 struct isakmp_pl_sa sa;
432 const u_int32_t *q;
433 u_int32_t doi, sit, ident;
434 const u_char *cp, *np;
435 int t;
437 printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
439 p = (struct isakmp_pl_sa *)ext;
440 TCHECK(*p);
441 safememcpy(&sa, ext, sizeof(sa));
442 doi = ntohl(sa.doi);
443 sit = ntohl(sa.sit);
444 if (doi != 1) {
445 printf(" doi=%d", doi);
446 printf(" situation=%u", (u_int32_t)ntohl(sa.sit));
447 return (u_char *)(p + 1);
450 printf(" doi=ipsec");
451 q = (u_int32_t *)&sa.sit;
452 printf(" situation=");
453 t = 0;
454 if (sit & 0x01) {
455 printf("identity");
456 t++;
458 if (sit & 0x02) {
459 printf("%ssecrecy", t ? "+" : "");
460 t++;
462 if (sit & 0x04)
463 printf("%sintegrity", t ? "+" : "");
465 np = (u_char *)ext + sizeof(sa);
466 if (sit != 0x01) {
467 TCHECK2(*(ext + 1), sizeof(ident));
468 safememcpy(&ident, ext + 1, sizeof(ident));
469 printf(" ident=%u", (u_int32_t)ntohl(ident));
470 np += sizeof(ident);
473 ext = (struct isakmp_gen *)np;
474 TCHECK(*ext);
476 cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
477 depth);
479 return cp;
480 trunc:
481 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
482 return NULL;
485 static const u_char *
486 isakmp_p_print(const struct isakmp_gen *ext, u_int item_len _U_,
487 const u_char *ep, u_int32_t phase, u_int32_t doi0,
488 u_int32_t proto0 _U_, int depth)
490 const struct isakmp_pl_p *p;
491 struct isakmp_pl_p prop;
492 const u_char *cp;
494 printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
496 p = (struct isakmp_pl_p *)ext;
497 TCHECK(*p);
498 safememcpy(&prop, ext, sizeof(prop));
499 printf(" #%d protoid=%s transform=%d",
500 prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
501 if (prop.spi_size) {
502 printf(" spi=");
503 if (!rawprint((caddr_t)(p + 1), prop.spi_size))
504 goto trunc;
507 ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
508 TCHECK(*ext);
510 cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
511 prop.prot_id, depth);
513 return cp;
514 trunc:
515 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
516 return NULL;
519 static const char *isakmp_p_map[] = {
520 NULL, "ike",
523 static const char *ah_p_map[] = {
524 NULL, "(reserved)", "md5", "sha", "1des",
525 "sha2-256", "sha2-384", "sha2-512",
528 static const char *esp_p_map[] = {
529 NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
530 "blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
533 static const char *ipcomp_p_map[] = {
534 NULL, "oui", "deflate", "lzs",
537 const struct attrmap ipsec_t_map[] = {
538 { NULL, 0, { NULL } },
539 { "lifetype", 3, { NULL, "sec", "kb", }, },
540 { "life", 0, { NULL } },
541 { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155",
542 "EC2N 2^185", }, },
543 { "enc mode", 3, { NULL, "tunnel", "transport", }, },
544 { "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
545 { "keylen", 0, { NULL } },
546 { "rounds", 0, { NULL } },
547 { "dictsize", 0, { NULL } },
548 { "privalg", 0, { NULL } },
551 const struct attrmap oakley_t_map[] = {
552 { NULL, 0, { NULL } },
553 { "enc", 8, { NULL, "1des", "idea", "blowfish", "rc5",
554 "3des", "cast", "aes", }, },
555 { "hash", 7, { NULL, "md5", "sha1", "tiger",
556 "sha2-256", "sha2-384", "sha2-512", }, },
557 { "auth", 6, { NULL, "preshared", "dss", "rsa sig", "rsa enc",
558 "rsa enc revised", }, },
559 { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155",
560 "EC2N 2^185", }, },
561 { "group type", 4, { NULL, "MODP", "ECP", "EC2N", }, },
562 { "group prime", 0, { NULL } },
563 { "group gen1", 0, { NULL } },
564 { "group gen2", 0, { NULL } },
565 { "group curve A", 0, { NULL } },
566 { "group curve B", 0, { NULL } },
567 { "lifetype", 3, { NULL, "sec", "kb", }, },
568 { "lifeduration", 0, { NULL } },
569 { "prf", 0, { NULL } },
570 { "keylen", 0, { NULL } },
571 { "field", 0, { NULL } },
572 { "order", 0, { NULL } },
575 static const u_char *
576 isakmp_t_print(const struct isakmp_gen *ext, u_int item_len,
577 const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
578 u_int32_t proto, int depth _U_)
580 const struct isakmp_pl_t *p;
581 struct isakmp_pl_t t;
582 const u_char *cp;
583 const char *idstr;
584 const struct attrmap *map;
585 size_t nmap;
586 const u_char *ep2;
588 printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
590 p = (struct isakmp_pl_t *)ext;
591 TCHECK(*p);
592 safememcpy(&t, ext, sizeof(t));
594 switch (proto) {
595 case 1:
596 idstr = STR_OR_ID(t.t_id, isakmp_p_map);
597 map = oakley_t_map;
598 nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
599 break;
600 case 2:
601 idstr = STR_OR_ID(t.t_id, ah_p_map);
602 map = ipsec_t_map;
603 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
604 break;
605 case 3:
606 idstr = STR_OR_ID(t.t_id, esp_p_map);
607 map = ipsec_t_map;
608 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
609 break;
610 case 4:
611 idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
612 map = ipsec_t_map;
613 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
614 break;
615 default:
616 idstr = NULL;
617 map = NULL;
618 nmap = 0;
619 break;
622 if (idstr)
623 printf(" #%d id=%s ", t.t_no, idstr);
624 else
625 printf(" #%d id=%d ", t.t_no, t.t_id);
626 cp = (u_char *)(p + 1);
627 ep2 = (u_char *)p + item_len;
628 while (cp < ep && cp < ep2) {
629 if (map && nmap) {
630 cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
631 map, nmap);
632 } else
633 cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
635 if (ep < ep2)
636 printf("...");
637 return cp;
638 trunc:
639 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
640 return NULL;
643 static const u_char *
644 isakmp_ke_print(const struct isakmp_gen *ext, u_int item_len _U_,
645 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
646 u_int32_t proto _U_, int depth _U_)
648 struct isakmp_gen e;
650 printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
652 TCHECK(*ext);
653 safememcpy(&e, ext, sizeof(e));
654 printf(" key len=%d", ntohs(e.len) - 4);
655 if (2 < vflag && 4 < ntohs(e.len)) {
656 printf(" ");
657 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
658 goto trunc;
660 return (u_char *)ext + ntohs(e.len);
661 trunc:
662 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
663 return NULL;
666 static const u_char *
667 isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
668 const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
669 u_int32_t proto _U_, int depth _U_)
671 #define USE_IPSECDOI_IN_PHASE1 1
672 const struct isakmp_pl_id *p;
673 struct isakmp_pl_id id;
674 static const char *idtypestr[] = {
675 "IPv4", "IPv4net", "IPv6", "IPv6net",
677 static const char *ipsecidtypestr[] = {
678 NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
679 "IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
680 "keyid",
682 int len;
683 const u_char *data;
685 printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
687 p = (struct isakmp_pl_id *)ext;
688 TCHECK(*p);
689 safememcpy(&id, ext, sizeof(id));
690 if (sizeof(*p) < item_len) {
691 data = (u_char *)(p + 1);
692 len = item_len - sizeof(*p);
693 } else {
694 data = NULL;
695 len = 0;
698 #if 0 /*debug*/
699 printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
700 #endif
701 switch (phase) {
702 #ifndef USE_IPSECDOI_IN_PHASE1
703 case 1:
704 #endif
705 default:
706 printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr));
707 printf(" doi_data=%u",
708 (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff));
709 break;
711 #ifdef USE_IPSECDOI_IN_PHASE1
712 case 1:
713 #endif
714 case 2:
716 const struct ipsecdoi_id *p;
717 struct ipsecdoi_id id;
718 struct protoent *pe;
720 p = (struct ipsecdoi_id *)ext;
721 TCHECK(*p);
722 safememcpy(&id, ext, sizeof(id));
723 printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
724 if (id.proto_id) {
725 #ifndef WIN32
726 setprotoent(1);
727 #endif /* WIN32 */
728 pe = getprotobynumber(id.proto_id);
729 if (pe)
730 printf(" protoid=%s", pe->p_name);
731 #ifndef WIN32
732 endprotoent();
733 #endif /* WIN32 */
734 } else {
735 /* it DOES NOT mean IPPROTO_IP! */
736 printf(" protoid=%s", "0");
738 printf(" port=%d", ntohs(id.port));
739 if (!len)
740 break;
741 if (data == NULL)
742 goto trunc;
743 TCHECK2(*data, len);
744 switch (id.type) {
745 case IPSECDOI_ID_IPV4_ADDR:
746 if (len < 4)
747 printf(" len=%d [bad: < 4]", len);
748 else
749 printf(" len=%d %s", len, ipaddr_string(data));
750 len = 0;
751 break;
752 case IPSECDOI_ID_FQDN:
753 case IPSECDOI_ID_USER_FQDN:
755 int i;
756 printf(" len=%d ", len);
757 for (i = 0; i < len; i++)
758 safeputchar(data[i]);
759 len = 0;
760 break;
762 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
764 const u_char *mask;
765 if (len < 8)
766 printf(" len=%d [bad: < 8]", len);
767 else {
768 mask = data + sizeof(struct in_addr);
769 printf(" len=%d %s/%u.%u.%u.%u", len,
770 ipaddr_string(data),
771 mask[0], mask[1], mask[2], mask[3]);
773 len = 0;
774 break;
776 #ifdef INET6
777 case IPSECDOI_ID_IPV6_ADDR:
778 if (len < 16)
779 printf(" len=%d [bad: < 16]", len);
780 else
781 printf(" len=%d %s", len, ip6addr_string(data));
782 len = 0;
783 break;
784 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
786 const u_int32_t *mask;
787 if (len < 20)
788 printf(" len=%d [bad: < 20]", len);
789 else {
790 mask = (u_int32_t *)(data + sizeof(struct in6_addr));
791 /*XXX*/
792 printf(" len=%d %s/0x%08x%08x%08x%08x", len,
793 ip6addr_string(data),
794 mask[0], mask[1], mask[2], mask[3]);
796 len = 0;
797 break;
799 #endif /*INET6*/
800 case IPSECDOI_ID_IPV4_ADDR_RANGE:
801 if (len < 8)
802 printf(" len=%d [bad: < 8]", len);
803 else {
804 printf(" len=%d %s-%s", len,
805 ipaddr_string(data),
806 ipaddr_string(data + sizeof(struct in_addr)));
808 len = 0;
809 break;
810 #ifdef INET6
811 case IPSECDOI_ID_IPV6_ADDR_RANGE:
812 if (len < 32)
813 printf(" len=%d [bad: < 32]", len);
814 else {
815 printf(" len=%d %s-%s", len,
816 ip6addr_string(data),
817 ip6addr_string(data + sizeof(struct in6_addr)));
819 len = 0;
820 break;
821 #endif /*INET6*/
822 case IPSECDOI_ID_DER_ASN1_DN:
823 case IPSECDOI_ID_DER_ASN1_GN:
824 case IPSECDOI_ID_KEY_ID:
825 break;
827 break;
830 if (data && len) {
831 printf(" len=%d", len);
832 if (2 < vflag) {
833 printf(" ");
834 if (!rawprint((caddr_t)data, len))
835 goto trunc;
838 return (u_char *)ext + item_len;
839 trunc:
840 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
841 return NULL;
844 static const u_char *
845 isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_,
846 const u_char *ep _U_, u_int32_t phase _U_,
847 u_int32_t doi0 _U_,
848 u_int32_t proto0 _U_, int depth _U_)
850 const struct isakmp_pl_cert *p;
851 struct isakmp_pl_cert cert;
852 static const char *certstr[] = {
853 "none", "pkcs7", "pgp", "dns",
854 "x509sign", "x509ke", "kerberos", "crl",
855 "arl", "spki", "x509attr",
858 printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
860 p = (struct isakmp_pl_cert *)ext;
861 TCHECK(*p);
862 safememcpy(&cert, ext, sizeof(cert));
863 printf(" len=%d", item_len - 4);
864 printf(" type=%s", STR_OR_ID((cert.encode), certstr));
865 if (2 < vflag && 4 < item_len) {
866 printf(" ");
867 if (!rawprint((caddr_t)(ext + 1), item_len - 4))
868 goto trunc;
870 return (u_char *)ext + item_len;
871 trunc:
872 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
873 return NULL;
876 static const u_char *
877 isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_,
878 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
879 u_int32_t proto0 _U_, int depth _U_)
881 const struct isakmp_pl_cert *p;
882 struct isakmp_pl_cert cert;
883 static const char *certstr[] = {
884 "none", "pkcs7", "pgp", "dns",
885 "x509sign", "x509ke", "kerberos", "crl",
886 "arl", "spki", "x509attr",
889 printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
891 p = (struct isakmp_pl_cert *)ext;
892 TCHECK(*p);
893 safememcpy(&cert, ext, sizeof(cert));
894 printf(" len=%d", item_len - 4);
895 printf(" type=%s", STR_OR_ID((cert.encode), certstr));
896 if (2 < vflag && 4 < item_len) {
897 printf(" ");
898 if (!rawprint((caddr_t)(ext + 1), item_len - 4))
899 goto trunc;
901 return (u_char *)ext + item_len;
902 trunc:
903 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
904 return NULL;
907 static const u_char *
908 isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_,
909 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
910 u_int32_t proto _U_, int depth _U_)
912 struct isakmp_gen e;
914 printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
916 TCHECK(*ext);
917 safememcpy(&e, ext, sizeof(e));
918 printf(" len=%d", ntohs(e.len) - 4);
919 if (2 < vflag && 4 < ntohs(e.len)) {
920 printf(" ");
921 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
922 goto trunc;
924 return (u_char *)ext + ntohs(e.len);
925 trunc:
926 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
927 return NULL;
930 static const u_char *
931 isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_,
932 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
933 u_int32_t proto _U_, int depth _U_)
935 struct isakmp_gen e;
937 printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
939 TCHECK(*ext);
940 safememcpy(&e, ext, sizeof(e));
941 printf(" len=%d", ntohs(e.len) - 4);
942 if (2 < vflag && 4 < ntohs(e.len)) {
943 printf(" ");
944 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
945 goto trunc;
947 return (u_char *)ext + ntohs(e.len);
948 trunc:
949 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
950 return NULL;
953 static const u_char *
954 isakmp_nonce_print(const struct isakmp_gen *ext,
955 u_int item_len _U_,
956 const u_char *ep _U_,
957 u_int32_t phase _U_, u_int32_t doi _U_,
958 u_int32_t proto _U_, int depth _U_)
960 struct isakmp_gen e;
962 printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
964 TCHECK(*ext);
965 safememcpy(&e, ext, sizeof(e));
966 printf(" n len=%d", ntohs(e.len) - 4);
967 if (2 < vflag && 4 < ntohs(e.len)) {
968 printf(" ");
969 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
970 goto trunc;
972 return (u_char *)ext + ntohs(e.len);
973 trunc:
974 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
975 return NULL;
978 static const u_char *
979 isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
980 const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
981 u_int32_t proto0 _U_, int depth)
983 struct isakmp_pl_n *p, n;
984 const u_char *cp;
985 u_char *ep2;
986 u_int32_t doi;
987 u_int32_t proto;
988 static const char *notify_error_str[] = {
989 NULL, "INVALID-PAYLOAD-TYPE",
990 "DOI-NOT-SUPPORTED", "SITUATION-NOT-SUPPORTED",
991 "INVALID-COOKIE", "INVALID-MAJOR-VERSION",
992 "INVALID-MINOR-VERSION", "INVALID-EXCHANGE-TYPE",
993 "INVALID-FLAGS", "INVALID-MESSAGE-ID",
994 "INVALID-PROTOCOL-ID", "INVALID-SPI",
995 "INVALID-TRANSFORM-ID", "ATTRIBUTES-NOT-SUPPORTED",
996 "NO-PROPOSAL-CHOSEN", "BAD-PROPOSAL-SYNTAX",
997 "PAYLOAD-MALFORMED", "INVALID-KEY-INFORMATION",
998 "INVALID-ID-INFORMATION", "INVALID-CERT-ENCODING",
999 "INVALID-CERTIFICATE", "CERT-TYPE-UNSUPPORTED",
1000 "INVALID-CERT-AUTHORITY", "INVALID-HASH-INFORMATION",
1001 "AUTHENTICATION-FAILED", "INVALID-SIGNATURE",
1002 "ADDRESS-NOTIFICATION", "NOTIFY-SA-LIFETIME",
1003 "CERTIFICATE-UNAVAILABLE", "UNSUPPORTED-EXCHANGE-TYPE",
1004 "UNEQUAL-PAYLOAD-LENGTHS",
1006 static const char *ipsec_notify_error_str[] = {
1007 "RESERVED",
1009 static const char *notify_status_str[] = {
1010 "CONNECTED",
1012 static const char *ipsec_notify_status_str[] = {
1013 "RESPONDER-LIFETIME", "REPLAY-STATUS",
1014 "INITIAL-CONTACT",
1016 /* NOTE: these macro must be called with x in proper range */
1018 /* 0 - 8191 */
1019 #define NOTIFY_ERROR_STR(x) \
1020 STR_OR_ID((x), notify_error_str)
1022 /* 8192 - 16383 */
1023 #define IPSEC_NOTIFY_ERROR_STR(x) \
1024 STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1026 /* 16384 - 24575 */
1027 #define NOTIFY_STATUS_STR(x) \
1028 STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1030 /* 24576 - 32767 */
1031 #define IPSEC_NOTIFY_STATUS_STR(x) \
1032 STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1034 printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
1036 p = (struct isakmp_pl_n *)ext;
1037 TCHECK(*p);
1038 safememcpy(&n, ext, sizeof(n));
1039 doi = ntohl(n.doi);
1040 proto = n.prot_id;
1041 if (doi != 1) {
1042 printf(" doi=%d", doi);
1043 printf(" proto=%d", proto);
1044 if (ntohs(n.type) < 8192)
1045 printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1046 else if (ntohs(n.type) < 16384)
1047 printf(" type=%s", numstr(ntohs(n.type)));
1048 else if (ntohs(n.type) < 24576)
1049 printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1050 else
1051 printf(" type=%s", numstr(ntohs(n.type)));
1052 if (n.spi_size) {
1053 printf(" spi=");
1054 if (!rawprint((caddr_t)(p + 1), n.spi_size))
1055 goto trunc;
1057 return (u_char *)(p + 1) + n.spi_size;
1060 printf(" doi=ipsec");
1061 printf(" proto=%s", PROTOIDSTR(proto));
1062 if (ntohs(n.type) < 8192)
1063 printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1064 else if (ntohs(n.type) < 16384)
1065 printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type)));
1066 else if (ntohs(n.type) < 24576)
1067 printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1068 else if (ntohs(n.type) < 32768)
1069 printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type)));
1070 else
1071 printf(" type=%s", numstr(ntohs(n.type)));
1072 if (n.spi_size) {
1073 printf(" spi=");
1074 if (!rawprint((caddr_t)(p + 1), n.spi_size))
1075 goto trunc;
1078 cp = (u_char *)(p + 1) + n.spi_size;
1079 ep2 = (u_char *)p + item_len;
1081 if (cp < ep) {
1082 printf(" orig=(");
1083 switch (ntohs(n.type)) {
1084 case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
1086 const struct attrmap *map = oakley_t_map;
1087 size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1088 while (cp < ep && cp < ep2) {
1089 cp = isakmp_attrmap_print(cp,
1090 (ep < ep2) ? ep : ep2, map, nmap);
1092 break;
1094 case IPSECDOI_NTYPE_REPLAY_STATUS:
1095 printf("replay detection %sabled",
1096 (*(u_int32_t *)cp) ? "en" : "dis");
1097 break;
1098 case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
1099 if (isakmp_sub_print(ISAKMP_NPTYPE_SA,
1100 (struct isakmp_gen *)cp, ep, phase, doi, proto,
1101 depth) == NULL)
1102 return NULL;
1103 break;
1104 default:
1105 /* NULL is dummy */
1106 isakmp_print(gndo, cp,
1107 item_len - sizeof(*p) - n.spi_size,
1108 NULL);
1110 printf(")");
1112 return (u_char *)ext + item_len;
1113 trunc:
1114 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
1115 return NULL;
1118 static const u_char *
1119 isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_,
1120 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1121 u_int32_t proto0 _U_, int depth _U_)
1123 const struct isakmp_pl_d *p;
1124 struct isakmp_pl_d d;
1125 const u_int8_t *q;
1126 u_int32_t doi;
1127 u_int32_t proto;
1128 int i;
1130 printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
1132 p = (struct isakmp_pl_d *)ext;
1133 TCHECK(*p);
1134 safememcpy(&d, ext, sizeof(d));
1135 doi = ntohl(d.doi);
1136 proto = d.prot_id;
1137 if (doi != 1) {
1138 printf(" doi=%u", doi);
1139 printf(" proto=%u", proto);
1140 } else {
1141 printf(" doi=ipsec");
1142 printf(" proto=%s", PROTOIDSTR(proto));
1144 printf(" spilen=%u", d.spi_size);
1145 printf(" nspi=%u", ntohs(d.num_spi));
1146 printf(" spi=");
1147 q = (u_int8_t *)(p + 1);
1148 for (i = 0; i < ntohs(d.num_spi); i++) {
1149 if (i != 0)
1150 printf(",");
1151 if (!rawprint((caddr_t)q, d.spi_size))
1152 goto trunc;
1153 q += d.spi_size;
1155 return q;
1156 trunc:
1157 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
1158 return NULL;
1161 static const u_char *
1162 isakmp_vid_print(const struct isakmp_gen *ext,
1163 u_int item_len _U_, const u_char *ep _U_,
1164 u_int32_t phase _U_, u_int32_t doi _U_,
1165 u_int32_t proto _U_, int depth _U_)
1167 struct isakmp_gen e;
1169 printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1171 TCHECK(*ext);
1172 safememcpy(&e, ext, sizeof(e));
1173 printf(" len=%d", ntohs(e.len) - 4);
1174 if (2 < vflag && 4 < ntohs(e.len)) {
1175 printf(" ");
1176 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
1177 goto trunc;
1179 return (u_char *)ext + ntohs(e.len);
1180 trunc:
1181 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
1182 return NULL;
1185 static const u_char *
1186 isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1187 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1189 const u_char *cp;
1190 struct isakmp_gen e;
1191 u_int item_len;
1193 cp = (u_char *)ext;
1194 TCHECK(*ext);
1195 safememcpy(&e, ext, sizeof(e));
1198 * Since we can't have a payload length of less than 4 bytes,
1199 * we need to bail out here if the generic header is nonsensical
1200 * or truncated, otherwise we could loop forever processing
1201 * zero-length items or otherwise misdissect the packet.
1203 item_len = ntohs(e.len);
1204 if (item_len <= 4)
1205 return NULL;
1207 if (NPFUNC(np)) {
1209 * XXX - what if item_len is too short, or too long,
1210 * for this payload type?
1212 cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth);
1213 } else {
1214 printf("%s", NPSTR(np));
1215 cp += item_len;
1218 return cp;
1219 trunc:
1220 printf(" [|isakmp]");
1221 return NULL;
1224 static const u_char *
1225 isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1226 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1228 const u_char *cp;
1229 int i;
1230 struct isakmp_gen e;
1232 cp = (const u_char *)ext;
1234 while (np) {
1235 TCHECK(*ext);
1237 safememcpy(&e, ext, sizeof(e));
1239 TCHECK2(*ext, ntohs(e.len));
1241 depth++;
1242 printf("\n");
1243 for (i = 0; i < depth; i++)
1244 printf(" ");
1245 printf("(");
1246 cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth);
1247 printf(")");
1248 depth--;
1250 if (cp == NULL) {
1251 /* Zero-length subitem */
1252 return NULL;
1255 np = e.np;
1256 ext = (struct isakmp_gen *)cp;
1258 return cp;
1259 trunc:
1260 printf(" [|%s]", NPSTR(np));
1261 return NULL;
1264 static char *
1265 numstr(int x)
1267 static char buf[20];
1268 snprintf(buf, sizeof(buf), "#%d", x);
1269 return buf;
1273 * some compiler tries to optimize memcpy(), using the alignment constraint
1274 * on the argument pointer type. by using this function, we try to avoid the
1275 * optimization.
1277 static void
1278 safememcpy(void *p, const void *q, size_t l)
1280 memcpy(p, q, l);
1283 void
1284 isakmp_print(netdissect_options *ndo,
1285 const u_char *bp, u_int length,
1286 const u_char *bp2)
1288 const struct isakmp *p;
1289 struct isakmp base;
1290 const u_char *ep;
1291 u_char np;
1292 int i;
1293 int phase;
1294 int major, minor;
1296 p = (const struct isakmp *)bp;
1297 ep = ndo->ndo_snapend;
1299 if ((struct isakmp *)ep < p + 1) {
1300 printf("[|isakmp]");
1301 return;
1304 safememcpy(&base, p, sizeof(base));
1306 printf("isakmp");
1307 if (vflag) {
1308 major = (base.vers & ISAKMP_VERS_MAJOR)
1309 >> ISAKMP_VERS_MAJOR_SHIFT;
1310 minor = (base.vers & ISAKMP_VERS_MINOR)
1311 >> ISAKMP_VERS_MINOR_SHIFT;
1312 printf(" %d.%d", major, minor);
1315 if (vflag) {
1316 printf(" msgid ");
1317 rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
1320 if (1 < vflag) {
1321 printf(" cookie ");
1322 rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
1323 printf("->");
1324 rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
1326 printf(":");
1328 phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
1329 if (phase == 1)
1330 printf(" phase %d", phase);
1331 else
1332 printf(" phase %d/others", phase);
1334 i = cookie_find(&base.i_ck);
1335 if (i < 0) {
1336 if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
1337 /* the first packet */
1338 printf(" I");
1339 if (bp2)
1340 cookie_record(&base.i_ck, bp2);
1341 } else
1342 printf(" ?");
1343 } else {
1344 if (bp2 && cookie_isinitiator(i, bp2))
1345 printf(" I");
1346 else if (bp2 && cookie_isresponder(i, bp2))
1347 printf(" R");
1348 else
1349 printf(" ?");
1352 printf(" %s", ETYPESTR(base.etype));
1353 if (base.flags) {
1354 printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
1355 base.flags & ISAKMP_FLAG_C ? "C" : "");
1358 if (vflag) {
1359 const struct isakmp_gen *ext;
1360 int nparen;
1362 #define CHECKLEN(p, np) \
1363 if (ep < (u_char *)(p)) { \
1364 printf(" [|%s]", NPSTR(np)); \
1365 goto done; \
1368 printf(":");
1370 /* regardless of phase... */
1371 if (base.flags & ISAKMP_FLAG_E) {
1373 * encrypted, nothing we can do right now.
1374 * we hope to decrypt the packet in the future...
1376 printf(" [encrypted %s]", NPSTR(base.np));
1377 goto done;
1380 nparen = 0;
1381 CHECKLEN(p + 1, base.np)
1383 np = base.np;
1384 ext = (struct isakmp_gen *)(p + 1);
1385 isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
1388 done:
1389 if (vflag) {
1390 if (ntohl(base.len) != length) {
1391 printf(" (len mismatch: isakmp %u/ip %u)",
1392 (u_int32_t)ntohl(base.len), length);
1397 void
1398 isakmp_rfc3948_print(netdissect_options *ndo,
1399 const u_char *bp, u_int length,
1400 const u_char *bp2)
1402 const u_char *ep;
1403 ep = ndo->ndo_snapend;
1405 if(length == 1 && bp[0]==0xff) {
1406 ND_PRINT((ndo, "isakmp-nat-keep-alive"));
1407 return;
1410 if(length < 4) {
1411 goto trunc;
1415 * see if this is an IKE packet
1417 if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
1418 ND_PRINT((ndo, "NONESP-encap: "));
1419 isakmp_print(ndo, bp+4, length-4, bp2);
1420 return;
1423 /* must be an ESP packet */
1425 int nh, enh, padlen;
1426 int advance;
1428 ND_PRINT((ndo, "UDP-encap: "));
1430 advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
1431 if(advance <= 0)
1432 return;
1434 bp += advance;
1435 length -= advance + padlen;
1436 nh = enh & 0xff;
1438 ip_print_inner(ndo, bp, length, nh, bp2);
1439 return;
1442 trunc:
1443 printf("[|isakmp]");
1444 return;
1448 * Local Variables:
1449 * c-style: whitesmith
1450 * c-basic-offset: 8
1451 * End: