1/* $NetBSD: admin.c,v 1.41 2018/05/19 20:14:56 maxv Exp $ */ 2 3/* Id: admin.c,v 1.25 2006/04/06 14:31:04 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/signal.h> 40#include <sys/stat.h> 41#include <sys/un.h> 42 43#include <net/pfkeyv2.h> 44 45#include <netinet/in.h> 46#include PATH_IPSEC_H 47 48 49#include <stdlib.h> 50#include <stdio.h> 51#include <string.h> 52#include <errno.h> 53#include <netdb.h> 54#ifdef HAVE_UNISTD_H 55#include <unistd.h> 56#endif 57#ifdef ENABLE_HYBRID 58#include <resolv.h> 59#endif 60 61#include "var.h" 62#include "misc.h" 63#include "vmbuf.h" 64#include "plog.h" 65#include "sockmisc.h" 66#include "debug.h" 67 68#include "schedule.h" 69#include "localconf.h" 70#include "remoteconf.h" 71#include "grabmyaddr.h" 72#include "isakmp_var.h" 73#include "isakmp.h" 74#include "oakley.h" 75#include "handler.h" 76#include "evt.h" 77#include "pfkey.h" 78#include "ipsec_doi.h" 79#include "policy.h" 80#include "admin.h" 81#include "admin_var.h" 82#include "isakmp_inf.h" 83#ifdef ENABLE_HYBRID 84#include "isakmp_cfg.h" 85#endif 86#include "session.h" 87#include "gcmalloc.h" 88 89#ifdef ENABLE_ADMINPORT 90char *adminsock_path = ADMINSOCK_PATH; 91uid_t adminsock_owner = 0; 92gid_t adminsock_group = 0; 93mode_t adminsock_mode = 0600; 94 95static struct sockaddr_un sunaddr; 96static int admin_process __P((int, char *)); 97static int admin_reply __P((int, struct admin_com *, int, vchar_t *)); 98 99static int 100admin_handler(void *ctx, int fd) 101{ 102 int so2; 103 struct sockaddr_storage from; 104 socklen_t fromlen = sizeof(from); 105 struct admin_com com; 106 char *combuf = NULL; 107 int len, error = -1; 108 109 so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen); 110 if (so2 < 0) { 111 plog(LLV_ERROR, LOCATION, NULL, 112 "failed to accept admin command: %s\n", 113 strerror(errno)); 114 return -1; 115 } 116 close_on_exec(so2); 117 118 /* get buffer length */ 119 while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) { 120 if (errno == EINTR) 121 continue; 122 plog(LLV_ERROR, LOCATION, NULL, 123 "failed to recv admin command: %s\n", 124 strerror(errno)); 125 goto end; 126 } 127 128 /* sanity check */ 129 if (len < sizeof(com)) { 130 plog(LLV_ERROR, LOCATION, NULL, 131 "invalid header length of admin command\n"); 132 goto end; 133 } 134 135 /* get buffer to receive */ 136 if ((combuf = racoon_malloc(com.ac_len)) == 0) { 137 plog(LLV_ERROR, LOCATION, NULL, 138 "failed to alloc buffer for admin command\n"); 139 goto end; 140 } 141 142 /* get real data */ 143 while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) { 144 if (errno == EINTR) 145 continue; 146 plog(LLV_ERROR, LOCATION, NULL, 147 "failed to recv admin command: %s\n", 148 strerror(errno)); 149 goto end; 150 } 151 152 error = admin_process(so2, combuf); 153 154end: 155 if (error == -2) { 156 plog(LLV_DEBUG, LOCATION, NULL, 157 "[%d] admin connection established\n", so2); 158 } else { 159 (void)close(so2); 160 } 161 162 if (combuf) 163 racoon_free(combuf); 164 165 return error; 166} 167 168static int admin_ph1_delete_sa(struct ph1handle *iph1, void *arg) 169{ 170 if (iph1->status >= PHASE1ST_ESTABLISHED) 171 isakmp_info_send_d1(iph1); 172 purge_remote(iph1); 173 return 0; 174} 175 176/* 177 * main child's process. 178 */ 179static int 180admin_process(so2, combuf) 181 int so2; 182 char *combuf; 183{ 184 struct admin_com *com = (struct admin_com *)combuf; 185 vchar_t *buf = NULL; 186 vchar_t *id = NULL; 187 vchar_t *key = NULL; 188 int idtype = 0; 189 int error = 0, l_ac_errno = 0; 190 struct evt_listener_list *event_list = NULL; 191 192 if (com->ac_cmd & ADMIN_FLAG_VERSION) 193 com->ac_cmd &= ~ADMIN_FLAG_VERSION; 194 else 195 com->ac_version = 0; 196 197 switch (com->ac_cmd) { 198 case ADMIN_RELOAD_CONF: 199 signal_handler(SIGHUP); 200 break; 201 202 case ADMIN_SHOW_SCHED: { 203 caddr_t p = NULL; 204 int len; 205 206 if (sched_dump(&p, &len) != -1) { 207 buf = vmalloc(len); 208 if (buf != NULL) 209 memcpy(buf->v, p, len); 210 else 211 l_ac_errno = ENOMEM; 212 racoon_free(p); 213 } else 214 l_ac_errno = ENOMEM; 215 break; 216 } 217 218 case ADMIN_SHOW_EVT: 219 if (com->ac_version == 0) { 220 buf = evt_dump(); 221 l_ac_errno = 0; 222 } 223 break; 224 225 case ADMIN_SHOW_SA: 226 switch (com->ac_proto) { 227 case ADMIN_PROTO_ISAKMP: 228 buf = dumpph1(); 229 if (buf == NULL) 230 l_ac_errno = ENOMEM; 231 break; 232 case ADMIN_PROTO_IPSEC: 233 case ADMIN_PROTO_AH: 234 case ADMIN_PROTO_ESP: { 235 u_int p; 236 p = admin2pfkey_proto(com->ac_proto); 237 if (p != -1) { 238 buf = pfkey_dump_sadb(p); 239 if (buf == NULL) 240 l_ac_errno = ENOMEM; 241 } else 242 l_ac_errno = EINVAL; 243 break; 244 } 245 case ADMIN_PROTO_INTERNAL: 246 default: 247 l_ac_errno = ENOTSUP; 248 break; 249 } 250 break; 251 252 case ADMIN_GET_SA_CERT: { 253 struct admin_com_indexes *ndx; 254 struct sockaddr *src, *dst; 255 struct ph1handle *iph1; 256 257 ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com)); 258 src = (struct sockaddr *) &ndx->src; 259 dst = (struct sockaddr *) &ndx->dst; 260 261 if (com->ac_proto != ADMIN_PROTO_ISAKMP) { 262 l_ac_errno = ENOTSUP; 263 break; 264 } 265 266 iph1 = getph1byaddr(src, dst, 0); 267 if (iph1 == NULL) { 268 l_ac_errno = ENOENT; 269 break; 270 } 271 272 if (iph1->cert_p != NULL) { 273 vchar_t tmp; 274 tmp.v = iph1->cert_p->v + 1; 275 tmp.l = iph1->cert_p->l - 1; 276 buf = vdup(&tmp); 277 } 278 break; 279 } 280 281 case ADMIN_FLUSH_SA: 282 switch (com->ac_proto) { 283 case ADMIN_PROTO_ISAKMP: 284 flushph1(); 285 break; 286 case ADMIN_PROTO_IPSEC: 287 case ADMIN_PROTO_AH: 288 case ADMIN_PROTO_ESP: 289 pfkey_flush_sadb(com->ac_proto); 290 break; 291 case ADMIN_PROTO_INTERNAL: 292 /*XXX flushph2();*/ 293 default: 294 l_ac_errno = ENOTSUP; 295 break; 296 } 297 break; 298 299 case ADMIN_DELETE_SA: { 300 char *loc, *rem; 301 struct ph1selector sel; 302 303 memset(&sel, 0, sizeof(sel)); 304 sel.local = (struct sockaddr *) 305 &((struct admin_com_indexes *) 306 ((caddr_t)com + sizeof(*com)))->src; 307 sel.remote = (struct sockaddr *) 308 &((struct admin_com_indexes *) 309 ((caddr_t)com + sizeof(*com)))->dst; 310 311 loc = racoon_strdup(saddr2str(sel.local)); 312 rem = racoon_strdup(saddr2str(sel.remote)); 313 STRDUP_FATAL(loc); 314 STRDUP_FATAL(rem); 315 316 plog(LLV_INFO, LOCATION, NULL, 317 "admin delete-sa %s %s\n", loc, rem); 318 enumph1(&sel, admin_ph1_delete_sa, NULL); 319 remcontacted(sel.remote); 320 321 racoon_free(loc); 322 racoon_free(rem); 323 break; 324 } 325 326#ifdef ENABLE_HYBRID 327 case ADMIN_LOGOUT_USER: { 328 char user[LOGINLEN+1]; 329 int found = 0, len = com->ac_len - sizeof(*com); 330 331 if (len > LOGINLEN) { 332 plog(LLV_ERROR, LOCATION, NULL, 333 "malformed message (login too long)\n"); 334 break; 335 } 336 337 memcpy(user, (char *)(com + 1), len); 338 user[len] = 0; 339 340 found = purgeph1bylogin(user); 341 plog(LLV_INFO, LOCATION, NULL, 342 "deleted %d SA for user \"%s\"\n", found, user); 343 344 break; 345 } 346#endif 347 348 case ADMIN_DELETE_ALL_SA_DST: { 349 struct ph1handle *iph1; 350 struct sockaddr *dst; 351 char *loc, *rem; 352 353 dst = (struct sockaddr *) 354 &((struct admin_com_indexes *) 355 ((caddr_t)com + sizeof(*com)))->dst; 356 357 rem = racoon_strdup(saddrwop2str(dst)); 358 STRDUP_FATAL(rem); 359 360 plog(LLV_INFO, LOCATION, NULL, 361 "Flushing all SAs for peer %s\n", rem); 362 363 while ((iph1 = getph1bydstaddr(dst)) != NULL) { 364 loc = racoon_strdup(saddrwop2str(iph1->local)); 365 STRDUP_FATAL(loc); 366 367 if (iph1->status >= PHASE1ST_ESTABLISHED) 368 isakmp_info_send_d1(iph1); 369 purge_remote(iph1); 370 371 racoon_free(loc); 372 } 373 374 racoon_free(rem); 375 break; 376 } 377 378 case ADMIN_ESTABLISH_SA_PSK: { 379 struct admin_com_psk *acp; 380 char *data; 381 382 acp = (struct admin_com_psk *) 383 ((char *)com + sizeof(*com) + 384 sizeof(struct admin_com_indexes)); 385 386 idtype = acp->id_type; 387 388 if ((id = vmalloc(acp->id_len)) == NULL) { 389 plog(LLV_ERROR, LOCATION, NULL, 390 "cannot allocate memory: %s\n", 391 strerror(errno)); 392 break; 393 } 394 data = (char *)(acp + 1); 395 memcpy(id->v, data, id->l); 396 397 if ((key = vmalloc(acp->key_len)) == NULL) { 398 plog(LLV_ERROR, LOCATION, NULL, 399 "cannot allocate memory: %s\n", 400 strerror(errno)); 401 vfree(id); 402 id = NULL; 403 break; 404 } 405 data = (char *)(data + acp->id_len); 406 memcpy(key->v, data, key->l); 407 } 408 /* FALLTHROUGH */ 409 case ADMIN_ESTABLISH_SA: { 410 struct admin_com_indexes *ndx; 411 struct sockaddr *dst; 412 struct sockaddr *src; 413 char *name = NULL; 414 415 ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com)); 416 src = (struct sockaddr *) &ndx->src; 417 dst = (struct sockaddr *) &ndx->dst; 418 419 if (com->ac_cmd == ADMIN_ESTABLISH_SA && 420 com->ac_len > sizeof(*com) + sizeof(*ndx)) 421 name = (char *) ((caddr_t) ndx + sizeof(*ndx)); 422 423 switch (com->ac_proto) { 424 case ADMIN_PROTO_ISAKMP: { 425 struct ph1handle *ph1; 426 struct remoteconf *rmconf; 427 428 l_ac_errno = -1; 429 430 /* connected already? */ 431 ph1 = getph1byaddr(src, dst, 0); 432 if (ph1 != NULL) { 433 event_list = &ph1->evt_listeners; 434 if (ph1->status == PHASE1ST_ESTABLISHED) 435 l_ac_errno = EEXIST; 436 else 437 l_ac_errno = 0; 438 break; 439 } 440 441 /* search appropreate configuration */ 442 if (name == NULL) 443 rmconf = getrmconf(dst, 0); 444 else 445 rmconf = getrmconf_by_name(name); 446 if (rmconf == NULL) { 447 plog(LLV_ERROR, LOCATION, NULL, 448 "no configuration found " 449 "for %s\n", saddrwop2str(dst)); 450 break; 451 } 452 453#ifdef ENABLE_HYBRID 454 /* XXX This overwrites rmconf information globally. */ 455 /* Set the id and key */ 456 if (id && key) { 457 if (xauth_rmconf_used(&rmconf->xauth) == -1) 458 break; 459 460 if (rmconf->xauth->login != NULL) { 461 vfree(rmconf->xauth->login); 462 rmconf->xauth->login = NULL; 463 } 464 if (rmconf->xauth->pass != NULL) { 465 vfree(rmconf->xauth->pass); 466 rmconf->xauth->pass = NULL; 467 } 468 469 rmconf->xauth->login = id; 470 rmconf->xauth->pass = key; 471 } 472#endif 473 474 plog(LLV_INFO, LOCATION, NULL, 475 "accept a request to establish IKE-SA: " 476 "%s\n", saddrwop2str(dst)); 477 478 /* begin ident mode */ 479 ph1 = isakmp_ph1begin_i(rmconf, dst, src); 480 if (ph1 == NULL) 481 break; 482 483 event_list = &ph1->evt_listeners; 484 l_ac_errno = 0; 485 break; 486 } 487 case ADMIN_PROTO_AH: 488 case ADMIN_PROTO_ESP: { 489 struct ph2handle *iph2; 490 struct secpolicy *sp_out = NULL, *sp_in = NULL; 491 struct policyindex spidx; 492 493 l_ac_errno = -1; 494 495 /* got outbound policy */ 496 memset(&spidx, 0, sizeof(spidx)); 497 spidx.dir = IPSEC_DIR_OUTBOUND; 498 memcpy(&spidx.src, src, sizeof(spidx.src)); 499 memcpy(&spidx.dst, dst, sizeof(spidx.dst)); 500 spidx.prefs = ndx->prefs; 501 spidx.prefd = ndx->prefd; 502 spidx.ul_proto = ndx->ul_proto; 503 504 sp_out = getsp_r(&spidx); 505 if (sp_out) { 506 plog(LLV_DEBUG, LOCATION, NULL, 507 "suitable outbound SP found: %s.\n", 508 spidx2str(&sp_out->spidx)); 509 } else { 510 l_ac_errno = ENOENT; 511 plog(LLV_NOTIFY, LOCATION, NULL, 512 "no outbound policy found: %s\n", 513 spidx2str(&spidx)); 514 break; 515 } 516 517 iph2 = getph2byid(src, dst, sp_out->id); 518 if (iph2 != NULL) { 519 event_list = &iph2->evt_listeners; 520 if (iph2->status == PHASE2ST_ESTABLISHED) 521 l_ac_errno = EEXIST; 522 else 523 l_ac_errno = 0; 524 break; 525 } 526 527 /* get inbound policy */ 528 memset(&spidx, 0, sizeof(spidx)); 529 spidx.dir = IPSEC_DIR_INBOUND; 530 memcpy(&spidx.src, dst, sizeof(spidx.src)); 531 memcpy(&spidx.dst, src, sizeof(spidx.dst)); 532 spidx.prefs = ndx->prefd; 533 spidx.prefd = ndx->prefs; 534 spidx.ul_proto = ndx->ul_proto; 535 536 sp_in = getsp_r(&spidx); 537 if (sp_in) { 538 plog(LLV_DEBUG, LOCATION, NULL, 539 "suitable inbound SP found: %s.\n", 540 spidx2str(&sp_in->spidx)); 541 } else { 542 l_ac_errno = ENOENT; 543 plog(LLV_NOTIFY, LOCATION, NULL, 544 "no inbound policy found: %s\n", 545 spidx2str(&spidx)); 546 break; 547 } 548 549 /* allocate a phase 2 */ 550 iph2 = newph2(); 551 if (iph2 == NULL) { 552 plog(LLV_ERROR, LOCATION, NULL, 553 "failed to allocate phase2 entry.\n"); 554 break; 555 } 556 iph2->side = INITIATOR; 557 iph2->satype = admin2pfkey_proto(com->ac_proto); 558 iph2->spid = sp_out->id; 559 iph2->seq = pk_getseq(); 560 iph2->status = PHASE2ST_STATUS2; 561 562 if (sp_out->local && sp_out->remote) { 563 /* hints available, let's use them */ 564 iph2->sa_dst = dupsaddr(dst); 565 iph2->sa_src = dupsaddr(src); 566 iph2->src = dupsaddr((struct sockaddr *)sp_out->local); 567 iph2->dst = dupsaddr((struct sockaddr *)sp_out->remote); 568 } else if (sp_out->req && sp_out->req->saidx.mode == IPSEC_MODE_TUNNEL) { 569 /* Tunnel mode and no hint, use endpoints */ 570 iph2->src = dupsaddr((struct sockaddr *)&sp_out->req->saidx.src); 571 iph2->dst = dupsaddr((struct sockaddr *)&sp_out->req->saidx.dst); 572 } else { 573 /* default, use selectors as fallback */ 574 iph2->sa_dst = dupsaddr(dst); 575 iph2->sa_src = dupsaddr(src); 576 iph2->dst = dupsaddr(dst); 577 iph2->src = dupsaddr(src); 578 } 579 580 if (iph2->dst == NULL || iph2->src == NULL) { 581 delph2(iph2); 582 break; 583 } 584 set_port(iph2->dst, 0); 585 set_port(iph2->src, 0); 586 587 if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) { 588 delph2(iph2); 589 break; 590 } 591 592 insph2(iph2); 593 if (isakmp_post_acquire(iph2, NULL, FALSE) < 0) { 594 remph2(iph2); 595 delph2(iph2); 596 break; 597 } 598 599 event_list = &iph2->evt_listeners; 600 l_ac_errno = 0; 601 break; 602 } 603 default: 604 /* ignore */ 605 l_ac_errno = ENOTSUP; 606 } 607 break; 608 } 609 610 default: 611 plog(LLV_ERROR, LOCATION, NULL, 612 "invalid command: %d\n", com->ac_cmd); 613 l_ac_errno = ENOTSUP; 614 } 615 616 if ((error = admin_reply(so2, com, l_ac_errno, buf)) != 0) 617 goto out; 618 619 /* start pushing events if so requested */ 620 if ((l_ac_errno == 0) && 621 (com->ac_version >= 1) && 622 (com->ac_cmd == ADMIN_SHOW_EVT || event_list != NULL)) 623 error = evt_subscribe(event_list, so2); 624out: 625 if (buf != NULL) 626 vfree(buf); 627 628 return error; 629} 630 631static int 632admin_reply(so, req, l_ac_errno, buf) 633 int so, l_ac_errno; 634 struct admin_com *req; 635 vchar_t *buf; 636{ 637 int tlen; 638 struct admin_com *combuf; 639 char *retbuf = NULL; 640 641 if (buf != NULL) 642 tlen = sizeof(*combuf) + buf->l; 643 else 644 tlen = sizeof(*combuf); 645 646 retbuf = racoon_calloc(1, tlen); 647 if (retbuf == NULL) { 648 plog(LLV_ERROR, LOCATION, NULL, 649 "failed to allocate admin buffer\n"); 650 return -1; 651 } 652 653 combuf = (struct admin_com *) retbuf; 654 combuf->ac_len = (u_int16_t) tlen; 655 combuf->ac_cmd = req->ac_cmd & ~ADMIN_FLAG_VERSION; 656 if (tlen != (u_int32_t) combuf->ac_len && 657 l_ac_errno == 0) { 658 combuf->ac_len_high = tlen >> 16; 659 combuf->ac_cmd |= ADMIN_FLAG_LONG_REPLY; 660 } else { 661 combuf->ac_errno = l_ac_errno; 662 } 663 combuf->ac_proto = req->ac_proto; 664 665 if (buf != NULL) 666 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l); 667 668 tlen = send(so, retbuf, tlen, 0); 669 racoon_free(retbuf); 670 if (tlen < 0) { 671 plog(LLV_ERROR, LOCATION, NULL, 672 "failed to send admin command: %s\n", 673 strerror(errno)); 674 return -1; 675 } 676 677 return 0; 678} 679 680/* ADMIN_PROTO -> SADB_SATYPE */ 681int 682admin2pfkey_proto(proto) 683 u_int proto; 684{ 685 switch (proto) { 686 case ADMIN_PROTO_IPSEC: 687 return SADB_SATYPE_UNSPEC; 688 case ADMIN_PROTO_AH: 689 return SADB_SATYPE_AH; 690 case ADMIN_PROTO_ESP: 691 return SADB_SATYPE_ESP; 692 default: 693 plog(LLV_ERROR, LOCATION, NULL, 694 "unsupported proto for admin: %d\n", proto); 695 return -1; 696 } 697 /*NOTREACHED*/ 698} 699 700int 701admin_init() 702{ 703 if (adminsock_path == NULL) { 704 lcconf->sock_admin = -1; 705 return 0; 706 } 707 708 memset(&sunaddr, 0, sizeof(sunaddr)); 709 sunaddr.sun_family = AF_UNIX; 710 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), 711 "%s", adminsock_path); 712 713 lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0); 714 if (lcconf->sock_admin == -1) { 715 plog(LLV_ERROR, LOCATION, NULL, 716 "socket: %s\n", strerror(errno)); 717 return -1; 718 } 719 close_on_exec(lcconf->sock_admin); 720 721 unlink(sunaddr.sun_path); 722 if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr, 723 sizeof(sunaddr)) != 0) { 724 plog(LLV_ERROR, LOCATION, NULL, 725 "bind(sockname:%s): %s\n", 726 sunaddr.sun_path, strerror(errno)); 727 (void)close(lcconf->sock_admin); 728 return -1; 729 } 730 731 if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) { 732 plog(LLV_ERROR, LOCATION, NULL, 733 "chown(%s, %d, %d): %s\n", 734 sunaddr.sun_path, adminsock_owner, 735 adminsock_group, strerror(errno)); 736 (void)close(lcconf->sock_admin); 737 return -1; 738 } 739 740 if (chmod(sunaddr.sun_path, adminsock_mode) != 0) { 741 plog(LLV_ERROR, LOCATION, NULL, 742 "chmod(%s, 0%03o): %s\n", 743 sunaddr.sun_path, adminsock_mode, strerror(errno)); 744 (void)close(lcconf->sock_admin); 745 return -1; 746 } 747 748 if (listen(lcconf->sock_admin, 5) != 0) { 749 plog(LLV_ERROR, LOCATION, NULL, 750 "listen(sockname:%s): %s\n", 751 sunaddr.sun_path, strerror(errno)); 752 (void)close(lcconf->sock_admin); 753 return -1; 754 } 755 756 monitor_fd(lcconf->sock_admin, admin_handler, NULL, 0); 757 plog(LLV_DEBUG, LOCATION, NULL, 758 "open %s as racoon management.\n", sunaddr.sun_path); 759 760 return 0; 761} 762 763int 764admin_close() 765{ 766 unmonitor_fd(lcconf->sock_admin); 767 close(lcconf->sock_admin); 768 return 0; 769} 770 771#endif 772