admin.c revision 6b112236f31ae21c11e416d3dd5d265a5cc5177a
1/* $NetBSD: admin.c,v 1.17.6.2 2008/06/18 07:30:19 mgrooms 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#ifndef ANDROID_CHANGES 40#include <sys/signal.h> 41#else 42#include <cutils/sockets.h> 43#include <arpa/inet.h> 44#include <ctype.h> 45#include "cfparse_proto.h" 46#define SIGHUP 1 47#endif 48#include <sys/stat.h> 49#include <sys/un.h> 50 51#include <net/pfkeyv2.h> 52 53#include <netinet/in.h> 54#include PATH_IPSEC_H 55 56 57#include <stdlib.h> 58#include <stdio.h> 59#include <string.h> 60#include <errno.h> 61#include <netdb.h> 62#ifdef HAVE_UNISTD_H 63#include <unistd.h> 64#endif 65#ifdef ENABLE_HYBRID 66#include <resolv.h> 67#endif 68 69#include "var.h" 70#include "misc.h" 71#include "vmbuf.h" 72#include "plog.h" 73#include "sockmisc.h" 74#include "debug.h" 75 76#include "schedule.h" 77#include "localconf.h" 78#include "remoteconf.h" 79#include "grabmyaddr.h" 80#include "isakmp_var.h" 81#include "isakmp.h" 82#include "oakley.h" 83#include "handler.h" 84#include "evt.h" 85#include "pfkey.h" 86#include "ipsec_doi.h" 87#include "admin.h" 88#include "admin_var.h" 89#include "isakmp_inf.h" 90#ifdef ENABLE_HYBRID 91#include "isakmp_cfg.h" 92#endif 93#include "session.h" 94#include "gcmalloc.h" 95 96#ifdef ENABLE_ADMINPORT 97char *adminsock_path = ADMINSOCK_PATH; 98uid_t adminsock_owner = 0; 99gid_t adminsock_group = 0; 100mode_t adminsock_mode = 0600; 101 102static struct sockaddr_un sunaddr; 103static int admin_process __P((int, char *)); 104static int admin_reply __P((int, struct admin_com *, vchar_t *)); 105 106int 107admin_handler() 108{ 109 int so2; 110 struct sockaddr_storage from; 111 socklen_t fromlen = sizeof(from); 112 struct admin_com com; 113 char *combuf = NULL; 114 int len, error = -1; 115 116 so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen); 117 if (so2 < 0) { 118 plog(LLV_ERROR, LOCATION, NULL, 119 "failed to accept admin command: %s\n", 120 strerror(errno)); 121 return -1; 122 } 123 124 /* get buffer length */ 125 while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) { 126 if (errno == EINTR) 127 continue; 128 plog(LLV_ERROR, LOCATION, NULL, 129 "failed to recv admin command: %s\n", 130 strerror(errno)); 131 goto end; 132 } 133 134 /* sanity check */ 135 if (len < sizeof(com)) { 136 plog(LLV_ERROR, LOCATION, NULL, 137 "invalid header length of admin command\n"); 138 goto end; 139 } 140 141 /* get buffer to receive */ 142 if ((combuf = racoon_malloc(com.ac_len)) == 0) { 143 plog(LLV_ERROR, LOCATION, NULL, 144 "failed to alloc buffer for admin command\n"); 145 goto end; 146 } 147 148 /* get real data */ 149 while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) { 150 if (errno == EINTR) 151 continue; 152 plog(LLV_ERROR, LOCATION, NULL, 153 "failed to recv admin command: %s\n", 154 strerror(errno)); 155 goto end; 156 } 157 158 if (com.ac_cmd == ADMIN_RELOAD_CONF) { 159 /* reload does not work at all! */ 160 signal_handler(SIGHUP); 161 goto end; 162 } 163 164 error = admin_process(so2, combuf); 165 166 end: 167 (void)close(so2); 168 if (combuf) 169 racoon_free(combuf); 170 171 return error; 172} 173 174/* 175 * main child's process. 176 */ 177static int 178admin_process(so2, combuf) 179 int so2; 180 char *combuf; 181{ 182 struct admin_com *com = (struct admin_com *)combuf; 183 vchar_t *buf = NULL; 184 vchar_t *id = NULL; 185 vchar_t *key = NULL; 186 int idtype = 0; 187 int error = -1; 188 189 com->ac_errno = 0; 190 191 switch (com->ac_cmd) { 192 case ADMIN_RELOAD_CONF: 193 /* don't entered because of proccessing it in other place. */ 194 plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n"); 195 goto out; 196 197 case ADMIN_SHOW_SCHED: 198 { 199 caddr_t p = NULL; 200 int len; 201 202 com->ac_errno = -1; 203 204 if (sched_dump(&p, &len) == -1) 205 goto out2; 206 207 if ((buf = vmalloc(len)) == NULL) 208 goto out2; 209 210 memcpy(buf->v, p, len); 211 212 com->ac_errno = 0; 213out2: 214 racoon_free(p); 215 break; 216 } 217 218 case ADMIN_SHOW_EVT: 219 /* It's not really an error, don't force racoonctl to quit */ 220 if ((buf = evt_dump()) == NULL) 221 com->ac_errno = 0; 222 break; 223 224 case ADMIN_SHOW_SA: 225 case ADMIN_FLUSH_SA: 226 { 227 switch (com->ac_proto) { 228 case ADMIN_PROTO_ISAKMP: 229 switch (com->ac_cmd) { 230 case ADMIN_SHOW_SA: 231 buf = dumpph1(); 232 if (buf == NULL) 233 com->ac_errno = -1; 234 break; 235 case ADMIN_FLUSH_SA: 236 flushph1(); 237 break; 238 } 239 break; 240 case ADMIN_PROTO_IPSEC: 241 case ADMIN_PROTO_AH: 242 case ADMIN_PROTO_ESP: 243 switch (com->ac_cmd) { 244 case ADMIN_SHOW_SA: 245 { 246 u_int p; 247 p = admin2pfkey_proto(com->ac_proto); 248 if (p == -1) 249 goto out; 250 buf = pfkey_dump_sadb(p); 251 if (buf == NULL) 252 com->ac_errno = -1; 253 } 254 break; 255 case ADMIN_FLUSH_SA: 256 pfkey_flush_sadb(com->ac_proto); 257 break; 258 } 259 break; 260 261 case ADMIN_PROTO_INTERNAL: 262 switch (com->ac_cmd) { 263 case ADMIN_SHOW_SA: 264 buf = NULL; /*XXX dumpph2(&error);*/ 265 if (buf == NULL) 266 com->ac_errno = error; 267 break; 268 case ADMIN_FLUSH_SA: 269 /*XXX flushph2();*/ 270 com->ac_errno = 0; 271 break; 272 } 273 break; 274 275 default: 276 /* ignore */ 277 com->ac_errno = -1; 278 } 279 } 280 break; 281 282 case ADMIN_DELETE_SA: { 283 struct ph1handle *iph1; 284 struct sockaddr *dst; 285 struct sockaddr *src; 286 char *loc, *rem; 287 288 src = (struct sockaddr *) 289 &((struct admin_com_indexes *) 290 ((caddr_t)com + sizeof(*com)))->src; 291 dst = (struct sockaddr *) 292 &((struct admin_com_indexes *) 293 ((caddr_t)com + sizeof(*com)))->dst; 294 295 loc = racoon_strdup(saddrwop2str(src)); 296 rem = racoon_strdup(saddrwop2str(dst)); 297 STRDUP_FATAL(loc); 298 STRDUP_FATAL(rem); 299 300 if ((iph1 = getph1byaddrwop(src, dst)) == NULL) { 301 plog(LLV_ERROR, LOCATION, NULL, 302 "phase 1 for %s -> %s not found\n", loc, rem); 303 } else { 304 if (iph1->status == PHASE1ST_ESTABLISHED) 305 isakmp_info_send_d1(iph1); 306 purge_remote(iph1); 307 } 308 309 racoon_free(loc); 310 racoon_free(rem); 311 312 break; 313 } 314 315#ifdef ENABLE_HYBRID 316 case ADMIN_LOGOUT_USER: { 317 struct ph1handle *iph1; 318 char *user; 319 int found = 0; 320 321 if (com->ac_len > sizeof(com) + LOGINLEN + 1) { 322 plog(LLV_ERROR, LOCATION, NULL, 323 "malformed message (login too long)\n"); 324 break; 325 } 326 327 user = (char *)(com + 1); 328 found = purgeph1bylogin(user); 329 plog(LLV_INFO, LOCATION, NULL, 330 "deleted %d SA for user \"%s\"\n", found, user); 331 332 break; 333 } 334#endif 335 336 case ADMIN_DELETE_ALL_SA_DST: { 337 struct ph1handle *iph1; 338 struct sockaddr *dst; 339 char *loc, *rem; 340 341 dst = (struct sockaddr *) 342 &((struct admin_com_indexes *) 343 ((caddr_t)com + sizeof(*com)))->dst; 344 345 rem = racoon_strdup(saddrwop2str(dst)); 346 STRDUP_FATAL(rem); 347 348 plog(LLV_INFO, LOCATION, NULL, 349 "Flushing all SAs for peer %s\n", rem); 350 351 while ((iph1 = getph1bydstaddrwop(dst)) != NULL) { 352 loc = racoon_strdup(saddrwop2str(iph1->local)); 353 STRDUP_FATAL(loc); 354 355 if (iph1->status == PHASE1ST_ESTABLISHED) 356 isakmp_info_send_d1(iph1); 357 purge_remote(iph1); 358 359 racoon_free(loc); 360 } 361 362 racoon_free(rem); 363 364 break; 365 } 366 367 case ADMIN_ESTABLISH_SA_PSK: { 368 struct admin_com_psk *acp; 369 char *data; 370 371 com->ac_cmd = ADMIN_ESTABLISH_SA; 372 373 acp = (struct admin_com_psk *) 374 ((char *)com + sizeof(*com) + 375 sizeof(struct admin_com_indexes)); 376 377 idtype = acp->id_type; 378 379 if ((id = vmalloc(acp->id_len)) == NULL) { 380 plog(LLV_ERROR, LOCATION, NULL, 381 "cannot allocate memory: %s\n", 382 strerror(errno)); 383 break; 384 } 385 data = (char *)(acp + 1); 386 memcpy(id->v, data, id->l); 387 388 if ((key = vmalloc(acp->key_len)) == NULL) { 389 plog(LLV_ERROR, LOCATION, NULL, 390 "cannot allocate memory: %s\n", 391 strerror(errno)); 392 vfree(id); 393 id = NULL; 394 break; 395 } 396 data = (char *)(data + acp->id_len); 397 memcpy(key->v, data, key->l); 398 } 399 /* FALLTHROUGH */ 400 case ADMIN_ESTABLISH_SA: 401 { 402 struct sockaddr *dst; 403 struct sockaddr *src; 404 src = (struct sockaddr *) 405 &((struct admin_com_indexes *) 406 ((caddr_t)com + sizeof(*com)))->src; 407 dst = (struct sockaddr *) 408 &((struct admin_com_indexes *) 409 ((caddr_t)com + sizeof(*com)))->dst; 410 411 switch (com->ac_proto) { 412 case ADMIN_PROTO_ISAKMP: { 413 struct remoteconf *rmconf; 414 struct sockaddr *remote = NULL; 415 struct sockaddr *local = NULL; 416 u_int16_t port; 417 418 com->ac_errno = -1; 419 420 /* search appropreate configuration */ 421 rmconf = getrmconf(dst); 422 if (rmconf == NULL) { 423 plog(LLV_ERROR, LOCATION, NULL, 424 "no configuration found " 425 "for %s\n", saddrwop2str(dst)); 426 goto out1; 427 } 428 429 /* get remote IP address and port number. */ 430 if ((remote = dupsaddr(dst)) == NULL) 431 goto out1; 432 433 port = extract_port(rmconf->remote); 434 if (set_port(remote, port) == NULL) 435 goto out1; 436 437 /* get local address */ 438 if ((local = dupsaddr(src)) == NULL) 439 goto out1; 440 441 port = getmyaddrsport(local); 442 if (set_port(local, port) == NULL) 443 goto out1; 444 445#ifdef ENABLE_HYBRID 446 /* Set the id and key */ 447 if (id && key) { 448 if (xauth_rmconf_used(&rmconf->xauth) == -1) 449 goto out1; 450 451 if (rmconf->xauth->login != NULL) { 452 vfree(rmconf->xauth->login); 453 rmconf->xauth->login = NULL; 454 } 455 if (rmconf->xauth->pass != NULL) { 456 vfree(rmconf->xauth->pass); 457 rmconf->xauth->pass = NULL; 458 } 459 460 rmconf->xauth->login = id; 461 rmconf->xauth->pass = key; 462 } 463#endif 464 465 plog(LLV_INFO, LOCATION, NULL, 466 "accept a request to establish IKE-SA: " 467 "%s\n", saddrwop2str(remote)); 468 469 /* begin ident mode */ 470 if (isakmp_ph1begin_i(rmconf, remote, local) < 0) 471 goto out1; 472 473 com->ac_errno = 0; 474out1: 475 if (local != NULL) 476 racoon_free(local); 477 if (remote != NULL) 478 racoon_free(remote); 479 break; 480 } 481 case ADMIN_PROTO_AH: 482 case ADMIN_PROTO_ESP: 483 break; 484 default: 485 /* ignore */ 486 com->ac_errno = -1; 487 } 488 } 489 break; 490 491 default: 492 plog(LLV_ERROR, LOCATION, NULL, 493 "invalid command: %d\n", com->ac_cmd); 494 com->ac_errno = -1; 495 } 496 497 if ((error = admin_reply(so2, com, buf)) != 0) 498 goto out; 499 500 error = 0; 501out: 502 if (buf != NULL) 503 vfree(buf); 504 505 return error; 506} 507 508static int 509admin_reply(so, combuf, buf) 510 int so; 511 struct admin_com *combuf; 512 vchar_t *buf; 513{ 514 int tlen; 515 char *retbuf = NULL; 516 517 if (buf != NULL) 518 tlen = sizeof(*combuf) + buf->l; 519 else 520 tlen = sizeof(*combuf); 521 522 retbuf = racoon_calloc(1, tlen); 523 if (retbuf == NULL) { 524 plog(LLV_ERROR, LOCATION, NULL, 525 "failed to allocate admin buffer\n"); 526 return -1; 527 } 528 529 memcpy(retbuf, combuf, sizeof(*combuf)); 530 ((struct admin_com *)retbuf)->ac_len = tlen; 531 532 if (buf != NULL) 533 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l); 534 535 tlen = send(so, retbuf, tlen, 0); 536 racoon_free(retbuf); 537 if (tlen < 0) { 538 plog(LLV_ERROR, LOCATION, NULL, 539 "failed to send admin command: %s\n", 540 strerror(errno)); 541 return -1; 542 } 543 544 return 0; 545} 546 547/* ADMIN_PROTO -> SADB_SATYPE */ 548int 549admin2pfkey_proto(proto) 550 u_int proto; 551{ 552 switch (proto) { 553 case ADMIN_PROTO_IPSEC: 554 return SADB_SATYPE_UNSPEC; 555 case ADMIN_PROTO_AH: 556 return SADB_SATYPE_AH; 557 case ADMIN_PROTO_ESP: 558 return SADB_SATYPE_ESP; 559 default: 560 plog(LLV_ERROR, LOCATION, NULL, 561 "unsupported proto for admin: %d\n", proto); 562 return -1; 563 } 564 /*NOTREACHED*/ 565} 566 567int 568admin_init() 569{ 570 if (adminsock_path == NULL) { 571 lcconf->sock_admin = -1; 572 return 0; 573 } 574 575 memset(&sunaddr, 0, sizeof(sunaddr)); 576 sunaddr.sun_family = AF_UNIX; 577 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), 578 "%s", adminsock_path); 579 580 lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0); 581 if (lcconf->sock_admin == -1) { 582 plog(LLV_ERROR, LOCATION, NULL, 583 "socket: %s\n", strerror(errno)); 584 return -1; 585 } 586 587 unlink(sunaddr.sun_path); 588 if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr, 589 sizeof(sunaddr)) != 0) { 590 plog(LLV_ERROR, LOCATION, NULL, 591 "bind(sockname:%s): %s\n", 592 sunaddr.sun_path, strerror(errno)); 593 (void)close(lcconf->sock_admin); 594 return -1; 595 } 596 597 if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) { 598 plog(LLV_ERROR, LOCATION, NULL, 599 "chown(%s, %d, %d): %s\n", 600 sunaddr.sun_path, adminsock_owner, 601 adminsock_group, strerror(errno)); 602 (void)close(lcconf->sock_admin); 603 return -1; 604 } 605 606 if (chmod(sunaddr.sun_path, adminsock_mode) != 0) { 607 plog(LLV_ERROR, LOCATION, NULL, 608 "chmod(%s, 0%03o): %s\n", 609 sunaddr.sun_path, adminsock_mode, strerror(errno)); 610 (void)close(lcconf->sock_admin); 611 return -1; 612 } 613 614 if (listen(lcconf->sock_admin, 5) != 0) { 615 plog(LLV_ERROR, LOCATION, NULL, 616 "listen(sockname:%s): %s\n", 617 sunaddr.sun_path, strerror(errno)); 618 (void)close(lcconf->sock_admin); 619 return -1; 620 } 621 plog(LLV_DEBUG, LOCATION, NULL, 622 "open %s as racoon management.\n", sunaddr.sun_path); 623 624 return 0; 625} 626 627int 628admin_close() 629{ 630 close(lcconf->sock_admin); 631 return 0; 632} 633#endif 634 635#ifdef ANDROID_CHANGES 636// Add the android specific control commands from VPN settings. 637#define CMD_LOAD_CONFIG "LOAD_CONFIG " 638#define CMD_SETKEY "SETKEY " 639#define CMD_SET_CERTS "SET_CERTS " 640#define RACOON_SOCKET "racoon" 641#define PORT_L2TP 1701 642 643// The following policy is supported for now. 644#define INCOMING_POLICY "in ipsec esp/transport//require" 645#define OUTGOING_POLICY "out ipsec esp/transport//require" 646 647static inline int get_sockaddr_in(addr, port, sin) 648 const char *addr; 649 int port; 650 struct sockaddr_in *sin; 651{ 652 struct hostent *entry; 653 654 sin->sin_family = AF_INET; 655 sin->sin_port = htons(port); 656 sin->sin_addr.s_addr = inet_addr(addr); 657 658 if ((int)sin->sin_addr.s_addr != -1) { 659 return 0; 660 } 661 if ((entry = gethostbyname(addr)) != NULL) { 662 memcpy(&sin->sin_addr, *entry->h_addr_list, sizeof(struct in_addr)); 663 if ((int)sin->sin_addr.s_addr != -1) { 664 return 0; 665 } 666 } 667 plog(LLV_ERROR, LOCATION, NULL, 668 "ERROR: incorrect src or dst address(%s)", addr); 669 return -1; 670} 671 672static int parse_addresses(buf, src, dst) 673 char *buf; 674 struct sockaddr_in *src, *dst; 675{ 676 char *tokens[2], *argv = buf; 677 int i = 0; 678 while(i < 2) { 679 if ((tokens[i++] = strtok(argv, " ")) == NULL) { 680 return -1; 681 } 682 argv = NULL; 683 } 684 if ((get_sockaddr_in(tokens[0], 0, src) != 0) || 685 (get_sockaddr_in(tokens[1], PORT_L2TP, dst) != 0)) { 686 return -1; 687 } 688 return 0; 689} 690 691static int spdadd(addresses) 692 const char *addresses; 693{ 694 struct sockaddr src, dst; 695 char *outpolicy, *inpolicy; 696 int inlen, outlen, plen; 697 int so = -1; 698 699 /* SETKEY src_ip dst_ip */ 700 if (parse_addresses(addresses, (struct sockaddr_in *)&src, 701 (struct sockaddr_in *)&dst) < 0) { 702 exit(1); 703 } 704 705 outpolicy = ipsec_set_policy(OUTGOING_POLICY, strlen(OUTGOING_POLICY)); 706 outlen = ipsec_get_policylen(outpolicy); 707 inpolicy = ipsec_set_policy(INCOMING_POLICY, strlen(INCOMING_POLICY)); 708 inlen = ipsec_get_policylen(inpolicy); 709 710 if ((so = pfkey_open()) < 0) { 711 plog(LLV_ERROR, LOCATION, NULL, "ERROR: %s", ipsec_strerror()); 712 exit(1); 713 } 714 // spdflush() 715 if (pfkey_send_spdflush(so) < 0) { 716 plog(LLV_ERROR, LOCATION, NULL, "ERROR: %s", ipsec_strerror()); 717 exit(1); 718 } 719 plen = sizeof(struct in_addr) << 3; 720 // add outgoing policy 721 if (pfkey_send_spdadd(so, &src, plen, &dst, plen, 722 17, outpolicy, outlen, 0) < 0) { 723 plog(LLV_ERROR, LOCATION, NULL, "ERROR: %s", ipsec_strerror()); 724 exit(1); 725 } 726 // add incoming policy 727 if (pfkey_send_spdadd(so, &dst, plen, &src, plen, 728 17, inpolicy, inlen, 0) < 0) { 729 plog(LLV_ERROR, LOCATION, NULL, "ERROR: %s", ipsec_strerror()); 730 exit(1); 731 } 732 733 pfkey_close(so); 734 return 0; 735} 736 737static int setcerts(cmd) 738 const char *cmd; 739{ 740 /* 741 * SET_CERTS has 4 arguments: 742 * destip cacert_path usercert_path userkey_path 743 */ 744 struct remoteconf *tplrmconf; 745 struct sockaddr dst, anonymous; 746 char *tokens[4], *buf = (char*)cmd; 747 int i = 0; 748 while(i < 4) { 749 if ((tokens[i++] = strtok(buf, " ")) == NULL) { 750 plog(LLV_ERROR, LOCATION, NULL, 751 "incorrect command SET_CERTS %s", cmd); 752 return -1; 753 } 754 buf = NULL; 755 } 756 if (get_sockaddr_in((struct sockaddr_in *)&dst, tokens[0], 0) != 0) { 757 plog(LLV_ERROR, LOCATION, NULL, "incorrect dest address %s", tokens[0]); 758 return -1; 759 } 760 anonymous.sa_family = AF_UNSPEC; 761 if((tplrmconf = getrmconf(&anonymous)) == NULL) { 762 plog(LLV_ERROR, LOCATION, NULL, "Can not find the remtoe template"); 763 return -1; 764 } 765 memcpy(tplrmconf->remote, &dst, sizeof(dst)); 766 tplrmconf->cacertfile = strdup(tokens[1]); 767 tplrmconf->mycertfile = strdup(tokens[2]); 768 tplrmconf->myprivfile = strdup(tokens[3]); 769 return 0; 770} 771 772static int 773control_process(buf) 774 char *buf; 775{ 776 plog(LLV_ERROR, LOCATION, NULL, "control command %s", buf); 777 if(strncmp(buf, CMD_LOAD_CONFIG, strlen(CMD_LOAD_CONFIG)) == 0) { 778 /* LOAD_CONFIG /data/misc/vpn/xxx/racoon.conf */ 779 lcconf->racoon_conf = strdup(buf + strlen(CMD_LOAD_CONFIG)); 780 return cfreparse(); 781 } else if (strncmp(buf, CMD_SETKEY, strlen(CMD_SETKEY)) == 0) { 782 return spdadd(buf + strlen(CMD_SETKEY)); 783 } else if (strncmp(buf, CMD_SET_CERTS, strlen(CMD_SET_CERTS)) == 0) { 784 return setcerts(buf + strlen(CMD_SET_CERTS)); 785 } 786 plog(LLV_ERROR, LOCATION, NULL, "Unsupported command '%s'", buf); 787 return -1; 788} 789 790int 791control_init() 792{ 793 lcconf->control_client = -1; 794 lcconf->sock_control = android_get_control_socket(RACOON_SOCKET); 795 if (lcconf->sock_control < 0) { 796 plog(LLV_ERROR, LOCATION, NULL, 797 "Obtaining file descriptor socket '%s' failed: %s", 798 RACOON_SOCKET, strerror(errno)); 799 return -1; 800 } 801 if (listen(lcconf->sock_control, 5) < 0) { 802 plog(LLV_ERROR, LOCATION, NULL, 803 "Unable to listen on fd '%d' for socket '%s': %s", 804 lcconf->sock_control, RACOON_SOCKET, strerror(errno)); 805 close(lcconf->sock_control); 806 lcconf->sock_control = -1; 807 return -1; 808 } 809 return 0; 810} 811 812int 813control_newclient() 814{ 815 struct sockaddr_storage from; 816 socklen_t fromlen = sizeof(from); 817 818 lcconf->control_client = 819 accept(lcconf->sock_control, (struct sockaddr *)&from, &fromlen); 820 if (lcconf->control_client < 0) { 821 plog(LLV_ERROR, LOCATION, NULL, 822 "failed to accept control command: %s\n", 823 strerror(errno)); 824 return -1; 825 } 826 return 0; 827} 828 829int 830control_handler() 831{ 832 char buf[512], reply; 833 int i, n, len, error = -1; 834 835 /* get command */ 836 i = 0; 837 len = sizeof(buf); 838 while ((n = recv(lcconf->control_client, buf + i, len - i, 0)) > 0) { 839 i += n; 840 if (i >= len) { 841 plog(LLV_ERROR, LOCATION, NULL, 842 "command is too long: %s\n", buf); 843 goto end; 844 } else if (buf[i - 1] == 0) { 845 error = control_process(buf); 846 goto end; 847 } 848 } 849 plog(LLV_ERROR, LOCATION, NULL, 850 "failed to recv control command: %s\n", strerror(errno)); 851 852end: 853 reply = error; 854 if (send(lcconf->control_client, &reply, 1, 0) != 1) { 855 plog(LLV_ERROR, LOCATION, NULL, 856 "failed to send the reply(%d) back\n", reply); 857 } 858 (void)close(lcconf->control_client); 859 lcconf->control_client = -1; 860 return error; 861} 862 863int 864control_close() 865{ 866 close(lcconf->sock_control); 867 return 0; 868} 869 870void test_commands(char *cmd) 871{ 872 control_process(0, cmd); 873} 874#endif 875