Annotation of embedaddon/ipsec-tools/src/racoon/admin.c, revision 1.1
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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>