10SN/A/* $NetBSD: setkey.c,v 1.14 2009/08/06 04:44:43 tteras Exp $ */ 29330SN/A 30SN/A/* $KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $ */ 40SN/A 50SN/A/* 60SN/A * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 72362SN/A * All rights reserved. 80SN/A * 92362SN/A * Redistribution and use in source and binary forms, with or without 100SN/A * modification, are permitted provided that the following conditions 110SN/A * are met: 120SN/A * 1. Redistributions of source code must retain the above copyright 130SN/A * notice, this list of conditions and the following disclaimer. 140SN/A * 2. Redistributions in binary form must reproduce the above copyright 150SN/A * notice, this list of conditions and the following disclaimer in the 160SN/A * documentation and/or other materials provided with the distribution. 170SN/A * 3. Neither the name of the project nor the names of its contributors 180SN/A * may be used to endorse or promote products derived from this software 190SN/A * without specific prior written permission. 200SN/A * 212362SN/A * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 222362SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 232362SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 240SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 250SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 260SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 270SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 280SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 290SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 300SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 310SN/A * SUCH DAMAGE. 320SN/A */ 330SN/A 340SN/A#ifdef HAVE_CONFIG_H 350SN/A#include "config.h" 360SN/A#endif 370SN/A 380SN/A#include <sys/types.h> 390SN/A#include <sys/param.h> 4017338Smli#include <sys/socket.h> 410SN/A#include <sys/time.h> 420SN/A#include <sys/stat.h> 430SN/A#include <sys/sysctl.h> 440SN/A#include <err.h> 450SN/A#include <netinet/in.h> 460SN/A#include <net/pfkeyv2.h> 470SN/A#include PATH_IPSEC_H 480SN/A 490SN/A#include <stdio.h> 500SN/A#include <stdlib.h> 510SN/A#include <limits.h> 520SN/A#include <string.h> 530SN/A#include <ctype.h> 540SN/A#include <unistd.h> 550SN/A#include <errno.h> 560SN/A#include <netdb.h> 570SN/A#include <fcntl.h> 580SN/A#include <dirent.h> 590SN/A#include <time.h> 601796SN/A 611796SN/A#ifdef HAVE_READLINE 620SN/A#include <readline/readline.h> 631796SN/A#include <readline/history.h> 641796SN/A#endif 651796SN/A 660SN/A#include "config.h" 670SN/A#include "libpfkey.h" 680SN/A#include "package_version.h" 691796SN/A#define extern /* so that variables in extern.h are not extern... */ 701959SN/A#include "extern.h" 711796SN/A 721796SN/A#define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0') 731796SN/A 741796SN/Avoid usage __P((int)); 757365SN/Aint main __P((int, char **)); 761796SN/Aint get_supported __P((void)); 771796SN/Avoid sendkeyshort __P((u_int)); 780SN/Avoid promisc __P((void)); 791796SN/Aint postproc __P((struct sadb_msg *, int)); 801796SN/Aint verifypriority __P((struct sadb_msg *m)); 811796SN/Aint fileproc __P((const char *)); 821796SN/Aconst char *numstr __P((int)); 830SN/Avoid shortdump_hdr __P((void)); 840SN/Avoid shortdump __P((struct sadb_msg *)); 850SN/Astatic void printdate __P((void)); 860SN/Astatic int32_t gmt2local __P((time_t)); 870SN/Avoid stdin_loop __P((void)); 880SN/A 890SN/A#define MODE_SCRIPT 1 901796SN/A#define MODE_CMDDUMP 2 911796SN/A#define MODE_CMDFLUSH 3 921796SN/A#define MODE_PROMISC 4 931796SN/A#define MODE_STDIN 5 941796SN/A 951796SN/Aint so; 961796SN/A 971796SN/Aint f_forever = 0; 981796SN/Aint f_all = 0; 991796SN/Aint f_verbose = 0; 1001796SN/Aint f_mode = 0; 1011796SN/Aint f_cmddump = 0; 1021796SN/Aint f_policy = 0; 1031796SN/Aint f_hexdump = 0; 1041796SN/Aint f_tflag = 0; 1057365SN/Aint f_notreally = 0; 1061796SN/Aint f_withports = 0; 1071796SN/A#ifdef HAVE_POLICY_FWD 1081796SN/Aint f_rfcmode = 1; 1090SN/A#define RK_OPTS "rk" 1100SN/A#else 1110SN/Aint f_rkwarn = 0; 1121796SN/A#define RK_OPTS "" 1131796SN/Astatic void rkwarn(void); 1141796SN/Astatic void 1151796SN/Arkwarn(void) 1161796SN/A{ 1171796SN/A if (!f_rkwarn) { 1181959SN/A f_rkwarn = 1; 1191796SN/A printf("warning: -r and -k options are not supported in this environment\n"); 1201796SN/A } 1211796SN/A} 1221796SN/A 1231796SN/A#endif 1241796SN/Astatic time_t thiszone; 1251796SN/A 1261796SN/Avoid 1271796SN/Ausage(int only_version) 1281796SN/A{ 1291796SN/A printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL); 1301796SN/A if (! only_version) { 1311796SN/A printf("usage: setkey [-v" RK_OPTS "] file ...\n"); 1321796SN/A printf(" setkey [-nv" RK_OPTS "] -c\n"); 1330SN/A printf(" setkey [-nv" RK_OPTS "] -f filename\n"); 1340SN/A printf(" setkey [-Palpv" RK_OPTS "] -D\n"); 1351796SN/A printf(" setkey [-Pv] -F\n"); 1361796SN/A printf(" setkey [-H] -x\n"); 1371796SN/A printf(" setkey [-V] [-h]\n"); 1381796SN/A } 1390SN/A exit(1); 1400SN/A} 1410SN/A 1420SN/Aint 1431796SN/Amain(argc, argv) 1440SN/A int argc; 1450SN/A char **argv; 1460SN/A{ 1470SN/A FILE *fp = stdin; 1481796SN/A int c; 1491796SN/A 1501796SN/A if (argc == 1) { 1511796SN/A usage(0); 1521796SN/A /* NOTREACHED */ 1531796SN/A } 1541796SN/A 1551959SN/A thiszone = gmt2local(0); 1561796SN/A 1571796SN/A while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) { 1581796SN/A switch (c) { 1591796SN/A case 'c': 1601796SN/A f_mode = MODE_STDIN; 1611796SN/A#ifdef HAVE_READLINE 1621796SN/A /* disable filename completion */ 1631796SN/A rl_bind_key('\t', rl_insert); 1641796SN/A#endif 1651796SN/A break; 1661796SN/A case 'f': 1670SN/A f_mode = MODE_SCRIPT; 1680SN/A if ((fp = fopen(optarg, "r")) == NULL) { 1691796SN/A err(1, "fopen"); 1701796SN/A /*NOTREACHED*/ 1711796SN/A } 1721796SN/A break; 1730SN/A case 'D': 1740SN/A f_mode = MODE_CMDDUMP; 1750SN/A break; 1761796SN/A case 'F': 1770SN/A f_mode = MODE_CMDFLUSH; 1780SN/A break; 1790SN/A case 'a': 1800SN/A f_all = 1; 1810SN/A break; 1820SN/A case 'l': 1830SN/A f_forever = 1; 1840SN/A break; 1850SN/A case 'n': 1860SN/A f_notreally = 1; 1870SN/A break; 1880SN/A#ifdef __NetBSD__ 1890SN/A case 'h': 1900SN/A#endif 1910SN/A case 'H': 1920SN/A f_hexdump = 1; 1930SN/A break; 1940SN/A case 'x': 1950SN/A f_mode = MODE_PROMISC; 1960SN/A f_tflag++; 1970SN/A break; 1980SN/A case 'P': 1990SN/A f_policy = 1; 2000SN/A break; 2010SN/A case 'p': 2020SN/A f_withports = 1; 2030SN/A break; 2040SN/A case 'v': 2050SN/A f_verbose = 1; 2060SN/A break; 2070SN/A case 'r': 2080SN/A#ifdef HAVE_POLICY_FWD 2090SN/A f_rfcmode = 1; 2103897SN/A#else 2113897SN/A rkwarn(); 2123897SN/A#endif 2130SN/A break; 2140SN/A case 'k': 2150SN/A#ifdef HAVE_POLICY_FWD 2160SN/A f_rfcmode = 0; 2170SN/A#else 2180SN/A rkwarn(); 2190SN/A#endif 2200SN/A break; 2210SN/A case 'V': 2220SN/A usage(1); 2230SN/A break; 2240SN/A /*NOTREACHED*/ 2250SN/A#ifndef __NetBSD__ 2260SN/A case 'h': 2270SN/A#endif 2280SN/A case '?': 2290SN/A default: 2300SN/A usage(0); 2310SN/A /*NOTREACHED*/ 2320SN/A } 2330SN/A } 2340SN/A 2350SN/A argc -= optind; 2360SN/A argv += optind; 2370SN/A 2380SN/A if (argc > 0) { 2390SN/A while (argc--) 2400SN/A if (fileproc(*argv++) < 0) { 2410SN/A err(1, "%s", argv[-1]); 2420SN/A /*NOTREACHED*/ 2430SN/A } 2440SN/A exit(0); 2450SN/A } 2460SN/A 2470SN/A so = pfkey_open(); 2480SN/A if (so < 0) { 2490SN/A perror("pfkey_open"); 2500SN/A exit(1); 2510SN/A } 2520SN/A 2530SN/A switch (f_mode) { 2540SN/A case MODE_CMDDUMP: 2550SN/A sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP); 2560SN/A break; 2571796SN/A case MODE_CMDFLUSH: 2581796SN/A sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH); 2591796SN/A break; 2601796SN/A case MODE_SCRIPT: 2611959SN/A if (get_supported() < 0) { 2621796SN/A errx(1, "%s", ipsec_strerror()); 2631959SN/A /*NOTREACHED*/ 2641959SN/A } 2651796SN/A if (parse(&fp)) 2661796SN/A exit (1); 2671796SN/A break; 2681796SN/A case MODE_STDIN: 2691796SN/A if (get_supported() < 0) { 2701796SN/A errx(1, "%s", ipsec_strerror()); 2711796SN/A /*NOTREACHED*/ 2721796SN/A } 2731796SN/A stdin_loop(); 2741796SN/A break; 2751796SN/A case MODE_PROMISC: 2761796SN/A promisc(); 2771796SN/A /*NOTREACHED*/ 2781796SN/A default: 2791796SN/A usage(0); 2801796SN/A /*NOTREACHED*/ 2811796SN/A } 2821796SN/A 2831796SN/A exit(0); 2841796SN/A} 2850SN/A 286int 287get_supported() 288{ 289 290 if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0) 291 return -1; 292 293 if (pfkey_recv_register(so) < 0) 294 return -1; 295 296 return (0); 297} 298 299void 300stdin_loop() 301{ 302 char line[1024], *semicolon, *comment; 303 size_t linelen = 0; 304 305 memset (line, 0, sizeof(line)); 306 307 parse_init(); 308 while (1) { 309#ifdef HAVE_READLINE 310 char *rbuf; 311 rbuf = readline (""); 312 if (! rbuf) 313 break; 314#else 315 char rbuf[1024]; 316 rbuf[0] = '\0'; 317 if (fgets(rbuf, sizeof(rbuf), stdin) == NULL) 318 break; 319 if (rbuf[strlen(rbuf)-1] == '\n') 320 rbuf[strlen(rbuf)-1] = '\0'; 321#endif 322 comment = strchr(rbuf, '#'); 323 if (comment) 324 *comment = '\0'; 325 326 if (!rbuf[0]) 327 continue; 328 329 linelen += snprintf (&line[linelen], sizeof(line) - linelen, 330 "%s%s", linelen > 0 ? " " : "", rbuf); 331 332 semicolon = strchr(line, ';'); 333 while (semicolon) { 334 char saved_char = *++semicolon; 335 *semicolon = '\0'; 336#ifdef HAVE_READLINE 337 add_history (line); 338#endif 339 340#ifdef HAVE_PFKEY_POLICY_PRIORITY 341 last_msg_type = -1; /* invalid message type */ 342#endif 343 344 parse_string (line); 345 if (exit_now) 346 return; 347 if (saved_char) { 348 *semicolon = saved_char; 349 linelen = strlen (semicolon); 350 memmove (line, semicolon, linelen + 1); 351 semicolon = strchr(line, ';'); 352 } 353 else { 354 semicolon = NULL; 355 linelen = 0; 356 } 357 } 358 } 359} 360 361void 362sendkeyshort(type) 363 u_int type; 364{ 365 struct sadb_msg msg; 366 367 msg.sadb_msg_version = PF_KEY_V2; 368 msg.sadb_msg_type = type; 369 msg.sadb_msg_errno = 0; 370 msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; 371 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 372 msg.sadb_msg_reserved = 0; 373 msg.sadb_msg_seq = 0; 374 msg.sadb_msg_pid = getpid(); 375 376 sendkeymsg((char *)&msg, sizeof(msg)); 377 378 return; 379} 380 381void 382promisc() 383{ 384 struct sadb_msg msg; 385 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 386 ssize_t l; 387 388 msg.sadb_msg_version = PF_KEY_V2; 389 msg.sadb_msg_type = SADB_X_PROMISC; 390 msg.sadb_msg_errno = 0; 391 msg.sadb_msg_satype = 1; 392 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 393 msg.sadb_msg_reserved = 0; 394 msg.sadb_msg_seq = 0; 395 msg.sadb_msg_pid = getpid(); 396 397 if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { 398 err(1, "send"); 399 /*NOTREACHED*/ 400 } 401 402 while (1) { 403 struct sadb_msg *base; 404 405 if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { 406 err(1, "recv"); 407 /*NOTREACHED*/ 408 } 409 410 if (l != sizeof(*base)) 411 continue; 412 413 base = (struct sadb_msg *)rbuf; 414 if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), 415 0)) < 0) { 416 err(1, "recv"); 417 /*NOTREACHED*/ 418 } 419 printdate(); 420 if (f_hexdump) { 421 int i; 422 for (i = 0; i < l; i++) { 423 if (i % 16 == 0) 424 printf("%08x: ", i); 425 printf("%02x ", rbuf[i] & 0xff); 426 if (i % 16 == 15) 427 printf("\n"); 428 } 429 if (l % 16) 430 printf("\n"); 431 } 432 /* adjust base pointer for promisc mode */ 433 if (base->sadb_msg_type == SADB_X_PROMISC) { 434 if ((ssize_t)sizeof(*base) < l) 435 base++; 436 else 437 base = NULL; 438 } 439 if (base) { 440 kdebug_sadb(base); 441 printf("\n"); 442 fflush(stdout); 443 } 444 } 445} 446 447/* Generate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts' 448 * Return value is dynamically generated array of SPIs, also number of 449 * SPIs through num_spi pointer. 450 * On any error, set *num_spi to 0 and return NULL. 451 */ 452u_int32_t * 453sendkeymsg_spigrep(satype, srcs, dsts, num_spi) 454 unsigned int satype; 455 struct addrinfo *srcs; 456 struct addrinfo *dsts; 457 int *num_spi; 458{ 459 struct sadb_msg msg, *m; 460 char *buf; 461 size_t len; 462 ssize_t l; 463 u_char rbuf[1024 * 32]; 464 caddr_t mhp[SADB_EXT_MAX + 1]; 465 struct sadb_address *saddr; 466 struct sockaddr *s; 467 struct addrinfo *a; 468 struct sadb_sa *sa; 469 u_int32_t *spi = NULL; 470 int max_spi = 0, fail = 0; 471 472 *num_spi = 0; 473 474 if (f_notreally) { 475 return NULL; 476 } 477 478 { 479 struct timeval tv; 480 tv.tv_sec = 1; 481 tv.tv_usec = 0; 482 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 483 perror("setsockopt"); 484 return NULL; 485 } 486 } 487 488 msg.sadb_msg_version = PF_KEY_V2; 489 msg.sadb_msg_type = SADB_DUMP; 490 msg.sadb_msg_errno = 0; 491 msg.sadb_msg_satype = satype; 492 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 493 msg.sadb_msg_reserved = 0; 494 msg.sadb_msg_seq = 0; 495 msg.sadb_msg_pid = getpid(); 496 buf = (char *)&msg; 497 len = sizeof(msg); 498 499 if (f_verbose) { 500 kdebug_sadb(&msg); 501 printf("\n"); 502 } 503 if (f_hexdump) { 504 int i; 505 for (i = 0; i < len; i++) { 506 if (i % 16 == 0) 507 printf("%08x: ", i); 508 printf("%02x ", buf[i] & 0xff); 509 if (i % 16 == 15) 510 printf("\n"); 511 } 512 if (len % 16) 513 printf("\n"); 514 } 515 516 if ((l = send(so, buf, len, 0)) < 0) { 517 perror("send"); 518 return NULL; 519 } 520 521 m = (struct sadb_msg *)rbuf; 522 do { 523 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 524 perror("recv"); 525 fail = 1; 526 break; 527 } 528 529 if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) { 530 warnx("invalid keymsg length"); 531 fail = 1; 532 break; 533 } 534 535 if (f_verbose) { 536 kdebug_sadb(m); 537 printf("\n"); 538 } 539 540 if (m->sadb_msg_type != SADB_DUMP) { 541 warnx("unexpected message type"); 542 fail = 1; 543 break; 544 } 545 546 if (m->sadb_msg_errno != 0) { 547 warnx("error encountered"); 548 fail = 1; 549 break; 550 } 551 552 /* match satype */ 553 if (m->sadb_msg_satype != satype) 554 continue; 555 556 pfkey_align(m, mhp); 557 pfkey_check(mhp); 558 559 /* match src */ 560 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; 561 if (saddr == NULL) 562 continue; 563 s = (struct sockaddr *)(saddr + 1); 564 for (a = srcs; a; a = a->ai_next) 565 if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0) 566 break; 567 if (a == NULL) 568 continue; 569 570 /* match dst */ 571 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; 572 if (saddr == NULL) 573 continue; 574 s = (struct sockaddr *)(saddr + 1); 575 for (a = dsts; a; a = a->ai_next) 576 if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0) 577 break; 578 if (a == NULL) 579 continue; 580 581 if (*num_spi >= max_spi) { 582 max_spi += 512; 583 spi = realloc(spi, max_spi * sizeof(u_int32_t)); 584 } 585 586 sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; 587 if (sa != NULL) 588 spi[(*num_spi)++] = (u_int32_t)ntohl(sa->sadb_sa_spi); 589 590 m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len)); 591 592 if (f_verbose) { 593 kdebug_sadb(m); 594 printf("\n"); 595 } 596 597 } while (m->sadb_msg_seq); 598 599 if (fail) { 600 free(spi); 601 *num_spi = 0; 602 return NULL; 603 } 604 605 return spi; 606} 607 608int 609sendkeymsg(buf, len) 610 char *buf; 611 size_t len; 612{ 613 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 614 ssize_t l; 615 struct sadb_msg *msg; 616 617 if (f_notreally) { 618 goto end; 619 } 620 621 { 622 struct timeval tv; 623 tv.tv_sec = 1; 624 tv.tv_usec = 0; 625 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 626 perror("setsockopt"); 627 goto end; 628 } 629 } 630 631 if (f_forever) 632 shortdump_hdr(); 633again: 634 if (f_verbose) { 635 kdebug_sadb((struct sadb_msg *)buf); 636 printf("\n"); 637 } 638 if (f_hexdump) { 639 int i; 640 for (i = 0; i < len; i++) { 641 if (i % 16 == 0) 642 printf("%08x: ", i); 643 printf("%02x ", buf[i] & 0xff); 644 if (i % 16 == 15) 645 printf("\n"); 646 } 647 if (len % 16) 648 printf("\n"); 649 } 650 651 if ((l = send(so, buf, len, 0)) < 0) { 652 perror("send"); 653 goto end; 654 } 655 656 msg = (struct sadb_msg *)rbuf; 657 do { 658 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 659 perror("recv"); 660 goto end; 661 } 662 663 if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) { 664 warnx("invalid keymsg length"); 665 break; 666 } 667 668 if (f_verbose) { 669 kdebug_sadb(msg); 670 printf("\n"); 671 } 672 if (postproc(msg, l) < 0) 673 break; 674 } while (msg->sadb_msg_errno || msg->sadb_msg_seq); 675 676 if (f_forever) { 677 fflush(stdout); 678 sleep(1); 679 goto again; 680 } 681 682end: 683 return (0); 684} 685 686int 687postproc(msg, len) 688 struct sadb_msg *msg; 689 int len; 690{ 691#ifdef HAVE_PFKEY_POLICY_PRIORITY 692 static int priority_support_check = 0; 693#endif 694 695 if (msg->sadb_msg_errno != 0) { 696 char inf[80]; 697 const char *errmsg = NULL; 698 699 if (f_mode == MODE_SCRIPT) 700 snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); 701 else 702 inf[0] = '\0'; 703 704 switch (msg->sadb_msg_errno) { 705 case ENOENT: 706 switch (msg->sadb_msg_type) { 707 case SADB_DELETE: 708 case SADB_GET: 709 case SADB_X_SPDDELETE: 710 errmsg = "No entry"; 711 break; 712 case SADB_DUMP: 713 errmsg = "No SAD entries"; 714 break; 715 case SADB_X_SPDDUMP: 716 errmsg = "No SPD entries"; 717 break; 718 } 719 break; 720 default: 721 errmsg = strerror(msg->sadb_msg_errno); 722 } 723 printf("%s%s.\n", inf, errmsg); 724 return (-1); 725 } 726 727 switch (msg->sadb_msg_type) { 728 case SADB_GET: 729 if (f_withports) 730 pfkey_sadump_withports(msg); 731 else 732 pfkey_sadump(msg); 733 break; 734 735 case SADB_DUMP: 736 /* filter out DEAD SAs */ 737 if (!f_all) { 738 caddr_t mhp[SADB_EXT_MAX + 1]; 739 struct sadb_sa *sa; 740 pfkey_align(msg, mhp); 741 pfkey_check(mhp); 742 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 743 if (sa->sadb_sa_state == SADB_SASTATE_DEAD) 744 break; 745 } 746 } 747 if (f_forever) { 748 /* TODO: f_withports */ 749 shortdump(msg); 750 } else { 751 if (f_withports) 752 pfkey_sadump_withports(msg); 753 else 754 pfkey_sadump(msg); 755 } 756 break; 757 758 case SADB_X_SPDGET: 759 if (f_withports) 760 pfkey_spdump_withports(msg); 761 else 762 pfkey_spdump(msg); 763 break; 764 765 case SADB_X_SPDDUMP: 766 if (f_withports) 767 pfkey_spdump_withports(msg); 768 else 769 pfkey_spdump(msg); 770 break; 771#ifdef HAVE_PFKEY_POLICY_PRIORITY 772 case SADB_X_SPDADD: 773 if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 774 msg->sadb_msg_pid == getpid() && !priority_support_check) { 775 priority_support_check = 1; 776 if (!verifypriority(msg)) 777 printf ("WARNING: Kernel does not support policy priorities\n"); 778 } 779 break; 780#endif 781 } 782 783 return (0); 784} 785 786#ifdef HAVE_PFKEY_POLICY_PRIORITY 787int 788verifypriority(m) 789 struct sadb_msg *m; 790{ 791 caddr_t mhp[SADB_EXT_MAX + 1]; 792 struct sadb_x_policy *xpl; 793 794 /* check pfkey message. */ 795 if (pfkey_align(m, mhp)) { 796 printf("(%s\n", ipsec_strerror()); 797 return 0; 798 } 799 if (pfkey_check(mhp)) { 800 printf("%s\n", ipsec_strerror()); 801 return 0; 802 } 803 804 xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY]; 805 806 if (xpl == NULL) { 807 printf("no X_POLICY extension.\n"); 808 return 0; 809 } 810 811 /* now make sure they match */ 812 if (last_priority != xpl->sadb_x_policy_priority) 813 return 0; 814 815 return 1; 816} 817#endif 818 819int 820fileproc(filename) 821 const char *filename; 822{ 823 int fd; 824 ssize_t len, l; 825 u_char *p, *ep; 826 struct sadb_msg *msg; 827 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 828 829 fd = open(filename, O_RDONLY); 830 if (fd < 0) 831 return -1; 832 833 l = 0; 834 while (1) { 835 len = read(fd, rbuf + l, sizeof(rbuf) - l); 836 if (len < 0) { 837 close(fd); 838 return -1; 839 } else if (len == 0) 840 break; 841 l += len; 842 } 843 844 if (l < sizeof(struct sadb_msg)) { 845 close(fd); 846 errno = EINVAL; 847 return -1; 848 } 849 close(fd); 850 851 p = rbuf; 852 ep = rbuf + l; 853 854 while (p < ep) { 855 msg = (struct sadb_msg *)p; 856 len = PFKEY_UNUNIT64(msg->sadb_msg_len); 857 if (f_verbose) { 858 kdebug_sadb((struct sadb_msg *)msg); 859 printf("\n"); 860 } 861 postproc(msg, len); 862 p += len; 863 } 864 865 return (0); 866} 867 868 869/*------------------------------------------------------------*/ 870static const char *satype[] = { 871 NULL, NULL, "ah", "esp" 872}; 873static const char *sastate[] = { 874 "L", "M", "D", "d" 875}; 876static const char *ipproto[] = { 877/*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 878 NULL, "tcp", NULL, "egp", NULL, 879/*10*/ NULL, NULL, NULL, NULL, NULL, 880 NULL, NULL, "udp", NULL, NULL, 881/*20*/ NULL, NULL, "idp", NULL, NULL, 882 NULL, NULL, NULL, NULL, "tp", 883/*30*/ NULL, NULL, NULL, NULL, NULL, 884 NULL, NULL, NULL, NULL, NULL, 885/*40*/ NULL, "ip6", NULL, "rt6", "frag6", 886 NULL, "rsvp", "gre", NULL, NULL, 887/*50*/ "esp", "ah", NULL, NULL, NULL, 888 NULL, NULL, NULL, "icmp6", "none", 889/*60*/ "dst6", 890}; 891 892#define STR_OR_ID(x, tab) \ 893 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) 894 895const char * 896numstr(x) 897 int x; 898{ 899 static char buf[20]; 900 snprintf(buf, sizeof(buf), "#%d", x); 901 return buf; 902} 903 904void 905shortdump_hdr() 906{ 907 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", 908 "time", "p", "s", "spi", "ltime", "src", "dst"); 909} 910 911void 912shortdump(msg) 913 struct sadb_msg *msg; 914{ 915 caddr_t mhp[SADB_EXT_MAX + 1]; 916 char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; 917 struct sadb_sa *sa; 918 struct sadb_address *saddr; 919 struct sadb_lifetime *lts, *lth, *ltc; 920 struct sockaddr *s; 921 u_int t; 922 time_t cur = time(0); 923 924 pfkey_align(msg, mhp); 925 pfkey_check(mhp); 926 927 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); 928 929 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); 930 931 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 932 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); 933 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); 934 } else 935 printf("%-1s %-8s", "?", "?"); 936 937 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 938 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 939 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 940 if (lts && lth && ltc) { 941 if (ltc->sadb_lifetime_addtime == 0) 942 t = (u_long)0; 943 else 944 t = (u_long)(cur - ltc->sadb_lifetime_addtime); 945 if (t >= 1000) 946 strlcpy(buf, " big/", sizeof(buf)); 947 else 948 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); 949 printf("%s", buf); 950 951 t = (u_long)lth->sadb_lifetime_addtime; 952 if (t >= 1000) 953 strlcpy(buf, "big", sizeof(buf)); 954 else 955 snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); 956 printf("%s", buf); 957 } else 958 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ 959 960 printf(" "); 961 962 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { 963 if (saddr->sadb_address_proto) 964 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 965 s = (struct sockaddr *)(saddr + 1); 966 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 967 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 968 if (strcmp(pbuf, "0") != 0) 969 printf("%s[%s]", buf, pbuf); 970 else 971 printf("%s", buf); 972 } else 973 printf("?"); 974 975 printf(" -> "); 976 977 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { 978 if (saddr->sadb_address_proto) 979 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 980 981 s = (struct sockaddr *)(saddr + 1); 982 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 983 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 984 if (strcmp(pbuf, "0") != 0) 985 printf("%s[%s]", buf, pbuf); 986 else 987 printf("%s", buf); 988 } else 989 printf("?"); 990 991 printf("\n"); 992} 993 994/* From: tcpdump(1):gmt2local.c and util.c */ 995/* 996 * Print the timestamp 997 */ 998static void 999printdate() 1000{ 1001 struct timeval tp; 1002 int s; 1003 1004 if (gettimeofday(&tp, NULL) == -1) { 1005 perror("gettimeofday"); 1006 return; 1007 } 1008 1009 if (f_tflag == 1) { 1010 /* Default */ 1011 s = (tp.tv_sec + thiszone ) % 86400; 1012 (void)printf("%02d:%02d:%02d.%06u ", 1013 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); 1014 } else if (f_tflag > 1) { 1015 /* Unix timeval style */ 1016 (void)printf("%u.%06u ", 1017 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); 1018 } 1019 1020 printf("\n"); 1021} 1022 1023/* 1024 * Returns the difference between gmt and local time in seconds. 1025 * Use gmtime() and localtime() to keep things simple. 1026 */ 1027int32_t 1028gmt2local(time_t t) 1029{ 1030 register int dt, dir; 1031 register struct tm *gmt, *loc; 1032 struct tm sgmt; 1033 1034 if (t == 0) 1035 t = time(NULL); 1036 gmt = &sgmt; 1037 *gmt = *gmtime(&t); 1038 loc = localtime(&t); 1039 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + 1040 (loc->tm_min - gmt->tm_min) * 60; 1041 1042 /* 1043 * If the year or julian day is different, we span 00:00 GMT 1044 * and must add or subtract a day. Check the year first to 1045 * avoid problems when the julian day wraps. 1046 */ 1047 dir = loc->tm_year - gmt->tm_year; 1048 if (dir == 0) 1049 dir = loc->tm_yday - gmt->tm_yday; 1050 dt += dir * 24 * 60 * 60; 1051 1052 return (dt); 1053} 1054