racoonctl.c revision 0a1907d434839af6a9cb6329bbde60b237bf53dc
1/* $NetBSD: racoonctl.c,v 1.7.6.1 2008/07/15 00:55:48 mgrooms 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 838 /* need username */ 839 if (ac < 1) 840 errx(1, "insufficient arguments"); 841 user = av[0]; 842 if ((user == NULL) || (strlen(user) > LOGINLEN)) 843 errx(1, "bad login (too long?)"); 844 845 buf = vmalloc(sizeof(*head) + strlen(user) + 1); 846 if (buf == NULL) 847 return NULL; 848 849 head = (struct admin_com *)buf->v; 850 head->ac_len = buf->l; 851 head->ac_cmd = ADMIN_LOGOUT_USER; 852 head->ac_errno = 0; 853 head->ac_proto = 0; 854 855 strncpy((char *)(head + 1), user, LOGINLEN); 856 857 return buf; 858} 859#endif /* ENABLE_HYBRID */ 860 861 862static int 863get_proto(str) 864 char *str; 865{ 866 struct proto_tag *cp; 867 868 if (str == NULL) { 869 errno = EINVAL; 870 return -1; 871 } 872 873 /* checking the string of command. */ 874 for (cp = &prototab[0]; cp->str; cp++) { 875 if (strcmp(str, cp->str) == 0) 876 return cp->proto; 877 } 878 879 errno = EINVAL; 880 return -1; 881} 882 883static vchar_t * 884get_index(ac, av) 885 int ac; 886 char **av; 887{ 888 int family; 889 890 if (ac != 3 && ac != 4) { 891 errno = EINVAL; 892 return NULL; 893 } 894 895 /* checking the string of family */ 896 family = get_family(*av); 897 if (family == -1) 898 return NULL; 899 av++; 900 ac--; 901 902 return get_comindexes(family, ac, av); 903} 904 905static int 906get_family(str) 907 char *str; 908{ 909 if (strcmp("inet", str) == 0) 910 return AF_INET; 911#ifdef INET6 912 else if (strcmp("inet6", str) == 0) 913 return AF_INET6; 914#endif 915 errno = EAFNOSUPPORT; 916 return -1; 917} 918 919static vchar_t * 920get_comindexes(family, ac, av) 921 int family; 922 int ac; 923 char **av; 924{ 925 vchar_t *buf; 926 struct admin_com_indexes *ci; 927 char *p_name = NULL, *p_port = NULL; 928 char *p_prefs = NULL, *p_prefd = NULL; 929 struct sockaddr *src = NULL, *dst = NULL; 930 int ulproto; 931 932 if (ac != 2 && ac != 3) { 933 errno = EINVAL; 934 return NULL; 935 } 936 937 if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1) 938 goto bad; 939 src = get_sockaddr(family, p_name, p_port); 940 if (p_name) { 941 racoon_free(p_name); 942 p_name = NULL; 943 } 944 if (p_port) { 945 racoon_free(p_port); 946 p_port = NULL; 947 } 948 if (src == NULL) 949 goto bad; 950 av++; 951 ac--; 952 if (get_comindex(*av, &p_name, &p_port, &p_prefd) == -1) 953 goto bad; 954 dst = get_sockaddr(family, p_name, p_port); 955 if (p_name) { 956 racoon_free(p_name); 957 p_name = NULL; 958 } 959 if (p_port) { 960 racoon_free(p_port); 961 p_port = NULL; 962 } 963 if (dst == NULL) 964 goto bad; 965 966 buf = vmalloc(sizeof(*ci)); 967 if (buf == NULL) 968 goto bad; 969 970 av++; 971 ac--; 972 if(ac){ 973 ulproto = get_ulproto(*av); 974 if (ulproto == -1) 975 goto bad; 976 }else 977 ulproto=0; 978 979 ci = (struct admin_com_indexes *)buf->v; 980 if(p_prefs) 981 ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */ 982 else 983 ci->prefs = 32; 984 if(p_prefd) 985 ci->prefd = (u_int8_t)atoi(p_prefd); /* XXX should be handled error. */ 986 else 987 ci->prefd = 32; 988 ci->ul_proto = ulproto; 989 memcpy(&ci->src, src, sysdep_sa_len(src)); 990 memcpy(&ci->dst, dst, sysdep_sa_len(dst)); 991 992 if (p_name) 993 racoon_free(p_name); 994 995 return buf; 996 997 bad: 998 if (p_name) 999 racoon_free(p_name); 1000 if (p_port) 1001 racoon_free(p_port); 1002 if (p_prefs) 1003 racoon_free(p_prefs); 1004 if (p_prefd) 1005 racoon_free(p_prefd); 1006 return NULL; 1007} 1008 1009static int 1010get_comindex(str, name, port, pref) 1011 char *str, **name, **port, **pref; 1012{ 1013 char *p; 1014 1015 *name = *port = *pref = NULL; 1016 1017 *name = racoon_strdup(str); 1018 STRDUP_FATAL(*name); 1019 p = strpbrk(*name, "/["); 1020 if (p != NULL) { 1021 if (*(p + 1) == '\0') 1022 goto bad; 1023 if (*p == '/') { 1024 *p = '\0'; 1025 *pref = racoon_strdup(p + 1); 1026 STRDUP_FATAL(*pref); 1027 p = strchr(*pref, '['); 1028 if (p != NULL) { 1029 if (*(p + 1) == '\0') 1030 goto bad; 1031 *p = '\0'; 1032 *port = racoon_strdup(p + 1); 1033 STRDUP_FATAL(*port); 1034 p = strchr(*pref, ']'); 1035 if (p == NULL) 1036 goto bad; 1037 *p = '\0'; 1038 } 1039 } else if (*p == '[') { 1040 if (*pref == NULL) 1041 goto bad; 1042 *p = '\0'; 1043 *port = racoon_strdup(p + 1); 1044 STRDUP_FATAL(*port); 1045 p = strchr(*pref, ']'); 1046 if (p == NULL) 1047 goto bad; 1048 *p = '\0'; 1049 } else { 1050 /* XXX */ 1051 } 1052 } 1053 1054 return 0; 1055 1056 bad: 1057 1058 if (*name) 1059 racoon_free(*name); 1060 if (*port) 1061 racoon_free(*port); 1062 if (*pref) 1063 racoon_free(*pref); 1064 *name = *port = *pref = NULL; 1065 return -1; 1066} 1067 1068static int 1069get_ulproto(str) 1070 char *str; 1071{ 1072 struct ulproto_tag *cp; 1073 1074 if(str == NULL){ 1075 errno = EINVAL; 1076 return -1; 1077 } 1078 1079 /* checking the string of upper layer protocol. */ 1080 for (cp = &ulprototab[0]; cp->str; cp++) { 1081 if (strcmp(str, cp->str) == 0) 1082 return cp->ul_proto; 1083 } 1084 1085 errno = EINVAL; 1086 return -1; 1087} 1088 1089/* %%% */ 1090void 1091dump_isakmp_sa(buf, len) 1092 char *buf; 1093 int len; 1094{ 1095 struct ph1dump *pd; 1096 struct tm *tm; 1097 char tbuf[56]; 1098 caddr_t p = NULL; 1099 1100/* isakmp status header */ 1101/* short header; 1102 1234567890123456789012 0000000000000000:0000000000000000 000000000000 1103*/ 1104char *header1 = 1105"Destination Cookies Created"; 1106 1107/* semi long header; 1108 1234567890123456789012 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000 1109*/ 1110char *header2 = 1111"Destination Cookies ST S V E Created Phase2"; 1112 1113/* long header; 1114 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 1115*/ 1116char *header3 = 1117"Source Destination Cookies ST S V E Created Phase2"; 1118 1119/* phase status header */ 1120/* short format; 1121 side stats source address destination address 1122 xxx xxxxx 1234567890123456789012 1234567890123456789012 1123*/ 1124 1125 static char *estr[] = { "", "B", "M", "U", "A", "I", }; 1126 1127 switch (long_format) { 1128 case 0: 1129 printf("%s\n", header1); 1130 break; 1131 case 1: 1132 printf("%s\n", header2); 1133 break; 1134 case 2: 1135 default: 1136 printf("%s\n", header3); 1137 break; 1138 } 1139 1140 if (len % sizeof(*pd)) 1141 printf("invalid length %d\n", len); 1142 len /= sizeof(*pd); 1143 1144 pd = (struct ph1dump *)buf; 1145 1146 while (len-- > 0) { 1147 /* source address */ 1148 if (long_format >= 2) { 1149 GETNAMEINFO((struct sockaddr *)&pd->local, _addr1_, _addr2_); 1150 switch (long_format) { 1151 case 0: 1152 break; 1153 case 1: 1154 p = fixed_addr(_addr1_, _addr2_, 22); 1155 break; 1156 case 2: 1157 default: 1158 p = fixed_addr(_addr1_, _addr2_, 45); 1159 break; 1160 } 1161 printf("%s ", p); 1162 } 1163 1164 /* destination address */ 1165 GETNAMEINFO((struct sockaddr *)&pd->remote, _addr1_, _addr2_); 1166 switch (long_format) { 1167 case 0: 1168 case 1: 1169 p = fixed_addr(_addr1_, _addr2_, 22); 1170 break; 1171 case 2: 1172 default: 1173 p = fixed_addr(_addr1_, _addr2_, 45); 1174 break; 1175 } 1176 printf("%s ", p); 1177 1178 printf("%s ", pindex_isakmp(&pd->index)); 1179 1180 /* statuc, side and version */ 1181 if (long_format >= 1) { 1182 printf("%2d %c %2x ", 1183 pd->status, 1184 pd->side == INITIATOR ? 'I' : 'R', 1185 pd->version); 1186 if (ARRAYLEN(estr) > pd->etype) 1187 printf("%s ", estr[pd->etype]); 1188 } 1189 1190 /* created date */ 1191 if (pd->created) { 1192 tm = localtime(&pd->created); 1193 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm); 1194 } else 1195 snprintf(tbuf, sizeof(tbuf), " "); 1196 printf("%s ", tbuf); 1197 1198 /* counter of phase 2 */ 1199 if (long_format >= 1) 1200 printf("%6d ", pd->ph2cnt); 1201 1202 printf("\n"); 1203 1204 pd++; 1205 } 1206 1207 return; 1208} 1209 1210/* %%% */ 1211void 1212dump_internal(buf, tlen) 1213 char *buf; 1214 int tlen; 1215{ 1216 struct ph2handle *iph2; 1217 struct sockaddr *addr; 1218 1219/* 1220short header; 1221 source address destination address 1222 1234567890123456789012 1234567890123456789012 1223*/ 1224char *short_h1 = 1225"Source Destination "; 1226 1227/* 1228long header; 1229 source address destination address 1230 123456789012345678901234567890123456789012345 123456789012345678901234567890123456789012345 1231 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 1232*/ 1233char *long_h1 = 1234"Source Destination "; 1235 1236 printf("%s\n", long_format ? long_h1 : short_h1); 1237 1238 while (tlen > 0) { 1239 iph2 = (struct ph2handle *)buf; 1240 addr = (struct sockaddr *)(++iph2); 1241 1242 GETNAMEINFO(addr, _addr1_, _addr2_); 1243 printf("%s ", long_format ? 1244 fixed_addr(_addr1_, _addr2_, 45) 1245 : fixed_addr(_addr1_, _addr2_, 22)); 1246 addr++; 1247 tlen -= sysdep_sa_len(addr); 1248 1249 GETNAMEINFO(addr, _addr1_, _addr2_); 1250 printf("%s ", long_format ? 1251 fixed_addr(_addr1_, _addr2_, 45) 1252 : fixed_addr(_addr1_, _addr2_, 22)); 1253 addr++; 1254 tlen -= sysdep_sa_len(addr); 1255 1256 printf("\n"); 1257 } 1258 1259 return; 1260} 1261 1262/* %%% */ 1263char * 1264pindex_isakmp(index) 1265 isakmp_index *index; 1266{ 1267 static char buf[64]; 1268 u_char *p; 1269 int i, j; 1270 1271 memset(buf, 0, sizeof(buf)); 1272 1273 /* copy index */ 1274 p = (u_char *)index; 1275 for (j = 0, i = 0; i < sizeof(isakmp_index); i++) { 1276 snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]); 1277 j += 2; 1278 switch (i) { 1279 case 7: 1280#if 0 1281 case 15: 1282#endif 1283 buf[j++] = ':'; 1284 } 1285 } 1286 1287 return buf; 1288} 1289 1290/* print schedule */ 1291char *str_sched_stat[] = { 1292"off", 1293"on", 1294"dead", 1295}; 1296 1297char *str_sched_id[] = { 1298"PH1resend", 1299"PH1lifetime", 1300"PH2resend", 1301"PSTacquire", 1302"PSTlifetime", 1303}; 1304 1305void 1306print_schedule(buf, len) 1307 caddr_t buf; 1308 int len; 1309{ 1310 struct scheddump *sc = (struct scheddump *)buf; 1311 struct tm *tm; 1312 char tbuf[56]; 1313 1314 if (len % sizeof(*sc)) 1315 printf("invalid length %d\n", len); 1316 len /= sizeof(*sc); 1317 1318 /* 00000000 00000000 00000000 xxx........*/ 1319 printf("index tick xtime created\n"); 1320 1321 while (len-- > 0) { 1322 tm = localtime(&sc->created); 1323 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm); 1324 1325 printf("%-8ld %-8ld %-8ld %s\n", 1326 sc->id, 1327 (long)sc->tick, 1328 (long)sc->xtime, 1329 tbuf); 1330 sc++; 1331 } 1332 1333 return; 1334} 1335 1336 1337void 1338print_evt(buf, len) 1339 caddr_t buf; 1340 int len; 1341{ 1342 struct evtdump *evtdump = (struct evtdump *)buf; 1343 int i; 1344 char *srcstr; 1345 char *dststr; 1346 1347 for (i = 0; evtmsg[i].msg; i++) 1348 if (evtmsg[i].type == evtdump->type) 1349 break; 1350 1351 if (evtmsg[i].msg == NULL) 1352 printf("Event %d: ", evtdump->type); 1353 else 1354 printf("%s : ", evtmsg[i].msg); 1355 1356 if ((srcstr = saddr2str((struct sockaddr *)&evtdump->src)) == NULL) 1357 printf("unknown"); 1358 else 1359 printf("%s", srcstr); 1360 printf(" -> "); 1361 if ((dststr = saddr2str((struct sockaddr *)&evtdump->dst)) == NULL) 1362 printf("unknown"); 1363 else 1364 printf("%s", dststr); 1365 printf("\n"); 1366 1367 return; 1368} 1369 1370void 1371print_err(buf, len) 1372 caddr_t buf; 1373 int len; 1374{ 1375 struct evtdump *evtdump = (struct evtdump *)buf; 1376 int i; 1377 1378 1379 for (i = 0; evtmsg[i].msg; i++) 1380 if (evtmsg[i].type == evtdump->type) 1381 break; 1382 1383 if (evtmsg[i].level != ERROR) 1384 return; 1385 1386 if (evtmsg[i].msg == NULL) 1387 printf("Error: Event %d\n", evtdump->type); 1388 else 1389 printf("Error: %s\n", evtmsg[i].msg); 1390 1391 if (evt_filter & EVTF_ERR_STOP) 1392 evt_filter &= ~EVTF_LOOP; 1393 1394 return; 1395} 1396 1397/* 1398 * Print a message when phase 1 SA goes down 1399 */ 1400void 1401print_ph1down(buf, len) 1402 caddr_t buf; 1403 int len; 1404{ 1405 struct evtdump *evtdump = (struct evtdump *)buf; 1406 1407 if (evtdump->type != EVTT_PHASE1_DOWN) 1408 return; 1409 1410 printf("VPN connexion terminated\n"); 1411 1412 if (evt_filter & EVTF_PH1DOWN_STOP) 1413 evt_filter &= ~EVTF_LOOP; 1414 1415 return; 1416} 1417 1418/* 1419 * Print ISAKMP mode config info (IP and banner) 1420 */ 1421void 1422print_cfg(buf, len) 1423 caddr_t buf; 1424 int len; 1425{ 1426 struct evtdump *evtdump = (struct evtdump *)buf; 1427 struct isakmp_data *attr; 1428 char *banner = NULL; 1429 struct in_addr addr4; 1430 1431 memset(&addr4, 0, sizeof(addr4)); 1432 1433 if (evtdump->type != EVTT_ISAKMP_CFG_DONE && 1434 evtdump->type != EVTT_NO_ISAKMP_CFG) 1435 return; 1436 1437 len -= sizeof(*evtdump); 1438 attr = (struct isakmp_data *)(evtdump + 1); 1439 1440 while (len > 0) { 1441 if (len < sizeof(*attr)) { 1442 printf("short attribute too short\n"); 1443 break; 1444 } 1445 1446 if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) { 1447 /* Short attribute, skip */ 1448 len -= sizeof(*attr); 1449 attr++; 1450 } else { /* Long attribute */ 1451 char *n; 1452 1453 if (len < (sizeof(*attr) + ntohs(attr->lorv))) { 1454 printf("long attribute too long\n"); 1455 break; 1456 } 1457 1458 switch (ntohs(attr->type) & ~ISAKMP_GEN_MASK) { 1459 case INTERNAL_IP4_ADDRESS: 1460 if (ntohs(attr->lorv) < sizeof(addr4)) { 1461 printf("addr4 attribute too short\n"); 1462 break; 1463 } 1464 memcpy(&addr4, attr + 1, sizeof(addr4)); 1465 break; 1466 1467 case UNITY_BANNER: 1468 banner = racoon_malloc(ntohs(attr->lorv) + 1); 1469 if (banner == NULL) { 1470 printf("malloc failed\n"); 1471 break; 1472 } 1473 memcpy(banner, attr + 1, ntohs(attr->lorv)); 1474 banner[ntohs(attr->lorv)] = '\0'; 1475 break; 1476 1477 default: 1478 break; 1479 } 1480 1481 len -= (sizeof(*attr) + ntohs(attr->lorv)); 1482 n = (char *)attr; 1483 attr = (struct isakmp_data *) 1484 (n + sizeof(*attr) + ntohs(attr->lorv)); 1485 } 1486 } 1487 1488 if (evtdump->type == EVTT_ISAKMP_CFG_DONE) 1489 printf("Bound to address %s\n", inet_ntoa(addr4)); 1490 else 1491 printf("VPN connexion established\n"); 1492 1493 if (banner) { 1494 struct winsize win; 1495 int col = 0; 1496 int i; 1497 1498 if (ioctl(1, TIOCGWINSZ, &win) != 1) 1499 col = win.ws_col; 1500 1501 for (i = 0; i < col; i++) 1502 printf("%c", '='); 1503 printf("\n%s\n", banner); 1504 for (i = 0; i < col; i++) 1505 printf("%c", '='); 1506 printf("\n"); 1507 racoon_free(banner); 1508 } 1509 1510 if (evt_filter & EVTF_CFG_STOP) 1511 evt_filter &= ~EVTF_LOOP; 1512 1513 return; 1514} 1515 1516 1517char * 1518fixed_addr(addr, port, len) 1519 char *addr, *port; 1520 int len; 1521{ 1522 static char _addr_buf_[BUFSIZ]; 1523 char *p; 1524 int plen, i; 1525 1526 /* initialize */ 1527 memset(_addr_buf_, ' ', sizeof(_addr_buf_)); 1528 1529 plen = strlen(port); 1530 if (len < plen + 1) 1531 return NULL; 1532 1533 p = _addr_buf_; 1534 for (i = 0; i < len - plen - 1 && addr[i] != '\0'; /*noting*/) 1535 *p++ = addr[i++]; 1536 *p++ = '.'; 1537 1538 for (i = 0; i < plen && port[i] != '\0'; /*noting*/) 1539 *p++ = port[i++]; 1540 1541 _addr_buf_[len] = '\0'; 1542 1543 return _addr_buf_; 1544} 1545 1546static int 1547handle_recv(combuf) 1548 vchar_t *combuf; 1549{ 1550 struct admin_com h, *com; 1551 caddr_t buf; 1552 int len; 1553 1554 com = (struct admin_com *)combuf->v; 1555 len = com->ac_len - sizeof(*com); 1556 buf = combuf->v + sizeof(*com); 1557 1558 switch (com->ac_cmd) { 1559 case ADMIN_SHOW_SCHED: 1560 print_schedule(buf, len); 1561 break; 1562 1563 case ADMIN_SHOW_EVT: { 1564 struct evtdump *evtdump; 1565 1566 /* We got no event */ 1567 if (len == 0) { 1568 /* If we were purging the queue, it is now done */ 1569 if (evt_filter & EVTF_PURGE) 1570 evt_filter &= ~EVTF_PURGE; 1571 break; 1572 } 1573 1574 if (len < sizeof(struct evtdump)) 1575 errx(1, "Short buffer\n"); 1576 1577 /* Toss outdated events */ 1578 evtdump = (struct evtdump *)buf; 1579 if (evtdump->timestamp < evt_start) 1580 break; 1581 1582 if (evt_filter & EVTF_ALL) 1583 print_evt(buf, len); 1584 if (evt_filter & EVTF_ERR) 1585 print_err(buf, len); 1586 if (evt_filter & EVTF_CFG) 1587 print_cfg(buf, len); 1588 if (evt_filter & EVTF_PH1DOWN) 1589 print_ph1down(buf, len); 1590 break; 1591 } 1592 1593 case ADMIN_SHOW_SA: 1594 { 1595 switch (com->ac_proto) { 1596 case ADMIN_PROTO_ISAKMP: 1597 dump_isakmp_sa(buf, len); 1598 break; 1599 case ADMIN_PROTO_IPSEC: 1600 case ADMIN_PROTO_AH: 1601 case ADMIN_PROTO_ESP: 1602 { 1603 struct sadb_msg *msg = (struct sadb_msg *)buf; 1604 1605 switch (msg->sadb_msg_errno) { 1606 case ENOENT: 1607 switch (msg->sadb_msg_type) { 1608 case SADB_DELETE: 1609 case SADB_GET: 1610 printf("No entry.\n"); 1611 break; 1612 case SADB_DUMP: 1613 printf("No SAD entries.\n"); 1614 break; 1615 } 1616 break; 1617 case 0: 1618 while (1) { 1619 pfkey_sadump(msg); 1620 if (msg->sadb_msg_seq == 0) 1621 break; 1622 msg = (struct sadb_msg *)((caddr_t)msg + 1623 PFKEY_UNUNIT64(msg->sadb_msg_len)); 1624 } 1625 break; 1626 default: 1627 printf("%s.\n", strerror(msg->sadb_msg_errno)); 1628 } 1629 } 1630 break; 1631 case ADMIN_PROTO_INTERNAL: 1632 dump_internal(buf, len); 1633 break; 1634 default: 1635 printf("Invalid proto [%d]\n", com->ac_proto); 1636 } 1637 1638 } 1639 break; 1640 1641 default: 1642 /* IGNORE */ 1643 break; 1644 } 1645 1646 close(so); 1647 return 0; 1648 1649 bad: 1650 close(so); 1651 return -1; 1652} 1653