1/* $NetBSD: racoonctl.c,v 1.7.6.2 2009/04/20 13:32:57 tteras Exp $ */ 2 3/* Id: racoonctl.c,v 1.11 2006/04/06 17:06:25 manubsd Exp */ 4 5/* 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "config.h" 35 36#include <sys/types.h> 37#include <sys/param.h> 38#include <sys/socket.h> 39#include <sys/un.h> 40 41#include <netinet/in.h> 42#include <arpa/inet.h> 43#include <net/pfkeyv2.h> 44 45#include <stdlib.h> 46#include <stdio.h> 47#include <string.h> 48#include <errno.h> 49#if TIME_WITH_SYS_TIME 50# include <sys/time.h> 51# include <time.h> 52#else 53# if HAVE_SYS_TIME_H 54# include <sys/time.h> 55# else 56# include <time.h> 57# endif 58#endif 59#include <netdb.h> 60#ifdef HAVE_UNISTD_H 61#include <unistd.h> 62#endif 63#include <err.h> 64#include <sys/ioctl.h> 65#include <resolv.h> 66 67#include "var.h" 68#include "vmbuf.h" 69#include "misc.h" 70#include "gcmalloc.h" 71 72#include "racoonctl.h" 73#include "admin.h" 74#include "schedule.h" 75#include "handler.h" 76#include "sockmisc.h" 77#include "vmbuf.h" 78#include "plog.h" 79#include "isakmp_var.h" 80#include "isakmp.h" 81#include "isakmp_xauth.h" 82#include "isakmp_cfg.h" 83#include "isakmp_unity.h" 84#include "ipsec_doi.h" 85#include "evt.h" 86 87char *adminsock_path = ADMINSOCK_PATH; 88 89static void usage __P((void)); 90static vchar_t *get_combuf __P((int, char **)); 91static int handle_recv __P((vchar_t *)); 92static vchar_t *f_reload __P((int, char **)); 93static vchar_t *f_getsched __P((int, char **)); 94static vchar_t *f_getsa __P((int, char **)); 95static vchar_t *f_flushsa __P((int, char **)); 96static vchar_t *f_deletesa __P((int, char **)); 97static vchar_t *f_exchangesa __P((int, char **)); 98static vchar_t *f_vpnc __P((int, char **)); 99static vchar_t *f_vpnd __P((int, char **)); 100static vchar_t *f_getevt __P((int, char **)); 101#ifdef ENABLE_HYBRID 102static vchar_t *f_logoutusr __P((int, char **)); 103#endif 104 105struct cmd_tag { 106 vchar_t *(*func) __P((int, char **)); 107 int cmd; 108 char *str; 109} cmdtab[] = { 110 { f_reload, ADMIN_RELOAD_CONF, "reload-config" }, 111 { f_reload, ADMIN_RELOAD_CONF, "rc" }, 112 { f_getsched, ADMIN_SHOW_SCHED, "show-schedule" }, 113 { f_getsched, ADMIN_SHOW_SCHED, "sc" }, 114 { f_getsa, ADMIN_SHOW_SA, "show-sa" }, 115 { f_getsa, ADMIN_SHOW_SA, "ss" }, 116 { f_flushsa, ADMIN_FLUSH_SA, "flush-sa" }, 117 { f_flushsa, ADMIN_FLUSH_SA, "fs" }, 118 { f_deletesa, ADMIN_DELETE_SA, "delete-sa" }, 119 { f_deletesa, ADMIN_DELETE_SA, "ds" }, 120 { f_exchangesa, ADMIN_ESTABLISH_SA, "establish-sa" }, 121 { f_exchangesa, ADMIN_ESTABLISH_SA, "es" }, 122 { f_vpnc, ADMIN_ESTABLISH_SA, "vpn-connect" }, 123 { f_vpnc, ADMIN_ESTABLISH_SA, "vc" }, 124 { f_vpnd, ADMIN_DELETE_ALL_SA_DST,"vpn-disconnect" }, 125 { f_vpnd, ADMIN_DELETE_ALL_SA_DST,"vd" }, 126 { f_getevt, ADMIN_SHOW_EVT, "show-event" }, 127 { f_getevt, ADMIN_SHOW_EVT, "se" }, 128#ifdef ENABLE_HYBRID 129 { f_logoutusr, ADMIN_LOGOUT_USER, "logout-user" }, 130 { f_logoutusr, ADMIN_LOGOUT_USER, "lu" }, 131#endif 132 { NULL, 0, NULL }, 133}; 134 135struct evtmsg { 136 int type; 137 char *msg; 138 enum { UNSPEC, ERROR, INFO } level; 139} evtmsg[] = { 140 { EVTT_PHASE1_UP, "Phase 1 established", INFO }, 141 { EVTT_PHASE1_DOWN, "Phase 1 deleted", INFO }, 142 { EVTT_XAUTH_SUCCESS, "Xauth exchange passed", INFO }, 143 { EVTT_ISAKMP_CFG_DONE, "ISAKMP mode config done", INFO }, 144 { EVTT_PHASE2_UP, "Phase 2 established", INFO }, 145 { EVTT_PHASE2_DOWN, "Phase 2 deleted", INFO }, 146 { EVTT_DPD_TIMEOUT, "Peer not reachable anymore", ERROR }, 147 { EVTT_PEER_NO_RESPONSE, "Peer not responding", ERROR }, 148 { EVTT_PEER_DELETE, "Peer terminated security association", ERROR }, 149 { EVTT_RACOON_QUIT, "Raccon terminated", ERROR }, 150 { EVTT_OVERFLOW, "Event queue overflow", ERROR }, 151 { EVTT_XAUTH_FAILED, "Xauth exchange failed", ERROR }, 152 { EVTT_PEERPH1AUTH_FAILED, "Peer failed phase 1 authentication " 153 "(certificate problem?)", ERROR }, 154 { EVTT_PEERPH1_NOPROP, "Peer failed phase 1 initiation " 155 "(proposal problem?)", ERROR }, 156 { 0, NULL, UNSPEC }, 157 { EVTT_NO_ISAKMP_CFG, "No need for ISAKMP mode config ", INFO }, 158}; 159 160static int get_proto __P((char *)); 161static vchar_t *get_index __P((int, char **)); 162static int get_family __P((char *)); 163static vchar_t *get_comindexes __P((int, int, char **)); 164static int get_comindex __P((char *, char **, char **, char **)); 165static int get_ulproto __P((char *)); 166 167struct proto_tag { 168 int proto; 169 char *str; 170} prototab[] = { 171 { ADMIN_PROTO_ISAKMP, "isakmp" }, 172 { ADMIN_PROTO_IPSEC, "ipsec" }, 173 { ADMIN_PROTO_AH, "ah" }, 174 { ADMIN_PROTO_ESP, "esp" }, 175 { ADMIN_PROTO_INTERNAL, "internal" }, 176 { 0, NULL }, 177}; 178 179struct ulproto_tag { 180 int ul_proto; 181 char *str; 182} ulprototab[] = { 183 { 0, "any" }, 184 { IPPROTO_ICMP, "icmp" }, 185 { IPPROTO_TCP, "tcp" }, 186 { IPPROTO_UDP, "udp" }, 187 { 0, NULL }, 188}; 189 190int so; 191 192static char _addr1_[NI_MAXHOST], _addr2_[NI_MAXHOST]; 193 194char *pname; 195int long_format = 0; 196 197#define EVTF_NONE 0x0000 /* Ignore any events */ 198#define EVTF_LOOP 0x0001 /* Loop awaiting for new events */ 199#define EVTF_CFG_STOP 0x0002 /* Stop after ISAKMP mode config */ 200#define EVTF_CFG 0x0004 /* Print ISAKMP mode config info */ 201#define EVTF_ALL 0x0008 /* Print any events */ 202#define EVTF_PURGE 0x0010 /* Print all available events */ 203#define EVTF_PH1DOWN_STOP 0x0020 /* Stop when phase 1 SA gets down */ 204#define EVTF_PH1DOWN 0x0040 /* Print that phase 1 SA got down */ 205#define EVTF_ERR 0x0080 /* Print any error */ 206#define EVTF_ERR_STOP 0x0100 /* Stop on any error */ 207 208int evt_filter = EVTF_NONE; 209time_t evt_start; 210 211void dump_isakmp_sa __P((char *, int)); 212void dump_internal __P((char *, int)); 213char *pindex_isakmp __P((isakmp_index *)); 214void print_schedule __P((caddr_t, int)); 215void print_evt __P((caddr_t, int)); 216void print_cfg __P((caddr_t, int)); 217void print_err __P((caddr_t, int)); 218void print_ph1down __P((caddr_t, int)); 219void print_ph1up __P((caddr_t, int)); 220int evt_poll __P((void)); 221char * fixed_addr __P((char *, char *, int)); 222 223static void 224usage() 225{ 226 printf( 227"Usage:\n" 228" %s reload-config\n" 229" %s [-l [-l]] show-sa [protocol]\n" 230" %s flush-sa [protocol]\n" 231" %s delete-sa <saopts>\n" 232" %s establish-sa [-u identity] <saopts>\n" 233" %s vpn-connect [-u identity] vpn_gateway\n" 234" %s vpn-disconnect vpn_gateway\n" 235"\n" 236" <protocol>: \"isakmp\", \"esp\" or \"ah\".\n" 237" In the case of \"show-sa\" or \"flush-sa\", you can use \"ipsec\".\n" 238"\n" 239" <saopts>: \"isakmp\" <family> <src> <dst>\n" 240" : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n" 241" <ul_proto>\n" 242" <family>: \"inet\" or \"inet6\"\n" 243" <ul_proto>: \"icmp\", \"tcp\", \"udp\" or \"any\"\n", 244 pname, pname, pname, pname, pname, pname, pname); 245} 246 247/* 248 * Check for proper racoonctl interface 249 */ 250#if ((RACOONCTL_INTERFACE_MAJOR != 1) || (RACOONCTL_INTERFACE < 20041230)) 251#error "Incompatible racoonctl interface" 252#endif 253 254int 255main(ac, av) 256 int ac; 257 char **av; 258{ 259 vchar_t *combuf; 260 int c; 261 262 pname = *av; 263 264 /* 265 * Check for proper racoonctl interface 266 */ 267 if ((racoonctl_interface_major != RACOONCTL_INTERFACE_MAJOR) || 268 (racoonctl_interface < RACOONCTL_INTERFACE)) 269 errx(1, "Incompatible racoonctl interface"); 270 271#ifdef __linux__ 272 /* 273 * Disable GNU extensions that will prevent racoonct vc -u login 274 * from working (GNU getopt(3) does not like options after vc) 275 */ 276 setenv("POSIXLY_CORRECT", "1", 0); 277#endif 278 while ((c = getopt(ac, av, "lds:")) != -1) { 279 switch(c) { 280 case 'l': 281 long_format++; 282 break; 283 284 case 'd': 285 loglevel++; 286 break; 287 288 case 's': 289 adminsock_path = optarg; 290 break; 291 292 default: 293 usage(); 294 exit(0); 295 } 296 } 297 298 ac -= optind; 299 av += optind; 300 301 combuf = get_combuf(ac, av); 302 if (!combuf) 303 err(1, "kmpstat"); 304 305 if (loglevel) 306 racoon_hexdump(combuf, ((struct admin_com *)combuf)->ac_len); 307 308 com_init(); 309 310 if (com_send(combuf) != 0) 311 goto bad; 312 313 vfree(combuf); 314 315 if (com_recv(&combuf) != 0) 316 goto bad; 317 if (handle_recv(combuf) != 0) 318 goto bad; 319 320 vfree(combuf); 321 322 if (evt_filter != EVTF_NONE) 323 if (evt_poll() != 0) 324 goto bad; 325 326 exit(0); 327 328 bad: 329 exit(1); 330} 331 332int 333evt_poll(void) { 334 struct timeval tv; 335 vchar_t *recvbuf; 336 vchar_t *sendbuf; 337 338 if ((sendbuf = f_getevt(0, NULL)) == NULL) 339 errx(1, "Cannot make combuf"); 340 341 342 while (evt_filter & (EVTF_LOOP|EVTF_PURGE)) { 343 /* handle_recv closes the socket time, so open it each time */ 344 com_init(); 345 346 if (com_send(sendbuf) != 0) 347 errx(1, "Cannot send combuf"); 348 349 if (com_recv(&recvbuf) == 0) { 350 handle_recv(recvbuf); 351 vfree(recvbuf); 352 } 353 354 tv.tv_sec = 0; 355 tv.tv_usec = 10; 356 (void)select(0, NULL, NULL, NULL, &tv); 357 } 358 359 vfree(sendbuf); 360 return 0; 361} 362 363/* %%% */ 364/* 365 * return command buffer. 366 */ 367static vchar_t * 368get_combuf(ac, av) 369 int ac; 370 char **av; 371{ 372 struct cmd_tag *cp; 373 374 if (ac == 0) { 375 usage(); 376 exit(0); 377 } 378 379 /* checking the string of command. */ 380 for (cp = &cmdtab[0]; cp->str; cp++) { 381 if (strcmp(*av, cp->str) == 0) { 382 break; 383 } 384 } 385 if (!cp->str) { 386 printf("Invalid command [%s]\n", *av); 387 errno = EINVAL; 388 return NULL; 389 } 390 391 ac--; 392 av++; 393 return (cp->func)(ac, av); 394} 395 396static vchar_t * 397f_reload(ac, av) 398 int ac; 399 char **av; 400{ 401 vchar_t *buf; 402 struct admin_com *head; 403 404 buf = vmalloc(sizeof(*head)); 405 if (buf == NULL) 406 errx(1, "not enough core"); 407 408 head = (struct admin_com *)buf->v; 409 head->ac_len = buf->l; 410 head->ac_cmd = ADMIN_RELOAD_CONF; 411 head->ac_errno = 0; 412 head->ac_proto = 0; 413 414 return buf; 415} 416 417static vchar_t * 418f_getevt(ac, av) 419 int ac; 420 char **av; 421{ 422 vchar_t *buf; 423 struct admin_com *head; 424 425 /* 426 * There are 3 ways of getting here 427 * 1) racoonctl vc => evt_filter = (EVTF_LOOP|EVTF_CFG| ... ) 428 * 2) racoonctl es => evt_filter = EVTF_NONE 429 * 3) racoonctl es -l => evt_filter = EVTF_LOOP 430 * Catch the second case: show-event is here to purge all 431 */ 432 if (evt_filter == EVTF_NONE) 433 evt_filter = (EVTF_ALL|EVTF_PURGE); 434 435 if ((ac >= 1) && (strcmp(av[0], "-l") == 0)) 436 evt_filter |= EVTF_LOOP; 437 438 if (ac >= 2) 439 errx(1, "too many arguments"); 440 441 buf = vmalloc(sizeof(*head)); 442 if (buf == NULL) 443 errx(1, "not enough core"); 444 445 head = (struct admin_com *)buf->v; 446 head->ac_len = buf->l; 447 head->ac_cmd = ADMIN_SHOW_EVT; 448 head->ac_errno = 0; 449 head->ac_proto = 0; 450 451 return buf; 452} 453 454static vchar_t * 455f_getsched(ac, av) 456 int ac; 457 char **av; 458{ 459 vchar_t *buf; 460 struct admin_com *head; 461 462 buf = vmalloc(sizeof(*head)); 463 if (buf == NULL) 464 errx(1, "not enough core"); 465 466 head = (struct admin_com *)buf->v; 467 head->ac_len = buf->l; 468 head->ac_cmd = ADMIN_SHOW_SCHED; 469 head->ac_errno = 0; 470 head->ac_proto = 0; 471 472 return buf; 473} 474 475static vchar_t * 476f_getsa(ac, av) 477 int ac; 478 char **av; 479{ 480 vchar_t *buf; 481 struct admin_com *head; 482 int proto; 483 484 /* need protocol */ 485 if (ac != 1) 486 errx(1, "insufficient arguments"); 487 proto = get_proto(*av); 488 if (proto == -1) 489 errx(1, "unknown protocol %s", *av); 490 491 buf = vmalloc(sizeof(*head)); 492 if (buf == NULL) 493 errx(1, "not enough core"); 494 495 head = (struct admin_com *)buf->v; 496 head->ac_len = buf->l; 497 head->ac_cmd = ADMIN_SHOW_SA; 498 head->ac_errno = 0; 499 head->ac_proto = proto; 500 501 return buf; 502} 503 504static vchar_t * 505f_flushsa(ac, av) 506 int ac; 507 char **av; 508{ 509 vchar_t *buf; 510 struct admin_com *head; 511 int proto; 512 513 /* need protocol */ 514 if (ac != 1) 515 errx(1, "insufficient arguments"); 516 proto = get_proto(*av); 517 if (proto == -1) 518 errx(1, "unknown protocol %s", *av); 519 520 buf = vmalloc(sizeof(*head)); 521 if (buf == NULL) 522 errx(1, "not enough core"); 523 524 head = (struct admin_com *)buf->v; 525 head->ac_len = buf->l; 526 head->ac_cmd = ADMIN_FLUSH_SA; 527 head->ac_errno = 0; 528 head->ac_proto = proto; 529 530 return buf; 531} 532 533static vchar_t * 534f_deletesa(ac, av) 535 int ac; 536 char **av; 537{ 538 vchar_t *buf, *index; 539 struct admin_com *head; 540 int proto; 541 542 /* need protocol */ 543 if (ac < 1) 544 errx(1, "insufficient arguments"); 545 proto = get_proto(*av); 546 if (proto == -1) 547 errx(1, "unknown protocol %s", *av); 548 549 /* get index(es) */ 550 av++; 551 ac--; 552 switch (proto) { 553 case ADMIN_PROTO_ISAKMP: 554 index = get_index(ac, av); 555 if (index == NULL) 556 return NULL; 557 break; 558 case ADMIN_PROTO_AH: 559 case ADMIN_PROTO_ESP: 560 index = get_index(ac, av); 561 if (index == NULL) 562 return NULL; 563 break; 564 default: 565 errno = EPROTONOSUPPORT; 566 return NULL; 567 } 568 569 buf = vmalloc(sizeof(*head) + index->l); 570 if (buf == NULL) 571 goto out; 572 573 head = (struct admin_com *)buf->v; 574 head->ac_len = buf->l + index->l; 575 head->ac_cmd = ADMIN_DELETE_SA; 576 head->ac_errno = 0; 577 head->ac_proto = proto; 578 579 memcpy(buf->v+sizeof(*head), index->v, index->l); 580 581out: 582 if (index != NULL) 583 vfree(index); 584 585 return buf; 586} 587 588static vchar_t * 589f_deleteallsadst(ac, av) 590 int ac; 591 char **av; 592{ 593 vchar_t *buf, *index; 594 struct admin_com *head; 595 int proto; 596 597 /* need protocol */ 598 if (ac < 1) 599 errx(1, "insufficient arguments"); 600 proto = get_proto(*av); 601 if (proto == -1) 602 errx(1, "unknown protocol %s", *av); 603 604 /* get index(es) */ 605 av++; 606 ac--; 607 switch (proto) { 608 case ADMIN_PROTO_ISAKMP: 609 index = get_index(ac, av); 610 if (index == NULL) 611 return NULL; 612 break; 613 case ADMIN_PROTO_AH: 614 case ADMIN_PROTO_ESP: 615 index = get_index(ac, av); 616 if (index == NULL) 617 return NULL; 618 break; 619 default: 620 errno = EPROTONOSUPPORT; 621 return NULL; 622 } 623 624 buf = vmalloc(sizeof(*head) + index->l); 625 if (buf == NULL) 626 goto out; 627 628 head = (struct admin_com *)buf->v; 629 head->ac_len = buf->l + index->l; 630 head->ac_cmd = ADMIN_DELETE_ALL_SA_DST; 631 head->ac_errno = 0; 632 head->ac_proto = proto; 633 634 memcpy(buf->v+sizeof(*head), index->v, index->l); 635 636out: 637 if (index != NULL) 638 vfree(index); 639 640 return buf; 641} 642 643static vchar_t * 644f_exchangesa(ac, av) 645 int ac; 646 char **av; 647{ 648 vchar_t *buf, *index; 649 struct admin_com *head; 650 int proto; 651 int cmd = ADMIN_ESTABLISH_SA; 652 size_t com_len = 0; 653 char *id = NULL; 654 char *key = NULL; 655 struct admin_com_psk *acp; 656 657 if (ac < 1) 658 errx(1, "insufficient arguments"); 659 660 /* Optional -u identity */ 661 if (strcmp(av[0], "-u") == 0) { 662 if (ac < 2) 663 errx(1, "-u require an argument"); 664 665 id = av[1]; 666 if ((key = getpass("Password: ")) == NULL) 667 errx(1, "getpass() failed: %s", strerror(errno)); 668 669 com_len += sizeof(*acp) + strlen(id) + 1 + strlen(key) + 1; 670 cmd = ADMIN_ESTABLISH_SA_PSK; 671 672 av += 2; 673 ac -= 2; 674 } 675 676 /* need protocol */ 677 if (ac < 1) 678 errx(1, "insufficient arguments"); 679 if ((proto = get_proto(*av)) == -1) 680 errx(1, "unknown protocol %s", *av); 681 682 /* get index(es) */ 683 av++; 684 ac--; 685 switch (proto) { 686 case ADMIN_PROTO_ISAKMP: 687 index = get_index(ac, av); 688 if (index == NULL) 689 return NULL; 690 break; 691 case ADMIN_PROTO_AH: 692 case ADMIN_PROTO_ESP: 693 index = get_index(ac, av); 694 if (index == NULL) 695 return NULL; 696 break; 697 default: 698 errno = EPROTONOSUPPORT; 699 return NULL; 700 } 701 702 com_len += sizeof(*head) + index->l; 703 if ((buf = vmalloc(com_len)) == NULL) 704 errx(1, "Cannot allocate buffer"); 705 706 head = (struct admin_com *)buf->v; 707 head->ac_len = buf->l; 708 head->ac_cmd = cmd; 709 head->ac_errno = 0; 710 head->ac_proto = proto; 711 712 memcpy(buf->v+sizeof(*head), index->v, index->l); 713 714 if (id && key) { 715 char *data; 716 acp = (struct admin_com_psk *) 717 (buf->v + sizeof(*head) + index->l); 718 719 acp->id_type = IDTYPE_USERFQDN; 720 acp->id_len = strlen(id) + 1; 721 acp->key_len = strlen(key) + 1; 722 723 data = (char *)(acp + 1); 724 strcpy(data, id); 725 726 data = (char *)(data + acp->id_len); 727 strcpy(data, key); 728 } 729 730 vfree(index); 731 732 return buf; 733} 734 735static vchar_t * 736f_vpnc(ac, av) 737 int ac; 738 char **av; 739{ 740 char *nav[] = {NULL, NULL, NULL, NULL, NULL, NULL}; 741 int nac = 0; 742 char *isakmp = "isakmp"; 743 char *inet = "inet"; 744 char *srcaddr; 745 struct addrinfo hints, *res; 746 struct sockaddr *src; 747 char *idx; 748 749 if (ac < 1) 750 errx(1, "insufficient arguments"); 751 752 evt_filter = (EVTF_LOOP|EVTF_CFG|EVTF_CFG_STOP|EVTF_ERR|EVTF_ERR_STOP); 753 time(&evt_start); 754 755 /* Optional -u identity */ 756 if (strcmp(av[0], "-u") == 0) { 757 if (ac < 2) 758 errx(1, "-u require an argument"); 759 760 nav[nac++] = av[0]; 761 nav[nac++] = av[1]; 762 763 ac -= 2; 764 av += 2; 765 } 766 767 if (ac < 1) 768 errx(1, "VPN gateway required"); 769 if (ac > 1) 770 warnx("Extra arguments"); 771 772 /* 773 * Find the source address 774 */ 775 memset(&hints, 0, sizeof(hints)); 776 hints.ai_family = PF_UNSPEC; 777 hints.ai_socktype = SOCK_DGRAM; 778 if (getaddrinfo(av[0], "4500", &hints, &res) != 0) 779 errx(1, "Cannot resolve destination address"); 780 781 if ((src = getlocaladdr(res->ai_addr)) == NULL) 782 errx(1, "cannot find source address"); 783 784 if ((srcaddr = saddr2str(src)) == NULL) 785 errx(1, "cannot read source address"); 786 787 /* We get "ip[port]" strip the port */ 788 if ((idx = index(srcaddr, '[')) == NULL) 789 errx(1, "unexpected source address format"); 790 *idx = '\0'; 791 792 nav[nac++] = isakmp; 793 nav[nac++] = inet; 794 nav[nac++] = srcaddr; 795 nav[nac++] = av[0]; 796 797 return f_exchangesa(nac, nav); 798} 799 800static vchar_t * 801f_vpnd(ac, av) 802 int ac; 803 char **av; 804{ 805 char *nav[] = {NULL, NULL, NULL, NULL}; 806 int nac = 0; 807 char *isakmp = "isakmp"; 808 char *inet = "inet"; 809 char *anyaddr = "0.0.0.0"; 810 char *idx; 811 812 if (ac < 1) 813 errx(1, "VPN gateway required"); 814 if (ac > 1) 815 warnx("Extra arguments"); 816 817 evt_filter = 818 (EVTF_PH1DOWN|EVTF_PH1DOWN_STOP|EVTF_LOOP|EVTF_ERR|EVTF_ERR_STOP); 819 820 nav[nac++] = isakmp; 821 nav[nac++] = inet; 822 nav[nac++] = anyaddr; 823 nav[nac++] = av[0]; 824 825 return f_deleteallsadst(nac, nav); 826} 827 828#ifdef ENABLE_HYBRID 829static vchar_t * 830f_logoutusr(ac, av) 831 int ac; 832 char **av; 833{ 834 vchar_t *buf; 835 struct admin_com *head; 836 char *user; 837 size_t userlen; 838 839 /* need username */ 840 if (ac < 1) 841 errx(1, "insufficient arguments"); 842 user = av[0]; 843 userlen = strlen(user); 844 if ((user == NULL) || (userlen > LOGINLEN)) 845 errx(1, "bad login (too long?)"); 846 847 buf = vmalloc(sizeof(*head) + userlen); 848 if (buf == NULL) 849 return NULL; 850 851 head = (struct admin_com *)buf->v; 852 head->ac_len = buf->l; 853 head->ac_cmd = ADMIN_LOGOUT_USER; 854 head->ac_errno = 0; 855 head->ac_proto = 0; 856 857 strncpy((char *)(head + 1), user, userlen); 858 859 return buf; 860} 861#endif /* ENABLE_HYBRID */ 862 863 864static int 865get_proto(str) 866 char *str; 867{ 868 struct proto_tag *cp; 869 870 if (str == NULL) { 871 errno = EINVAL; 872 return -1; 873 } 874 875 /* checking the string of command. */ 876 for (cp = &prototab[0]; cp->str; cp++) { 877 if (strcmp(str, cp->str) == 0) 878 return cp->proto; 879 } 880 881 errno = EINVAL; 882 return -1; 883} 884 885static vchar_t * 886get_index(ac, av) 887 int ac; 888 char **av; 889{ 890 int family; 891 892 if (ac != 3 && ac != 4) { 893 errno = EINVAL; 894 return NULL; 895 } 896 897 /* checking the string of family */ 898 family = get_family(*av); 899 if (family == -1) 900 return NULL; 901 av++; 902 ac--; 903 904 return get_comindexes(family, ac, av); 905} 906 907static int 908get_family(str) 909 char *str; 910{ 911 if (strcmp("inet", str) == 0) 912 return AF_INET; 913#ifdef INET6 914 else if (strcmp("inet6", str) == 0) 915 return AF_INET6; 916#endif 917 errno = EAFNOSUPPORT; 918 return -1; 919} 920 921static vchar_t * 922get_comindexes(family, ac, av) 923 int family; 924 int ac; 925 char **av; 926{ 927 vchar_t *buf; 928 struct admin_com_indexes *ci; 929 char *p_name = NULL, *p_port = NULL; 930 char *p_prefs = NULL, *p_prefd = NULL; 931 struct sockaddr *src = NULL, *dst = NULL; 932 int ulproto; 933 934 if (ac != 2 && ac != 3) { 935 errno = EINVAL; 936 return NULL; 937 } 938 939 if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1) 940 goto bad; 941 src = get_sockaddr(family, p_name, p_port); 942 if (p_name) { 943 racoon_free(p_name); 944 p_name = NULL; 945 } 946 if (p_port) { 947 racoon_free(p_port); 948 p_port = NULL; 949 } 950 if (src == NULL) 951 goto bad; 952 av++; 953 ac--; 954 if (get_comindex(*av, &p_name, &p_port, &p_prefd) == -1) 955 goto bad; 956 dst = get_sockaddr(family, p_name, p_port); 957 if (p_name) { 958 racoon_free(p_name); 959 p_name = NULL; 960 } 961 if (p_port) { 962 racoon_free(p_port); 963 p_port = NULL; 964 } 965 if (dst == NULL) 966 goto bad; 967 968 buf = vmalloc(sizeof(*ci)); 969 if (buf == NULL) 970 goto bad; 971 972 av++; 973 ac--; 974 if(ac){ 975 ulproto = get_ulproto(*av); 976 if (ulproto == -1) 977 goto bad; 978 }else 979 ulproto=0; 980 981 ci = (struct admin_com_indexes *)buf->v; 982 if(p_prefs) 983 ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */ 984 else 985 ci->prefs = 32; 986 if(p_prefd) 987 ci->prefd = (u_int8_t)atoi(p_prefd); /* XXX should be handled error. */ 988 else 989 ci->prefd = 32; 990 ci->ul_proto = ulproto; 991 memcpy(&ci->src, src, sysdep_sa_len(src)); 992 memcpy(&ci->dst, dst, sysdep_sa_len(dst)); 993 994 if (p_name) 995 racoon_free(p_name); 996 997 return buf; 998 999 bad: 1000 if (p_name) 1001 racoon_free(p_name); 1002 if (p_port) 1003 racoon_free(p_port); 1004 if (p_prefs) 1005 racoon_free(p_prefs); 1006 if (p_prefd) 1007 racoon_free(p_prefd); 1008 return NULL; 1009} 1010 1011static int 1012get_comindex(str, name, port, pref) 1013 char *str, **name, **port, **pref; 1014{ 1015 char *p; 1016 1017 *name = *port = *pref = NULL; 1018 1019 *name = racoon_strdup(str); 1020 STRDUP_FATAL(*name); 1021 p = strpbrk(*name, "/["); 1022 if (p != NULL) { 1023 if (*(p + 1) == '\0') 1024 goto bad; 1025 if (*p == '/') { 1026 *p = '\0'; 1027 *pref = racoon_strdup(p + 1); 1028 STRDUP_FATAL(*pref); 1029 p = strchr(*pref, '['); 1030 if (p != NULL) { 1031 if (*(p + 1) == '\0') 1032 goto bad; 1033 *p = '\0'; 1034 *port = racoon_strdup(p + 1); 1035 STRDUP_FATAL(*port); 1036 p = strchr(*pref, ']'); 1037 if (p == NULL) 1038 goto bad; 1039 *p = '\0'; 1040 } 1041 } else if (*p == '[') { 1042 if (*pref == NULL) 1043 goto bad; 1044 *p = '\0'; 1045 *port = racoon_strdup(p + 1); 1046 STRDUP_FATAL(*port); 1047 p = strchr(*pref, ']'); 1048 if (p == NULL) 1049 goto bad; 1050 *p = '\0'; 1051 } else { 1052 /* XXX */ 1053 } 1054 } 1055 1056 return 0; 1057 1058 bad: 1059 1060 if (*name) 1061 racoon_free(*name); 1062 if (*port) 1063 racoon_free(*port); 1064 if (*pref) 1065 racoon_free(*pref); 1066 *name = *port = *pref = NULL; 1067 return -1; 1068} 1069 1070static int 1071get_ulproto(str) 1072 char *str; 1073{ 1074 struct ulproto_tag *cp; 1075 1076 if(str == NULL){ 1077 errno = EINVAL; 1078 return -1; 1079 } 1080 1081 /* checking the string of upper layer protocol. */ 1082 for (cp = &ulprototab[0]; cp->str; cp++) { 1083 if (strcmp(str, cp->str) == 0) 1084 return cp->ul_proto; 1085 } 1086 1087 errno = EINVAL; 1088 return -1; 1089} 1090 1091/* %%% */ 1092void 1093dump_isakmp_sa(buf, len) 1094 char *buf; 1095 int len; 1096{ 1097 struct ph1dump *pd; 1098 struct tm *tm; 1099 char tbuf[56]; 1100 caddr_t p = NULL; 1101 1102/* isakmp status header */ 1103/* short header; 1104 1234567890123456789012 0000000000000000:0000000000000000 000000000000 1105*/ 1106char *header1 = 1107"Destination Cookies Created"; 1108 1109/* semi long header; 1110 1234567890123456789012 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000 1111*/ 1112char *header2 = 1113"Destination Cookies ST S V E Created Phase2"; 1114 1115/* long header; 1116 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000 1117*/ 1118char *header3 = 1119"Source Destination Cookies ST S V E Created Phase2"; 1120 1121/* phase status header */ 1122/* short format; 1123 side stats source address destination address 1124 xxx xxxxx 1234567890123456789012 1234567890123456789012 1125*/ 1126 1127 static char *estr[] = { "", "B", "M", "U", "A", "I", }; 1128 1129 switch (long_format) { 1130 case 0: 1131 printf("%s\n", header1); 1132 break; 1133 case 1: 1134 printf("%s\n", header2); 1135 break; 1136 case 2: 1137 default: 1138 printf("%s\n", header3); 1139 break; 1140 } 1141 1142 if (len % sizeof(*pd)) 1143 printf("invalid length %d\n", len); 1144 len /= sizeof(*pd); 1145 1146 pd = (struct ph1dump *)buf; 1147 1148 while (len-- > 0) { 1149 /* source address */ 1150 if (long_format >= 2) { 1151 GETNAMEINFO((struct sockaddr *)&pd->local, _addr1_, _addr2_); 1152 switch (long_format) { 1153 case 0: 1154 break; 1155 case 1: 1156 p = fixed_addr(_addr1_, _addr2_, 22); 1157 break; 1158 case 2: 1159 default: 1160 p = fixed_addr(_addr1_, _addr2_, 45); 1161 break; 1162 } 1163 printf("%s ", p); 1164 } 1165 1166 /* destination address */ 1167 GETNAMEINFO((struct sockaddr *)&pd->remote, _addr1_, _addr2_); 1168 switch (long_format) { 1169 case 0: 1170 case 1: 1171 p = fixed_addr(_addr1_, _addr2_, 22); 1172 break; 1173 case 2: 1174 default: 1175 p = fixed_addr(_addr1_, _addr2_, 45); 1176 break; 1177 } 1178 printf("%s ", p); 1179 1180 printf("%s ", pindex_isakmp(&pd->index)); 1181 1182 /* statuc, side and version */ 1183 if (long_format >= 1) { 1184 printf("%2d %c %2x ", 1185 pd->status, 1186 pd->side == INITIATOR ? 'I' : 'R', 1187 pd->version); 1188 if (ARRAYLEN(estr) > pd->etype) 1189 printf("%s ", estr[pd->etype]); 1190 } 1191 1192 /* created date */ 1193 if (pd->created) { 1194 tm = localtime(&pd->created); 1195 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm); 1196 } else 1197 snprintf(tbuf, sizeof(tbuf), " "); 1198 printf("%s ", tbuf); 1199 1200 /* counter of phase 2 */ 1201 if (long_format >= 1) 1202 printf("%6d ", pd->ph2cnt); 1203 1204 printf("\n"); 1205 1206 pd++; 1207 } 1208 1209 return; 1210} 1211 1212/* %%% */ 1213void 1214dump_internal(buf, tlen) 1215 char *buf; 1216 int tlen; 1217{ 1218 struct ph2handle *iph2; 1219 struct sockaddr *addr; 1220 1221/* 1222short header; 1223 source address destination address 1224 1234567890123456789012 1234567890123456789012 1225*/ 1226char *short_h1 = 1227"Source Destination "; 1228 1229/* 1230long header; 1231 source address destination address 1232 123456789012345678901234567890123456789012345 123456789012345678901234567890123456789012345 1233 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 1234*/ 1235char *long_h1 = 1236"Source Destination "; 1237 1238 printf("%s\n", long_format ? long_h1 : short_h1); 1239 1240 while (tlen > 0) { 1241 iph2 = (struct ph2handle *)buf; 1242 addr = (struct sockaddr *)(++iph2); 1243 1244 GETNAMEINFO(addr, _addr1_, _addr2_); 1245 printf("%s ", long_format ? 1246 fixed_addr(_addr1_, _addr2_, 45) 1247 : fixed_addr(_addr1_, _addr2_, 22)); 1248 addr++; 1249 tlen -= sysdep_sa_len(addr); 1250 1251 GETNAMEINFO(addr, _addr1_, _addr2_); 1252 printf("%s ", long_format ? 1253 fixed_addr(_addr1_, _addr2_, 45) 1254 : fixed_addr(_addr1_, _addr2_, 22)); 1255 addr++; 1256 tlen -= sysdep_sa_len(addr); 1257 1258 printf("\n"); 1259 } 1260 1261 return; 1262} 1263 1264/* %%% */ 1265char * 1266pindex_isakmp(index) 1267 isakmp_index *index; 1268{ 1269 static char buf[64]; 1270 u_char *p; 1271 int i, j; 1272 1273 memset(buf, 0, sizeof(buf)); 1274 1275 /* copy index */ 1276 p = (u_char *)index; 1277 for (j = 0, i = 0; i < sizeof(isakmp_index); i++) { 1278 snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]); 1279 j += 2; 1280 switch (i) { 1281 case 7: 1282#if 0 1283 case 15: 1284#endif 1285 buf[j++] = ':'; 1286 } 1287 } 1288 1289 return buf; 1290} 1291 1292/* print schedule */ 1293char *str_sched_stat[] = { 1294"off", 1295"on", 1296"dead", 1297}; 1298 1299char *str_sched_id[] = { 1300"PH1resend", 1301"PH1lifetime", 1302"PH2resend", 1303"PSTacquire", 1304"PSTlifetime", 1305}; 1306 1307void 1308print_schedule(buf, len) 1309 caddr_t buf; 1310 int len; 1311{ 1312 struct scheddump *sc = (struct scheddump *)buf; 1313 struct tm *tm; 1314 char tbuf[56]; 1315 1316 if (len % sizeof(*sc)) 1317 printf("invalid length %d\n", len); 1318 len /= sizeof(*sc); 1319 1320 /* 00000000 00000000 00000000 xxx........*/ 1321 printf("index tick xtime created\n"); 1322 1323 while (len-- > 0) { 1324 tm = localtime(&sc->created); 1325 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm); 1326 1327 printf("%-8ld %-8ld %-8ld %s\n", 1328 sc->id, 1329 (long)sc->tick, 1330 (long)sc->xtime, 1331 tbuf); 1332 sc++; 1333 } 1334 1335 return; 1336} 1337 1338 1339void 1340print_evt(buf, len) 1341 caddr_t buf; 1342 int len; 1343{ 1344 struct evtdump *evtdump = (struct evtdump *)buf; 1345 int i; 1346 char *srcstr; 1347 char *dststr; 1348 1349 for (i = 0; evtmsg[i].msg; i++) 1350 if (evtmsg[i].type == evtdump->type) 1351 break; 1352 1353 if (evtmsg[i].msg == NULL) 1354 printf("Event %d: ", evtdump->type); 1355 else 1356 printf("%s : ", evtmsg[i].msg); 1357 1358 if ((srcstr = saddr2str((struct sockaddr *)&evtdump->src)) == NULL) 1359 printf("unknown"); 1360 else 1361 printf("%s", srcstr); 1362 printf(" -> "); 1363 if ((dststr = saddr2str((struct sockaddr *)&evtdump->dst)) == NULL) 1364 printf("unknown"); 1365 else 1366 printf("%s", dststr); 1367 printf("\n"); 1368 1369 return; 1370} 1371 1372void 1373print_err(buf, len) 1374 caddr_t buf; 1375 int len; 1376{ 1377 struct evtdump *evtdump = (struct evtdump *)buf; 1378 int i; 1379 1380 1381 for (i = 0; evtmsg[i].msg; i++) 1382 if (evtmsg[i].type == evtdump->type) 1383 break; 1384 1385 if (evtmsg[i].level != ERROR) 1386 return; 1387 1388 if (evtmsg[i].msg == NULL) 1389 printf("Error: Event %d\n", evtdump->type); 1390 else 1391 printf("Error: %s\n", evtmsg[i].msg); 1392 1393 if (evt_filter & EVTF_ERR_STOP) 1394 evt_filter &= ~EVTF_LOOP; 1395 1396 return; 1397} 1398 1399/* 1400 * Print a message when phase 1 SA goes down 1401 */ 1402void 1403print_ph1down(buf, len) 1404 caddr_t buf; 1405 int len; 1406{ 1407 struct evtdump *evtdump = (struct evtdump *)buf; 1408 1409 if (evtdump->type != EVTT_PHASE1_DOWN) 1410 return; 1411 1412 printf("VPN connexion terminated\n"); 1413 1414 if (evt_filter & EVTF_PH1DOWN_STOP) 1415 evt_filter &= ~EVTF_LOOP; 1416 1417 return; 1418} 1419 1420/* 1421 * Print ISAKMP mode config info (IP and banner) 1422 */ 1423void 1424print_cfg(buf, len) 1425 caddr_t buf; 1426 int len; 1427{ 1428 struct evtdump *evtdump = (struct evtdump *)buf; 1429 struct isakmp_data *attr; 1430 char *banner = NULL; 1431 struct in_addr addr4; 1432 1433 memset(&addr4, 0, sizeof(addr4)); 1434 1435 if (evtdump->type != EVTT_ISAKMP_CFG_DONE && 1436 evtdump->type != EVTT_NO_ISAKMP_CFG) 1437 return; 1438 1439 len -= sizeof(*evtdump); 1440 attr = (struct isakmp_data *)(evtdump + 1); 1441 1442 while (len > 0) { 1443 if (len < sizeof(*attr)) { 1444 printf("short attribute too short\n"); 1445 break; 1446 } 1447 1448 if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) { 1449 /* Short attribute, skip */ 1450 len -= sizeof(*attr); 1451 attr++; 1452 } else { /* Long attribute */ 1453 char *n; 1454 1455 if (len < (sizeof(*attr) + ntohs(attr->lorv))) { 1456 printf("long attribute too long\n"); 1457 break; 1458 } 1459 1460 switch (ntohs(attr->type) & ~ISAKMP_GEN_MASK) { 1461 case INTERNAL_IP4_ADDRESS: 1462 if (ntohs(attr->lorv) < sizeof(addr4)) { 1463 printf("addr4 attribute too short\n"); 1464 break; 1465 } 1466 memcpy(&addr4, attr + 1, sizeof(addr4)); 1467 break; 1468 1469 case UNITY_BANNER: 1470 banner = racoon_malloc(ntohs(attr->lorv) + 1); 1471 if (banner == NULL) { 1472 printf("malloc failed\n"); 1473 break; 1474 } 1475 memcpy(banner, attr + 1, ntohs(attr->lorv)); 1476 banner[ntohs(attr->lorv)] = '\0'; 1477 break; 1478 1479 default: 1480 break; 1481 } 1482 1483 len -= (sizeof(*attr) + ntohs(attr->lorv)); 1484 n = (char *)attr; 1485 attr = (struct isakmp_data *) 1486 (n + sizeof(*attr) + ntohs(attr->lorv)); 1487 } 1488 } 1489 1490 if (evtdump->type == EVTT_ISAKMP_CFG_DONE) 1491 printf("Bound to address %s\n", inet_ntoa(addr4)); 1492 else 1493 printf("VPN connexion established\n"); 1494 1495 if (banner) { 1496 struct winsize win; 1497 int col = 0; 1498 int i; 1499 1500 if (ioctl(1, TIOCGWINSZ, &win) != 1) 1501 col = win.ws_col; 1502 1503 for (i = 0; i < col; i++) 1504 printf("%c", '='); 1505 printf("\n%s\n", banner); 1506 for (i = 0; i < col; i++) 1507 printf("%c", '='); 1508 printf("\n"); 1509 racoon_free(banner); 1510 } 1511 1512 if (evt_filter & EVTF_CFG_STOP) 1513 evt_filter &= ~EVTF_LOOP; 1514 1515 return; 1516} 1517 1518 1519char * 1520fixed_addr(addr, port, len) 1521 char *addr, *port; 1522 int len; 1523{ 1524 static char _addr_buf_[BUFSIZ]; 1525 char *p; 1526 int plen, i; 1527 1528 /* initialize */ 1529 memset(_addr_buf_, ' ', sizeof(_addr_buf_)); 1530 1531 plen = strlen(port); 1532 if (len < plen + 1) 1533 return NULL; 1534 1535 p = _addr_buf_; 1536 for (i = 0; i < len - plen - 1 && addr[i] != '\0'; /*noting*/) 1537 *p++ = addr[i++]; 1538 *p++ = '.'; 1539 1540 for (i = 0; i < plen && port[i] != '\0'; /*noting*/) 1541 *p++ = port[i++]; 1542 1543 _addr_buf_[len] = '\0'; 1544 1545 return _addr_buf_; 1546} 1547 1548static int 1549handle_recv(combuf) 1550 vchar_t *combuf; 1551{ 1552 struct admin_com h, *com; 1553 caddr_t buf; 1554 int len; 1555 1556 com = (struct admin_com *)combuf->v; 1557 len = com->ac_len - sizeof(*com); 1558 buf = combuf->v + sizeof(*com); 1559 1560 switch (com->ac_cmd) { 1561 case ADMIN_SHOW_SCHED: 1562 print_schedule(buf, len); 1563 break; 1564 1565 case ADMIN_SHOW_EVT: { 1566 struct evtdump *evtdump; 1567 1568 /* We got no event */ 1569 if (len == 0) { 1570 /* If we were purging the queue, it is now done */ 1571 if (evt_filter & EVTF_PURGE) 1572 evt_filter &= ~EVTF_PURGE; 1573 break; 1574 } 1575 1576 if (len < sizeof(struct evtdump)) 1577 errx(1, "Short buffer\n"); 1578 1579 /* Toss outdated events */ 1580 evtdump = (struct evtdump *)buf; 1581 if (evtdump->timestamp < evt_start) 1582 break; 1583 1584 if (evt_filter & EVTF_ALL) 1585 print_evt(buf, len); 1586 if (evt_filter & EVTF_ERR) 1587 print_err(buf, len); 1588 if (evt_filter & EVTF_CFG) 1589 print_cfg(buf, len); 1590 if (evt_filter & EVTF_PH1DOWN) 1591 print_ph1down(buf, len); 1592 break; 1593 } 1594 1595 case ADMIN_SHOW_SA: 1596 { 1597 switch (com->ac_proto) { 1598 case ADMIN_PROTO_ISAKMP: 1599 dump_isakmp_sa(buf, len); 1600 break; 1601 case ADMIN_PROTO_IPSEC: 1602 case ADMIN_PROTO_AH: 1603 case ADMIN_PROTO_ESP: 1604 { 1605 struct sadb_msg *msg = (struct sadb_msg *)buf; 1606 1607 switch (msg->sadb_msg_errno) { 1608 case ENOENT: 1609 switch (msg->sadb_msg_type) { 1610 case SADB_DELETE: 1611 case SADB_GET: 1612 printf("No entry.\n"); 1613 break; 1614 case SADB_DUMP: 1615 printf("No SAD entries.\n"); 1616 break; 1617 } 1618 break; 1619 case 0: 1620 while (1) { 1621 pfkey_sadump(msg); 1622 if (msg->sadb_msg_seq == 0) 1623 break; 1624 msg = (struct sadb_msg *)((caddr_t)msg + 1625 PFKEY_UNUNIT64(msg->sadb_msg_len)); 1626 } 1627 break; 1628 default: 1629 printf("%s.\n", strerror(msg->sadb_msg_errno)); 1630 } 1631 } 1632 break; 1633 case ADMIN_PROTO_INTERNAL: 1634 dump_internal(buf, len); 1635 break; 1636 default: 1637 printf("Invalid proto [%d]\n", com->ac_proto); 1638 } 1639 1640 } 1641 break; 1642 1643 default: 1644 /* IGNORE */ 1645 break; 1646 } 1647 1648 close(so); 1649 return 0; 1650 1651 bad: 1652 close(so); 1653 return -1; 1654} 1655