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