1 /* $FreeBSD$ */ 2 /* $KAME: pfkey_dump.c,v 1.19 2000/06/10 06:47:11 sakane Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/socket.h> 36 #include <netinet6/ipsec.h> 37 #include <net/pfkeyv2.h> 38 #include <netkey/key_var.h> 39 #include <netkey/key_debug.h> 40 41 #include <netinet/in.h> 42 #include <netinet6/ipsec.h> 43 #include <arpa/inet.h> 44 45 #include <stdlib.h> 46 #include <unistd.h> 47 #include <stdio.h> 48 #include <string.h> 49 #include <time.h> 50 #include <netdb.h> 51 52 #include "ipsec_strerror.h" 53 #include "libpfkey.h" 54 55 #define GETMSGSTR(str, num) \ 56 do { \ 57 if (sizeof((str)[0]) == 0 \ 58 || num >= sizeof(str)/sizeof((str)[0])) \ 59 printf("%d ", (num)); \ 60 else if (strlen((str)[(num)]) == 0) \ 61 printf("%d ", (num)); \ 62 else \ 63 printf("%s ", (str)[(num)]); \ 64 } while (0) 65 66 static char *str_ipaddr __P((struct sockaddr *)); 67 static char *str_prefport __P((u_int, u_int, u_int)); 68 static char *str_time __P((time_t)); 69 static void str_lifetime_byte __P((struct sadb_lifetime *, char *)); 70 71 /* 72 * Must to be re-written about following strings. 73 */ 74 static char *_str_satype[] = { 75 "unspec", 76 "unknown", 77 "ah", 78 "esp", 79 "unknown", 80 "rsvp", 81 "ospfv2", 82 "ripv2", 83 "mip", 84 "ipcomp", 85 }; 86 87 static char *_str_mode[] = { 88 "any", 89 "transport", 90 "tunnel", 91 }; 92 93 static char *_str_upper[] = { 94 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 95 "", "tcp", "", "egp", "", 96 /*10*/ "", "", "", "", "", 97 "", "", "udp", "", "", 98 /*20*/ "", "", "idp", "", "", 99 "", "", "", "", "tp", 100 /*30*/ "", "", "", "", "", 101 "", "", "", "", "", 102 /*40*/ "", "ip6", "", "rt6", "frag6", 103 "", "rsvp", "gre", "", "", 104 /*50*/ "esp", "ah", "", "", "", 105 "", "", "", "icmp6", "none", 106 /*60*/ "dst6", 107 }; 108 109 static char *_str_state[] = { 110 "larval", 111 "mature", 112 "dying", 113 "dead", 114 }; 115 116 static char *_str_alg_auth[] = { 117 "none", 118 "hmac-md5", 119 "hmac-sha1", 120 "md5", 121 "sha", 122 "null", 123 }; 124 125 static char *_str_alg_enc[] = { 126 "none", 127 "des-cbc", 128 "3des-cbc", 129 "null", 130 "blowfish-cbc", 131 "cast128-cbc", 132 "rc5-cbc", 133 }; 134 135 static char *_str_alg_comp[] = { 136 "none", 137 "oui", 138 "deflate", 139 "lzs", 140 }; 141 142 /* 143 * dump SADB_MSG formated. For debugging, you should use kdebug_sadb(). 144 */ 145 void 146 pfkey_sadump(m) 147 struct sadb_msg *m; 148 { 149 caddr_t mhp[SADB_EXT_MAX + 1]; 150 struct sadb_sa *m_sa; 151 struct sadb_x_sa2 *m_sa2; 152 struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts; 153 struct sadb_address *m_saddr, *m_daddr, *m_paddr; 154 struct sadb_key *m_auth, *m_enc; 155 struct sadb_ident *m_sid, *m_did; 156 struct sadb_sens *m_sens; 157 158 /* check pfkey message. */ 159 if (pfkey_align(m, mhp)) { 160 printf("%s\n", ipsec_strerror()); 161 return; 162 } 163 if (pfkey_check(mhp)) { 164 printf("%s\n", ipsec_strerror()); 165 return; 166 } 167 168 m_sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; 169 m_sa2 = (struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2]; 170 m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 171 m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 172 m_lfts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 173 m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; 174 m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; 175 m_paddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_PROXY]; 176 m_auth = (struct sadb_key *)mhp[SADB_EXT_KEY_AUTH]; 177 m_enc = (struct sadb_key *)mhp[SADB_EXT_KEY_ENCRYPT]; 178 m_sid = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_SRC]; 179 m_did = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_DST]; 180 m_sens = (struct sadb_sens *)mhp[SADB_EXT_SENSITIVITY]; 181 182 /* source address */ 183 if (m_saddr == NULL) { 184 printf("no ADDRESS_SRC extension.\n"); 185 return; 186 } 187 printf("%s ", str_ipaddr((struct sockaddr *)(m_saddr + 1))); 188 189 /* destination address */ 190 if (m_daddr == NULL) { 191 printf("no ADDRESS_DST extension.\n"); 192 return; 193 } 194 printf("%s ", str_ipaddr((struct sockaddr *)(m_daddr + 1))); 195 196 /* SA type */ 197 if (m_sa == NULL) { 198 printf("no SA extension.\n"); 199 return; 200 } 201 if (m_sa2 == NULL) { 202 printf("no SA2 extension.\n"); 203 return; 204 } 205 printf("\n\t"); 206 207 GETMSGSTR(_str_satype, m->sadb_msg_satype); 208 209 printf("mode="); 210 GETMSGSTR(_str_mode, m_sa2->sadb_x_sa2_mode); 211 212 printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n", 213 (u_int32_t)ntohl(m_sa->sadb_sa_spi), 214 (u_int32_t)ntohl(m_sa->sadb_sa_spi), 215 (u_int32_t)m_sa2->sadb_x_sa2_reqid, 216 (u_int32_t)m_sa2->sadb_x_sa2_reqid); 217 218 /* encryption key */ 219 if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) { 220 printf("\tC: "); 221 GETMSGSTR(_str_alg_comp, m_sa->sadb_sa_encrypt); 222 } else if (m->sadb_msg_satype == SADB_SATYPE_ESP) { 223 if (m_enc != NULL) { 224 printf("\tE: "); 225 GETMSGSTR(_str_alg_enc, m_sa->sadb_sa_encrypt); 226 ipsec_hexdump((caddr_t)m_enc + sizeof(*m_enc), 227 m_enc->sadb_key_bits / 8); 228 printf("\n"); 229 } 230 } 231 232 /* authentication key */ 233 if (m_auth != NULL) { 234 printf("\tA: "); 235 GETMSGSTR(_str_alg_auth, m_sa->sadb_sa_auth); 236 ipsec_hexdump((caddr_t)m_auth + sizeof(*m_auth), 237 m_auth->sadb_key_bits / 8); 238 printf("\n"); 239 } 240 241 /* replay windoe size & flags */ 242 printf("\treplay=%u flags=0x%08x ", 243 m_sa->sadb_sa_replay, 244 m_sa->sadb_sa_flags); 245 246 /* state */ 247 printf("state="); 248 GETMSGSTR(_str_state, m_sa->sadb_sa_state); 249 250 printf("seq=%lu pid=%lu\n", 251 (u_long)m->sadb_msg_seq, 252 (u_long)m->sadb_msg_pid); 253 254 /* lifetime */ 255 if (m_lftc != NULL) { 256 time_t tmp_time = time(0); 257 258 printf("\tcreated: %s", 259 str_time(m_lftc->sadb_lifetime_addtime)); 260 printf("\tcurrent: %s\n", str_time(tmp_time)); 261 printf("\tdiff: %lu(s)", 262 (u_long)(m_lftc->sadb_lifetime_addtime == 0 ? 263 0 : (tmp_time - m_lftc->sadb_lifetime_addtime))); 264 265 printf("\thard: %lu(s)", 266 (u_long)(m_lfth == NULL ? 267 0 : m_lfth->sadb_lifetime_addtime)); 268 printf("\tsoft: %lu(s)\n", 269 (u_long)(m_lfts == NULL ? 270 0 : m_lfts->sadb_lifetime_addtime)); 271 272 printf("\tlast: %s", 273 str_time(m_lftc->sadb_lifetime_usetime)); 274 printf("\thard: %lu(s)", 275 (u_long)(m_lfth == NULL ? 276 0 : m_lfth->sadb_lifetime_usetime)); 277 printf("\tsoft: %lu(s)\n", 278 (u_long)(m_lfts == NULL ? 279 0 : m_lfts->sadb_lifetime_usetime)); 280 281 str_lifetime_byte(m_lftc, "current"); 282 str_lifetime_byte(m_lfth, "hard"); 283 str_lifetime_byte(m_lfts, "soft"); 284 printf("\n"); 285 286 printf("\tallocated: %lu", 287 (unsigned long)m_lftc->sadb_lifetime_allocations); 288 printf("\thard: %lu", 289 (u_long)(m_lfth == NULL ? 290 0 : m_lfth->sadb_lifetime_allocations)); 291 printf("\tsoft: %lu\n", 292 (u_long)(m_lfts == NULL ? 293 0 : m_lfts->sadb_lifetime_allocations)); 294 } 295 296 /* XXX DEBUG */ 297 printf("\trefcnt=%u\n", m->sadb_msg_reserved); 298 299 return; 300 } 301 302 void 303 pfkey_spdump(m) 304 struct sadb_msg *m; 305 { 306 char pbuf[NI_MAXSERV]; 307 caddr_t mhp[SADB_EXT_MAX + 1]; 308 struct sadb_address *m_saddr, *m_daddr; 309 struct sadb_x_policy *m_xpl; 310 struct sockaddr *sa; 311 u_int16_t port; 312 313 /* check pfkey message. */ 314 if (pfkey_align(m, mhp)) { 315 printf("%s\n", ipsec_strerror()); 316 return; 317 } 318 if (pfkey_check(mhp)) { 319 printf("%s\n", ipsec_strerror()); 320 return; 321 } 322 323 m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; 324 m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; 325 m_xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; 326 327 /* source address */ 328 if (m_saddr == NULL) { 329 printf("no ADDRESS_SRC extension.\n"); 330 return; 331 } 332 sa = (struct sockaddr *)(m_saddr + 1); 333 switch (sa->sa_family) { 334 case AF_INET: 335 case AF_INET6: 336 if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf), 337 NI_NUMERICSERV) != 0) 338 port = 0; /*XXX*/ 339 else 340 port = atoi(pbuf); 341 printf("%s%s ", str_ipaddr(sa), 342 str_prefport(sa->sa_family, 343 m_saddr->sadb_address_prefixlen, port)); 344 break; 345 default: 346 printf("unknown-af "); 347 break; 348 } 349 350 /* destination address */ 351 if (m_daddr == NULL) { 352 printf("no ADDRESS_DST extension.\n"); 353 return; 354 } 355 sa = (struct sockaddr *)(m_daddr + 1); 356 switch (sa->sa_family) { 357 case AF_INET: 358 case AF_INET6: 359 if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf), 360 NI_NUMERICSERV) != 0) 361 port = 0; /*XXX*/ 362 else 363 port = atoi(pbuf); 364 printf("%s%s ", str_ipaddr(sa), 365 str_prefport(sa->sa_family, 366 m_daddr->sadb_address_prefixlen, port)); 367 break; 368 default: 369 printf("unknown-af "); 370 break; 371 } 372 373 /* upper layer protocol */ 374 if (m_saddr->sadb_address_proto != m_daddr->sadb_address_proto) { 375 printf("upper layer protocol mismatched.\n"); 376 return; 377 } 378 if (m_saddr->sadb_address_proto == IPSEC_ULPROTO_ANY) 379 printf("any"); 380 else 381 GETMSGSTR(_str_upper, m_saddr->sadb_address_proto); 382 383 /* policy */ 384 { 385 char *d_xpl; 386 387 if (m_xpl == NULL) { 388 printf("no X_POLICY extension.\n"); 389 return; 390 } 391 d_xpl = ipsec_dump_policy((char *)m_xpl, "\n\t"); 392 393 /* dump SPD */ 394 printf("\n\t%s\n", d_xpl); 395 free(d_xpl); 396 } 397 398 printf("\tspid=%ld seq=%ld pid=%ld\n", 399 (u_long)m_xpl->sadb_x_policy_id, 400 (u_long)m->sadb_msg_seq, 401 (u_long)m->sadb_msg_pid); 402 403 /* XXX TEST */ 404 printf("\trefcnt=%u\n", m->sadb_msg_reserved); 405 406 return; 407 } 408 409 /* 410 * set "ipaddress" to buffer. 411 */ 412 static char * 413 str_ipaddr(sa) 414 struct sockaddr *sa; 415 { 416 static char buf[NI_MAXHOST]; 417 #ifdef NI_WITHSCOPEID 418 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 419 #else 420 const int niflag = NI_NUMERICHOST; 421 #endif 422 423 if (sa == NULL) 424 return ""; 425 426 if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, niflag) == 0) 427 return buf; 428 return NULL; 429 } 430 431 /* 432 * set "/prefix[port number]" to buffer. 433 */ 434 static char * 435 str_prefport(family, pref, port) 436 u_int family, pref, port; 437 { 438 static char buf[128]; 439 char prefbuf[10]; 440 char portbuf[10]; 441 int plen; 442 443 switch (family) { 444 case AF_INET: 445 plen = sizeof(struct in_addr) << 3; 446 break; 447 case AF_INET6: 448 plen = sizeof(struct in6_addr) << 3; 449 break; 450 default: 451 return "?"; 452 } 453 454 if (pref == plen) 455 prefbuf[0] = '\0'; 456 else 457 snprintf(prefbuf, sizeof(prefbuf), "/%u", pref); 458 459 if (port == IPSEC_PORT_ANY) 460 snprintf(portbuf, sizeof(portbuf), "[%s]", "any"); 461 else 462 snprintf(portbuf, sizeof(portbuf), "[%u]", port); 463 464 snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf); 465 466 return buf; 467 } 468 469 /* 470 * set "Mon Day Time Year" to buffer 471 */ 472 static char * 473 str_time(t) 474 time_t t; 475 { 476 static char buf[128]; 477 478 if (t == 0) { 479 int i = 0; 480 for (;i < 20;) buf[i++] = ' '; 481 } else { 482 char *t0; 483 t0 = ctime(&t); 484 memcpy(buf, t0 + 4, 20); 485 } 486 487 buf[20] = '\0'; 488 489 return(buf); 490 } 491 492 static void 493 str_lifetime_byte(x, str) 494 struct sadb_lifetime *x; 495 char *str; 496 { 497 double y; 498 char *unit; 499 int w; 500 501 if (x == NULL) { 502 printf("\t%s: 0(bytes)", str); 503 return; 504 } 505 506 #if 0 507 if ((x->sadb_lifetime_bytes) / 1024 / 1024) { 508 y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024; 509 unit = "M"; 510 w = 1; 511 } else if ((x->sadb_lifetime_bytes) / 1024) { 512 y = (x->sadb_lifetime_bytes) * 1.0 / 1024; 513 unit = "K"; 514 w = 1; 515 } else { 516 y = (x->sadb_lifetime_bytes) * 1.0; 517 unit = ""; 518 w = 0; 519 } 520 #else 521 y = (x->sadb_lifetime_bytes) * 1.0; 522 unit = ""; 523 w = 0; 524 #endif 525 printf("\t%s: %.*f(%sbytes)", str, w, y, unit); 526 } 527