1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <stdio.h> 25#include <fcntl.h> 26#include <ctype.h> 27#include <stdlib.h> 28#include <string.h> 29#include <netdb.h> 30#include <paths.h> 31#include <unistd.h> 32#include <arpa/inet.h> 33#include <ifaddrs.h> 34#include <net/if.h> 35#include <netinet/in.h> 36#include <sys/ioctl.h> 37#include <sys/socket.h> 38#include <sys/queue.h> 39#include <sys/wait.h> 40#include <sys/stat.h> 41#include <sys/param.h> 42#include <sys/kern_event.h> 43#include <arpa/inet.h> 44#include <sys/un.h> 45 46#include <net/if_var.h> 47 48#include <netinet/in_var.h> 49#include <mach/mach_time.h> 50 51#include <CoreFoundation/CoreFoundation.h> 52#include <SystemConfiguration/SystemConfiguration.h> 53 54#include "vpnoptions.h" 55#include "vpnplugins.h" 56#include "vpnd.h" 57 58#define VPN_ADDR_DELETE 0x1 59 60struct vpn_address { 61 TAILQ_ENTRY(vpn_address) next; 62 int pid; 63 int flags; 64 char ip_address[16]; 65}; 66 67#define LB_MAX_SLAVE_AGE 10 68#define LB_IPCONFIG_TIMEOUT 60 69 70struct lb_slave { 71 TAILQ_ENTRY(lb_slave) next; 72 struct sockaddr_in server_address; 73 int age; 74 struct in_addr redirect_address; 75 u_int16_t max_connection; 76 u_int16_t cur_connection; 77 u_int32_t ratio; 78}; 79 80enum { 81 HEALTH_UNKNOWN = -1, 82 HEALTH_OK, 83 HEALTH_SICK, 84 HEALTH_DEAD 85}; 86 87// ---------------------------------------------------------------------------- 88// Private Globals 89// ---------------------------------------------------------------------------- 90static int listen_sockfd = -1; 91static int lb_sockfd = -1; 92static int evt_sockfd = -1; 93static int health_sockfd = -1; 94static int health_state = HEALTH_UNKNOWN; 95static struct vpn_channel the_vpn_channel; 96 97static double timeScaleSeconds; /* scale factor for machine absolute time to seconds */ 98static double timeScaleMicroSeconds; /* scale factor for machine absolute time to microseconds */ 99 100/* load balancing state information */ 101int lb_is_started = 0; // is load balancing currently started ? 102int lb_is_master = 0; // are we currently the master ? 103struct sockaddr_in lb_master_address; // address of a master, as discovered by the slave 104TAILQ_HEAD(, lb_slave) lb_slaves_list; // list opf slaves, as discoverd by the master server 105u_int16_t lb_cur_connections = 0; // nb of connections currently active 106u_int16_t lb_max_connections = 0; // max number of connections 107struct lb_slave *lb_next_slave = 0; // next slave to redirect the call to 108int lb_ipconfig_time = 0; // ip config confirmation timer 109 110 111 112TAILQ_HEAD(, vpn_address) save_address_list; 113TAILQ_HEAD(, vpn_address) free_address_list; 114TAILQ_HEAD(, vpn_address) child_list; 115 116// ---------------------------------------------------------------------------- 117// Function Prototypes 118// ---------------------------------------------------------------------------- 119extern int got_sig_chld(void); 120extern int got_sig_hup(void); 121extern int got_sig_usr1(void); 122extern int got_terminate(void); 123 124static pid_t fork_child(int fdSocket); 125static int reap_children(void); 126static int terminate_children(void); 127static int getabsolutetime(struct timeval *timenow); 128static void determine_next_slave(struct vpn_params* params); 129int start_load_balancing(struct vpn_params *params, fd_set *out_fds, int *out_fdmax); 130int stop_load_balancing(struct vpn_params *params, fd_set *out_fds); 131 132 133// ---------------------------------------------------------------------------- 134// init_address_lists 135// ---------------------------------------------------------------------------- 136void init_address_lists(void) 137{ 138 TAILQ_INIT(&free_address_list); 139 TAILQ_INIT(&save_address_list); 140 TAILQ_INIT(&child_list); 141 TAILQ_INIT(&lb_slaves_list); 142 143 lb_max_connections = 0; 144 lb_cur_connections = 0; 145} 146 147// ---------------------------------------------------------------------------- 148// add_address 149// ---------------------------------------------------------------------------- 150int add_address(char* ip_address) 151{ 152 struct vpn_address *address_slot; 153 int size; 154 155 if ((size = strlen(ip_address) + 1) > 16) 156 return -1; 157 158 address_slot = (struct vpn_address*)malloc(sizeof(struct vpn_address)); 159 if (address_slot == 0) 160 return -1; 161 162 lb_max_connections++; 163 164 /* %%%% this address stuff needs to be redone for IPv6 addresses */ 165 memcpy(address_slot->ip_address, ip_address, strlen(ip_address) + 1); 166 address_slot->flags = 0; 167 TAILQ_INSERT_TAIL(&free_address_list, address_slot, next); 168 169 return 0; 170} 171 172// ---------------------------------------------------------------------------- 173// add_address_range 174// ---------------------------------------------------------------------------- 175int add_address_range(char* ip_addr_start, char* ip_addr_end) 176{ 177 struct in_addr start_addr; 178 struct in_addr end_addr; 179 struct in_addr cur_addr; 180 char addr_str[16]; 181 char *ip_addr; 182 183 if (!ip_addr_end) 184 return add_address(ip_addr_start); 185 if (inet_pton(AF_INET, ip_addr_start, &start_addr) < 1) 186 return -1; 187 if (inet_pton(AF_INET, ip_addr_end, &end_addr) < 1) 188 return -1; 189 start_addr.s_addr = ntohl(start_addr.s_addr); 190 end_addr.s_addr = ntohl(end_addr.s_addr); 191 if (start_addr.s_addr > end_addr.s_addr) 192 return -1; 193 if (start_addr.s_addr == end_addr.s_addr) 194 return add_address(ip_addr_start); 195 196 for (; start_addr.s_addr <= end_addr.s_addr; start_addr.s_addr++) { 197 cur_addr = start_addr; 198 cur_addr.s_addr = htonl(cur_addr.s_addr); 199 if ((ip_addr = (char*)inet_ntop(AF_INET, &cur_addr, addr_str, 16))) { 200 if (add_address(ip_addr)) 201 return -1; 202 } else 203 return -1; 204 } 205 206 return 0; 207} 208 209// ---------------------------------------------------------------------------- 210// begin_address_update 211// ---------------------------------------------------------------------------- 212void begin_address_update(void) 213{ 214 struct vpn_address *address_slot; 215 216 // copy the free addresses to the save list 217 while ((address_slot = (struct vpn_address*)TAILQ_FIRST(&free_address_list))) { 218 TAILQ_REMOVE(&free_address_list, address_slot, next); 219 TAILQ_INSERT_TAIL(&save_address_list, address_slot, next); 220 } 221 222} 223 224// ---------------------------------------------------------------------------- 225// cancel_address_update 226// ---------------------------------------------------------------------------- 227void cancel_address_update(void) 228{ 229 struct vpn_address *address_slot; 230 231 // remove any new addresses 232 while ((address_slot = (struct vpn_address*)TAILQ_FIRST(&free_address_list))) { 233 TAILQ_REMOVE(&free_address_list, address_slot, next); 234 free(address_slot); 235 lb_max_connections--; 236 } 237 238 // copy the free addresses back from the save list 239 while ((address_slot = (struct vpn_address*)TAILQ_FIRST(&save_address_list))) { 240 TAILQ_REMOVE(&save_address_list, address_slot, next); 241 TAILQ_INSERT_TAIL(&free_address_list, address_slot, next); 242 } 243} 244 245// ---------------------------------------------------------------------------- 246// apply_address_update 247// ---------------------------------------------------------------------------- 248void apply_address_update(void) 249{ 250 struct vpn_address *address_slot; 251 struct vpn_address *child_address; 252 253 // remove the old free addresses 254 while ((address_slot = (struct vpn_address*)TAILQ_FIRST(&save_address_list))) { 255 TAILQ_REMOVE(&save_address_list, address_slot, next); 256 free(address_slot); 257 lb_max_connections--; 258 } 259 260 // search the child address list and match up with new addresses 261 // kill children using invalid addresses 262 TAILQ_FOREACH(child_address, &child_list, next) { 263 child_address->flags |= VPN_ADDR_DELETE; 264 TAILQ_FOREACH(address_slot, &free_address_list, next) { 265 if (!strcmp(child_address->ip_address, address_slot->ip_address)) { 266 TAILQ_REMOVE(&free_address_list, address_slot, next); // address match - remove from free list 267 free(address_slot); 268 lb_max_connections--; 269 child_address->flags &= ~VPN_ADDR_DELETE; // don't kill child 270 break; 271 } 272 } 273 if (child_address->flags & VPN_ADDR_DELETE) 274 while (kill(child_address->pid, SIGTERM) < 0) 275 if (errno != EINTR) { 276 vpnlog(LOG_ERR, "VPND: error terminating child - err = %s\n", strerror(errno)); 277 break; 278 } 279 } 280 281 vpnlog(LOG_DEBUG, "address list updated\n"); 282 283 reap_children(); 284 285} 286 287 288// ---------------------------------------------------------------------------- 289// address_avail 290// ---------------------------------------------------------------------------- 291int address_avail(void) 292{ 293 return (TAILQ_FIRST(&free_address_list) != 0); 294} 295 296//----------------------------------------------------------------------------- 297// init_plugin 298//----------------------------------------------------------------------------- 299int init_plugin(struct vpn_params *params) 300{ 301 char path[MAXPATHLEN], name[MAXPATHLEN], *p; 302 CFBundleRef pluginbdl, bdl; 303 CFURLRef pluginurl, url; 304 int (*start)(struct vpn_channel*, CFBundleRef, CFBundleRef, int debug, int log_verbose) = 0; 305 bool isPPP; 306 int len, err = -1; 307 308 bzero(&the_vpn_channel, sizeof(struct vpn_channel)); 309 if (params->plugin_path == 0) { 310 err = add_builtin_plugin(params, &the_vpn_channel); 311 if (err) 312 vpnlog(LOG_ERR, "Cannot initialize built-in channel\n"); 313 return err; 314 } 315 316 len = strlen(params->plugin_path); 317 if (len > 4 && !strcmp(¶ms->plugin_path[len - 4], ".ppp")) 318 isPPP = 1; 319 else if (len > 4 && !strcmp(¶ms->plugin_path[len - 4], ".vpn")) 320 isPPP = 0; 321 else { 322 vpnlog(LOG_ERR, "Plugin ''%s' has an incorrect suffix (must end with '.ppp' or '.vpn')\n", params->plugin_path); 323 return -1; 324 } 325 326 if (params->plugin_path[0] == '/') { 327 strlcpy(path, params->plugin_path, sizeof(path)); 328 for (p = ¶ms->plugin_path[len - 1]; *p != '/'; p--); 329 strncpy(name, p + 1, strlen(p) - 5); 330 *(name + (strlen(p) - 5)) = 0; 331 } 332 else { 333 strlcpy(path, PLUGINS_DIR, sizeof(path)); 334 strlcat(path, params->plugin_path, sizeof(path)); 335 strlcpy(name, params->plugin_path, sizeof(name) - 4); // leave space for .vpn 336 *(name + len - 4) = 0; 337 } 338 339 vpnlog(LOG_NOTICE, "Loading plugin %s\n", path); 340 341 if ((url = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8 *)path, strlen(path), TRUE))) { 342 if ((bdl = CFBundleCreate(NULL, url))) { 343 344 if (isPPP) { 345 if ((pluginurl = CFBundleCopyBuiltInPlugInsURL(bdl))) { 346 strlcat(path, "/", sizeof(path)); 347 CFURLGetFileSystemRepresentation(pluginurl, 0, (UInt8 *)(path+strlen(path)), MAXPATHLEN-strlen(path)); 348 CFRelease(pluginurl); 349 strlcat(path, "/", sizeof(path)); 350 strlcat(path, name, sizeof(path)); 351 strlcat(path, ".vpn", sizeof(path)); 352 353 if ((pluginurl = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8 *)path, strlen(path), TRUE))) { 354 355 if ((pluginbdl = CFBundleCreate(NULL, pluginurl))) { 356 357 // load the executable from the vpn plugin 358 if (CFBundleLoadExecutable(pluginbdl) 359 && (start = CFBundleGetFunctionPointerForName(pluginbdl, CFSTR("start")))) 360 err = (*start)(&the_vpn_channel, pluginbdl, bdl, params->debug, params->log_verbose); 361 362 CFRelease(pluginbdl); 363 } 364 CFRelease(pluginurl); 365 } 366 } 367 } 368 else { 369 // load the default executable 370 if (CFBundleLoadExecutable(bdl) 371 && (start = CFBundleGetFunctionPointerForName(bdl, CFSTR("start")))) 372 err = (*start)(&the_vpn_channel, bdl, NULL, params->debug, params->log_verbose); 373 } 374 375 CFRelease(bdl); 376 } 377 CFRelease(url); 378 } 379 380 if (err) { 381 vpnlog(LOG_ERR, "Unable to load plugin (error = %d)\n", err); 382 return -1; 383 } 384 385 if (the_vpn_channel.listen == 0 || the_vpn_channel.accept == 0 386 || the_vpn_channel.refuse == 0 || the_vpn_channel.close == 0) { 387 vpnlog(LOG_ERR, "Plugin channel not properly initialized\n"); 388 return -1; 389 } 390 391 //vpnlog(LOG_INFO, "Plugin loaded\n"); 392 393 return 0; 394} 395 396// ---------------------------------------------------------------------------- 397// get_plugin_args 398// ---------------------------------------------------------------------------- 399int get_plugin_args(struct vpn_params* params, int reload) 400{ 401 402 /* get any extra params from the plugin */ 403 if (the_vpn_channel.get_pppd_args) 404 if (the_vpn_channel.get_pppd_args(params, reload)) 405 return -1; 406 407 // Load Balancing is only supported for L2TP/IPSec protocol 408 if (params->lb_enable && !the_vpn_channel.lb_redirect) { 409 vpnlog(LOG_ERR, "Plugin does not support Load Balancing\n"); 410 params->lb_enable = 0; 411 } 412 413 return 0; 414} 415 416// ---------------------------------------------------------------------------- 417// call the ipconfig command 418// ---------------------------------------------------------------------------- 419int call_ipconfig(char *command, char *interface, struct in_addr *address, int timeout) 420{ 421 422 int pid, exitcode = -1, status; 423 char str[32], str1[32]; 424 425 426 if ((pid = fork()) < 0) 427 return 1; 428 429 if (pid == 0) { 430 int i; 431 for (i = getdtablesize() - 1; i >= 0; i--) close(i); 432 open("/dev/null", O_RDWR, 0); 433 dup(0); 434 dup(0); 435 inet_ntop(AF_INET, address, str, sizeof(str)); 436 snprintf(str1, sizeof(str1), "%d", timeout); 437 execle("/usr/sbin/ipconfig", "ipconfig", command, interface, "FAILOVER", str, "255.255.255.255", str1, (char *)0, (char *)0); 438 exit(1); 439 } 440 441 while (waitpid(pid, &status, 0) < 0) { 442 if (errno == EINTR) 443 continue; 444 return 1; 445 } 446 447 exitcode = WIFEXITED(status) ? WEXITSTATUS(status) : -1; 448 449 if (exitcode) 450 vpnlog(LOG_ERR, "Unable to configure IP Failover Service (error %d)\n", exitcode); 451 452 return exitcode; 453} 454 455// ---------------------------------------------------------------------------- 456// configure/unconfigure failover 457// ---------------------------------------------------------------------------- 458int configure_failover(char *interface, struct in_addr *address, int timeout) 459{ 460 int err = -1; 461 462 err = call_ipconfig("setservice", interface, address, timeout); 463 if (err) 464 vpnlog(LOG_ERR, "Unable to configure IP Failover Service (error %d)\n", err); 465 466 return err; 467} 468 469// ---------------------------------------------------------------------------- 470// delete load balancing pool address 471// ---------------------------------------------------------------------------- 472int unconfigure_failover(char *interface, struct in_addr *address) 473{ 474 int err = -1; 475 476 err = call_ipconfig("removeservice", interface, address, 0); 477 if (err) 478 vpnlog(LOG_ERR, "Unable to unconfigure IP Failover Service (error %d)\n", err); 479 480 return err; 481} 482 483// ---------------------------------------------------------------------------- 484// health_check 485// ---------------------------------------------------------------------------- 486int health_check(struct vpn_params *params, int event, fd_set *out_fds, int *out_fdmax) 487{ 488 int fd = health_sockfd, err, ret = 0; 489 490 err = the_vpn_channel.health_check(&fd, event); 491 492 /* check if health socket has changed */ 493 if (fd != health_sockfd) { 494 if (health_sockfd != -1) 495 FD_CLR(health_sockfd, out_fds); 496 health_sockfd = fd; 497 if (health_sockfd != -1) { 498 FD_SET(health_sockfd, out_fds); 499 if (*out_fdmax <= health_sockfd) 500 *out_fdmax = health_sockfd + 1; 501 } 502 } 503 504 switch (err) { 505 case 0: 506 if (health_state == HEALTH_SICK) { 507 vpnlog(LOG_ERR, "Health control check: server is back to normal...\n"); 508 // feeling better... 509 if (params->lb_enable) { 510 if (start_load_balancing(params, out_fds, out_fdmax) < 0) 511 ret = -1; 512 } 513 } 514 health_state = HEALTH_OK; 515 break; 516 517 case -2: 518 if (health_state == HEALTH_OK) { 519 vpnlog(LOG_ERR, "Health control check: server is sick...\n"); 520 } 521 health_state = HEALTH_SICK; 522 523 if (lb_is_started) 524 stop_load_balancing(params, out_fds); 525 break; 526 527 default: 528 case -1: 529 health_state = HEALTH_DEAD; 530 vpnlog(LOG_ERR, "Health control check: server is dead...\n"); 531 ret = -1; 532 break; 533 } 534 535 return ret; 536} 537 538// ---------------------------------------------------------------------------- 539// start load balancing 540// ---------------------------------------------------------------------------- 541int start_load_balancing(struct vpn_params *params, fd_set *out_fds, int *out_fdmax) 542{ 543 struct sockaddr_in listen_addr; 544 fd_set fds = *out_fds; 545 int fdmax = *out_fdmax; 546 struct kev_request kev_req; 547 548 if (lb_is_started) 549 return 0; 550 551 // Load Balancing is only supported for L2TP/IPSec protocol 552 if (params->lb_enable && !the_vpn_channel.lb_redirect) { 553 vpnlog(LOG_ERR, "Plugin does not support Load Balancing\n"); 554 params->lb_enable = 0; 555 } 556 557 558 evt_sockfd = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT); 559 if (evt_sockfd < 0) { 560 vpnlog(LOG_ERR, "Unable to create event socket (errno = %d)\n", errno); 561 goto fail; 562 } 563 564 FD_SET(evt_sockfd, &fds); 565 if (fdmax <= evt_sockfd) 566 fdmax = evt_sockfd + 1; 567 568 kev_req.vendor_code = KEV_VENDOR_APPLE; 569 kev_req.kev_class = KEV_NETWORK_CLASS; 570 kev_req.kev_subclass = KEV_INET_SUBCLASS; 571 ioctl(evt_sockfd, SIOCSKEVFILT, &kev_req); 572 573 lb_sockfd = socket(PF_INET, SOCK_DGRAM, 0); 574 if (lb_sockfd < 0) { 575 vpnlog(LOG_ERR, "Unable to create load balancing socket (errno = %d)\n", errno); 576 goto fail; 577 } 578 579 FD_SET(lb_sockfd, &fds); 580 if (fdmax <= lb_sockfd) 581 fdmax = lb_sockfd + 1; 582 583 bzero(&listen_addr, sizeof(listen_addr)); 584 listen_addr.sin_family = PF_INET; 585 listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); 586 listen_addr.sin_port = params->lb_port; 587 588 if (bind(lb_sockfd, (struct sockaddr*)&listen_addr, sizeof(listen_addr)) < 0 ){ 589 vpnlog(LOG_ERR, "Unable to bind load balancing socket (errno = %d)\n", errno); 590 goto fail; 591 } 592 593 // set master address 594 bzero(&lb_master_address, sizeof(lb_master_address)); 595 lb_master_address.sin_family = AF_INET; 596 lb_master_address.sin_len = sizeof(lb_master_address); 597 lb_master_address.sin_addr = params->lb_cluster_address; 598 lb_master_address.sin_port = params->lb_port; 599 600 configure_failover(params->lb_interface, ¶ms->lb_cluster_address, LB_IPCONFIG_TIMEOUT); 601 lb_ipconfig_time = LB_IPCONFIG_TIMEOUT - 10; 602 603 lb_is_master = find_address(&lb_master_address, params->lb_interface); 604 605 *out_fds = fds; 606 *out_fdmax = fdmax; 607 lb_is_started = 1; 608 lb_next_slave = 0; 609 vpnlog(LOG_NOTICE, "Load Balancing: Started\n"); 610 611 return 0; 612 613fail: 614 if (evt_sockfd >= 0) { 615 close(evt_sockfd); 616 evt_sockfd = -1; 617 } 618 if (lb_sockfd >= 0) { 619 close(lb_sockfd); 620 lb_sockfd = -1; 621 } 622 return -1; 623} 624 625// ---------------------------------------------------------------------------- 626// stop load balancing 627// ---------------------------------------------------------------------------- 628int stop_load_balancing(struct vpn_params *params, fd_set *out_fds) 629{ 630 631 if (!lb_is_started) 632 return 0; 633 634 if (evt_sockfd >= 0) { 635 FD_CLR(evt_sockfd, out_fds); 636 close(evt_sockfd); 637 evt_sockfd = -1; 638 } 639 if (lb_sockfd >= 0) { 640 FD_CLR(lb_sockfd, out_fds); 641 close(lb_sockfd); 642 lb_sockfd = -1; 643 } 644 645 unconfigure_failover(params->lb_interface, ¶ms->lb_cluster_address); 646 647 lb_is_master = 0; 648 lb_is_started = 0; 649 lb_next_slave = 0; 650 651 vpnlog(LOG_NOTICE, "Load Balancing: Stopped\n"); 652 653 return 0; 654} 655 656// ---------------------------------------------------------------------------- 657// determine which slave takes next call 658// ---------------------------------------------------------------------------- 659static void determine_next_slave(struct vpn_params *params) 660{ 661 struct lb_slave *slave, *oldslave; 662 u_int32_t a; 663 664 oldslave = lb_next_slave; 665 666 // determine the server that will take the next call 667 lb_next_slave = TAILQ_FIRST(&lb_slaves_list); 668 TAILQ_FOREACH(slave, &lb_slaves_list, next) { 669 if (slave->ratio < lb_next_slave->ratio) 670 lb_next_slave = slave; 671 } 672 673 // and inform racoon about the redirection 674 if (lb_next_slave && lb_next_slave != oldslave) { 675 676 a = ntohl(lb_next_slave->redirect_address.s_addr); 677 vpnlog(LOG_NOTICE, "Load Balancing: Next call will be redirected to slave with IP address %d.%d.%d.%d. Current slave load %d/%d.\n", 678 a >> 24 & 0xFF, a >> 16 & 0xFF, a >> 8 & 0xFF, a & 0xFF, lb_next_slave->cur_connection, lb_next_slave->max_connection); 679 680 if (the_vpn_channel.lb_redirect) { 681 the_vpn_channel.lb_redirect(¶ms->lb_cluster_address, &lb_next_slave->redirect_address); 682 } 683 } 684 685} 686 687#define LB_MSG_TYPE_UPDATE 1 688 689struct lb_message { 690 691// header 692 u_int16_t type; 693 u_int16_t len; 694 u_int8_t version; 695 u_int8_t reserved1; 696 u_int16_t reserved2; 697 698// version 1 699 u_int32_t redirect_address; //ip v4 700 u_int16_t max_connection; // 100 701 u_int16_t cur_connection; // 50 702 u_int32_t reserved3; 703 u_int32_t reserved4; 704 705}; 706 707// ---------------------------------------------------------------------------- 708// accept_connections 709// ---------------------------------------------------------------------------- 710void accept_connections(struct vpn_params* params) 711{ 712 713 pid_t pid_child; 714 fd_set fds, fds_save; 715 char addr_str[32]; 716 int i, child_sockfd, fdmax, err, hastimeout; 717 struct vpn_address *address_slot; 718 struct sockaddr_in addr; 719 socklen_t addrlen; 720 size_t datalen; 721 char data[1000]; 722 struct timeval timenow, timeout, timeend; 723 struct lb_message *lbmsg; 724 u_int16_t lbmsgtype; 725 struct lb_slave *slave; 726 u_int32_t a; 727 728 FD_ZERO(&fds_save); 729 fdmax = 0; 730 731 /* 732 open the new connection listening socket 733 */ 734 listen_sockfd = 0; 735 if (the_vpn_channel.listen) 736 listen_sockfd = the_vpn_channel.listen(); // initialize the plugin and get listen socket 737 738 if (listen_sockfd < 0) { 739 vpnlog(LOG_ERR, "Unable to initialize vpn plugin\n"); 740 goto fail; 741 } 742 743 if (listen_sockfd) { 744 FD_SET(listen_sockfd, &fds_save); 745 if (fdmax <= listen_sockfd) 746 fdmax = listen_sockfd + 1; 747 } 748 749 /* 750 health monitoring 751 */ 752 health_sockfd = -1; 753 754 /* 755 start the load balancing 756 */ 757 if (params->lb_enable) { 758 if (start_load_balancing(params, &fds_save, &fdmax) < 0) { 759 goto fail; 760 } 761 } 762 763 hastimeout = lb_is_started || the_vpn_channel.health_check; 764 765 if (hastimeout) { 766 getabsolutetime(&timeend); 767 timeend.tv_sec += 1; // timeout immediatly 768 } 769 770 /* 771 loop - listening for connection requests and other events 772 */ 773 while (!got_terminate()) { 774 775 if (hastimeout) { 776 getabsolutetime(&timenow); 777 timeout.tv_sec = timeend.tv_sec > timenow.tv_sec ? timeend.tv_sec - timenow.tv_sec : 0; 778 timeout.tv_usec = timeend.tv_usec - timenow.tv_usec; 779 if (timeout.tv_usec < 0) { 780 timeout.tv_usec += 1000000; 781 timeout.tv_sec -= 1; 782 } 783 if (timeout.tv_sec < 0) 784 timeout.tv_sec = timeout.tv_usec = 0; 785 786 } 787 788 fds = fds_save; 789 i = select(fdmax, &fds, NULL, NULL, hastimeout ? &timeout : 0); 790 791 // --------------- file descriptor selected -------------- 792 if (i > 0) { 793 794 /* event on new kernel event socket */ 795 if (lb_is_started && FD_ISSET (evt_sockfd, &fds)) { 796 char buf[256]; 797 struct kern_event_msg *ev_msg; 798 struct kev_in_data *inetdata; 799 800 if (recv(evt_sockfd, &buf, sizeof(buf), 0) != -1) { 801 ev_msg = (struct kern_event_msg *) &buf; 802 switch (ev_msg->event_code) { 803 case KEV_INET_NEW_ADDR: 804 inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 805 if (inetdata->ia_addr.s_addr == params->lb_cluster_address.s_addr) { 806 // our master address has been assigned. we are now the master server 807 vpnlog(LOG_NOTICE, "Load Balancing: Cluster address assigned. Server is becoming master...\n"); 808 lb_is_master = 1; 809 } 810 break; 811 case KEV_INET_ADDR_DELETED: 812 inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 813 if (inetdata->ia_addr.s_addr == params->lb_cluster_address.s_addr) { 814 // our master address has been deleted. we are not master anymore 815 vpnlog(LOG_NOTICE, "Load Balancing: Cluster address deleted. Server is no longer master...\n"); 816 lb_is_master = 0; 817 while ((slave = TAILQ_FIRST(&lb_slaves_list))) { 818 TAILQ_REMOVE(&lb_slaves_list, slave, next); 819 free(slave); 820 } 821 } 822 break; 823 824 } 825 } 826 } 827 828 /* event on load balancing socket */ 829 if (lb_is_started && FD_ISSET (lb_sockfd, &fds)) { 830 831 addrlen = sizeof(addr); 832 datalen = recvfrom (lb_sockfd, data, sizeof(data) - 1, 0, (struct sockaddr*)&addr, &addrlen); 833 if (datalen > 0) { 834 835 data[datalen] = 0; 836 lbmsg = (struct lb_message *)data; 837 lbmsgtype = ntohs(lbmsg->type); 838 839 if (lb_is_master && lbmsgtype == LB_MSG_TYPE_UPDATE) { 840 841 // search for slave in the list 842 TAILQ_FOREACH(slave, &lb_slaves_list, next) { 843 if (slave->server_address.sin_addr.s_addr == addr.sin_addr.s_addr) 844 break; 845 } 846 if (!slave) { 847 slave = malloc(sizeof(struct lb_slave)); 848 if (slave == 0) { 849 vpnlog(LOG_ERR, "cannot allocate memory for slave server.\n"); 850 break; 851 } 852 853 a = ntohl(addr.sin_addr.s_addr); 854 vpnlog(LOG_NOTICE, "Load Balancing: Slave server appeared with IP address %d.%d.%d.%d\n", a >> 24 & 0xFF, a >> 16 & 0xFF, a >> 8 & 0xFF, a & 0xFF); 855 bcopy(&addr, &slave->server_address, sizeof(addr)); 856 TAILQ_INSERT_TAIL(&lb_slaves_list, slave, next); 857 858 } 859 860 slave->age = LB_MAX_SLAVE_AGE; 861 slave->redirect_address.s_addr = lbmsg->redirect_address; 862 slave->max_connection = ntohs(lbmsg->max_connection); 863 slave->cur_connection = ntohs(lbmsg->cur_connection); 864 slave->ratio = (lbmsg->cur_connection < lbmsg->max_connection) ? (lbmsg->cur_connection * 1000)/lbmsg->max_connection : 1000; 865 a = ntohl(lbmsg->redirect_address); 866// vpnlog(LOG_DEBUG, "Load Balancing: Slave server update. Redirection address is %d.%d.%d.%d, current load is %d/%d\n", 867// a >> 24 & 0xFF, a >> 16 & 0xFF, a >> 8 & 0xFF, a & 0xFF, slave->cur_connection, slave->max_connection); 868 869 determine_next_slave(params); 870 } 871 } 872 } 873 874 /* event on health control socket */ 875 if (health_sockfd != -1 && FD_ISSET (health_sockfd, &fds)) { 876 err = health_check(params, 1, &fds_save, &fdmax); 877 if (err < 0) 878 goto fail; 879 } 880 881 /* event on new connection listening socket */ 882 if (FD_ISSET (listen_sockfd, &fds)) { 883 884 address_slot = (struct vpn_address*)TAILQ_FIRST(&free_address_list); 885 if (address_slot == 0) { 886 if ((child_sockfd = the_vpn_channel.refuse()) < 0) { 887 vpnlog(LOG_ERR, "Error while refusing incoming call %s\n", strerror(errno)); 888 continue; 889 } 890 } else { 891 if ((child_sockfd = the_vpn_channel.accept()) < 0) { 892 vpnlog(LOG_ERR, "Error accepting incoming call %s\n", strerror(errno)); 893 continue; 894 } 895 } 896 if (child_sockfd == 0) 897 continue; 898 // Turn this connection over to a child. 899 while ((pid_child = fork_child(child_sockfd)) < 0) { 900 if (errno != EINTR) { 901 vpnlog(LOG_ERR, "Error during fork = %s\n", strerror(errno)); 902 goto fail; 903 } else if (got_terminate()) 904 goto fail; 905 } 906 if (pid_child && address_slot) { // parent 907 vpnlog(LOG_NOTICE, "Incoming call... Address given to client = %s\n", address_slot->ip_address); 908 TAILQ_REMOVE(&free_address_list, address_slot, next); 909 address_slot->pid = pid_child; 910 TAILQ_INSERT_TAIL(&child_list, address_slot, next); 911 lb_cur_connections++; 912 } else if (address_slot) { 913 // child 914 snprintf(addr_str, sizeof(addr_str), ":%s", address_slot->ip_address); 915 params->exec_args[params->next_arg_index] = addr_str; // setup ip address in arg list 916 params->exec_args[params->next_arg_index + 1] = 0; // make sure arg list end with zero 917 execve(PATH_PPPD, params->exec_args, NULL); // launch it 918 919 /* not reached except if there is an error */ 920 vpnlog(LOG_ERR, "execve failed during exec of /usr/sbin/pppd\nARGUMENTS\n"); 921 for (i = 1; i < MAXARG && i < params->next_arg_index; i++) { 922 if (params->exec_args[i]) 923 vpnlog(LOG_DEBUG, "%d : %s\n", i, params->exec_args[i]); 924 } 925 vpnlog(LOG_DEBUG, "\n"); 926 927 exit(1); 928 } 929 } 930 } 931 932 // --------------- timeout expired -------------- 933 else if (i == 0) { 934 935 // check health 936 if (the_vpn_channel.health_check) { 937 err = health_check(params, 0, &fds_save, &fdmax); 938 if (err < 0) 939 goto fail; 940 } 941 942 if (lb_is_started) { 943 // update the master every second 944 945 lbmsg = (struct lb_message *)data; 946 bzero(lbmsg, sizeof(struct lb_message)); 947 lbmsg->type = htons(LB_MSG_TYPE_UPDATE); 948 lbmsg->len = htons(sizeof(*lbmsg)); 949 950 // fill in actual load balancing data 951 lbmsg->redirect_address = params->lb_redirect_address.s_addr; 952 lbmsg->max_connection = htons(lb_max_connections); 953 lbmsg->cur_connection = htons(lb_cur_connections); 954 955 a = ntohl(params->lb_redirect_address.s_addr); 956 // vpnlog(LOG_DEBUG, "Load Balancing: Sending update to master server. Updating my master. Redirection address is %d.%d.%d.%d, current load is %d/%d\n", 957 // a >> 24 & 0xFF, a >> 16 & 0xFF, a >> 8 & 0xFF, a & 0xFF, lb_cur_connections, lb_max_connections); 958 959 if (sendto(lb_sockfd, data, sizeof(*lbmsg), 0, (struct sockaddr*)&lb_master_address, sizeof(lb_master_address)) < 0) { 960 vpnlog(LOG_ERR, "Load balancing: failed to send update (%s)", strerror(errno)); 961 } 962 963 // if we are a master, check on slave age 964 if (lb_is_master) { 965 966 TAILQ_FOREACH(slave, &lb_slaves_list, next) { 967 if (--slave->age == 0) { 968 a = ntohl(slave->server_address.sin_addr.s_addr); 969 vpnlog(LOG_NOTICE, "Load Balancing: Slave server with IP address %d.%d.%d.%d disappeared\n", a >> 24 & 0xFF, a >> 16 & 0xFF, a >> 8 & 0xFF, a & 0xFF); 970 TAILQ_REMOVE(&lb_slaves_list, slave, next); 971 if (slave == lb_next_slave) { 972 lb_next_slave = 0; 973 determine_next_slave(params); 974 } 975 free(slave); 976 } 977 } 978 } 979 980 lb_ipconfig_time--; 981 if (lb_ipconfig_time <= 0) { 982 configure_failover(params->lb_interface, ¶ms->lb_cluster_address, LB_IPCONFIG_TIMEOUT); 983 lb_ipconfig_time = LB_IPCONFIG_TIMEOUT - 10; 984 } 985 } 986 987 getabsolutetime(&timeend); 988 timeend.tv_sec += 1; // 1 second probes 989 990 } 991 // --------------- error or interrupt -------------- 992 else { 993 if (errno != EINTR) { 994 vpnlog(LOG_ERR, "Unexpected result from select - err = %s\n", strerror(errno)); 995 996 goto fail; 997 } 998 } 999 1000 if (got_sig_chld()) 1001 reap_children(); 1002 if (got_sig_usr1()) 1003 toggle_debug(); 1004 if (got_sig_hup()) { 1005 1006 if (lb_is_started) 1007 stop_load_balancing(params, &fds_save); 1008 1009 update_prefs(); 1010 1011 // restart load balancing 1012 if (params->lb_enable) { 1013 if (start_load_balancing(params, &fds_save, &fdmax) < 0) 1014 goto fail; 1015 } 1016 } 1017 } 1018 1019fail: 1020 if (lb_is_started) 1021 stop_load_balancing(params, &fds_save); 1022 if (the_vpn_channel.close) 1023 the_vpn_channel.close(); 1024 terminate_children(); 1025} 1026 1027 1028 1029//----------------------------------------------------------------------------- 1030// fork_child 1031//----------------------------------------------------------------------------- 1032static pid_t fork_child(int fdSocket) 1033{ 1034 register pid_t pidChild = 0 ; 1035 int i; 1036 1037 errno = 0 ; 1038 1039 switch (pidChild = fork ()) { 1040 case 0: // in child 1041 break ; 1042 case -1: // error 1043 syslog(LOG_ERR, "fork() failed: %m") ; 1044 /* FALLTHRU */ 1045 default: // parent 1046 close (fdSocket) ; 1047 return pidChild ; 1048 } 1049 1050 for (i = getdtablesize() - 1; i >= 0; i--) 1051 if (i != fdSocket) 1052 close(i); 1053 dup2 (fdSocket, STDIN_FILENO) ; 1054 open("/dev/null", O_RDWR, 0); 1055 open("/dev/null", O_RDWR, 0); 1056 close (fdSocket) ; 1057 1058 return pidChild ; 1059} 1060 1061 1062//----------------------------------------------------------------------------- 1063// reap_children 1064//----------------------------------------------------------------------------- 1065static int reap_children(void) 1066{ 1067 1068 int pid, status; 1069 struct vpn_address *address_slot; 1070 1071 if (!TAILQ_FIRST(&child_list)) 1072 return 0; 1073 1074 /* loop on waitpid collecting children and freeing the addresses */ 1075 while ((pid = waitpid(-1, &status, WNOHANG)) != -1 && pid != 0) { 1076 // find the child in the child list - remove it and free the address 1077 // back to the free address list 1078 TAILQ_FOREACH(address_slot, &child_list, next) { 1079 if (address_slot->pid == pid) { 1080 vpnlog(LOG_NOTICE, " --> Client with address = %s has hungup\n", address_slot->ip_address); 1081 TAILQ_REMOVE(&child_list, address_slot, next); 1082 lb_cur_connections--; 1083 if (address_slot->flags & VPN_ADDR_DELETE) { // address no longer valid? 1084 free(address_slot); 1085 lb_max_connections--; 1086 } 1087 else { 1088 TAILQ_INSERT_TAIL(&free_address_list, address_slot, next); 1089 } 1090 if (WIFSIGNALED(status)) 1091 vpnlog(LOG_WARNING, "Child process (pid %d) terminated with signal %d", pid, WTERMSIG(status)); 1092 break; 1093 } 1094 } 1095 } 1096 1097 if (pid == -1) 1098 if (errno != EINTR) { 1099 //syslog(LOG_ERR, "Error waiting for child process: %m"); 1100 return -1; 1101 } 1102 return 0; 1103} 1104 1105//----------------------------------------------------------------------------- 1106// terminate_children 1107//----------------------------------------------------------------------------- 1108static int terminate_children(void) 1109{ 1110 1111 struct vpn_address *child; 1112 1113 /* loop on waitpid collecting children and freeing the addresses */ 1114 while ((child = (struct vpn_address*)TAILQ_FIRST(&child_list))) { 1115 while (kill(child->pid, SIGTERM) < 0) 1116 if (errno != EINTR) { 1117 vpnlog(LOG_ERR, "Error terminating child - err = %s\n", strerror(errno)); 1118 break; 1119 } 1120 TAILQ_REMOVE(&child_list, child, next); 1121 lb_cur_connections--; 1122 TAILQ_INSERT_TAIL(&free_address_list, child, next); 1123 } 1124 1125 return 0; 1126} 1127 1128/* ----------------------------------------------------------------------------- 1129get mach asbolute time, for timeout purpose independent of date changes 1130----------------------------------------------------------------------------- */ 1131int getabsolutetime(struct timeval *timenow) 1132{ 1133 double now; 1134 1135 if (timeScaleSeconds == 0) { 1136 mach_timebase_info_data_t timebaseInfo; 1137 if (mach_timebase_info(&timebaseInfo) == KERN_SUCCESS) { // returns scale factor for ns 1138 timeScaleMicroSeconds = ((double) timebaseInfo.numer / (double) timebaseInfo.denom) / 1000; 1139 timeScaleSeconds = timeScaleMicroSeconds / 1000000; 1140 } 1141 else 1142 return -1; 1143 } 1144 1145 now = mach_absolute_time(); 1146 timenow->tv_sec = now * timeScaleSeconds; 1147 timenow->tv_usec = (now * timeScaleMicroSeconds) - ((double)timenow->tv_sec * 1000000); 1148 return 0; 1149} 1150 1151