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/* ----------------------------------------------------------------------------- 25 * 26 * Theory of operation : 27 * 28 * plugin to add PPTP client support to pppd. 29 * 30----------------------------------------------------------------------------- */ 31 32 33/* ----------------------------------------------------------------------------- 34 Includes 35----------------------------------------------------------------------------- */ 36 37#include <stdio.h> 38#include <ctype.h> 39#include <stdlib.h> 40#include <string.h> 41#include <unistd.h> 42#include <signal.h> 43#include <errno.h> 44#include <fcntl.h> 45#include <syslog.h> 46#include <netdb.h> 47#include <pwd.h> 48#include <setjmp.h> 49#include <sys/param.h> 50#include <sys/types.h> 51#include <sys/wait.h> 52#include <sys/time.h> 53#include <sys/resource.h> 54#include <sys/socket.h> 55#include <sys/stat.h> 56#include <sys/socket.h> 57#include <sys/sysctl.h> 58#include <netinet/in.h> 59#include <arpa/inet.h> 60#include <syslog.h> 61#include <sys/ioctl.h> 62#include <net/if.h> 63#include <net/if_media.h> 64#include <net/route.h> 65#include <pthread.h> 66#include <sys/kern_event.h> 67#include <netinet/in_var.h> 68#include <netinet/tcp.h> 69#include <net/if_dl.h> 70#include <ifaddrs.h> 71 72#include <CoreFoundation/CFNumber.h> 73#include <CoreFoundation/CFBundle.h> 74#include <SystemConfiguration/SystemConfiguration.h> 75 76#define APPLE 1 77 78#include "../../../Controller/ppp_msg.h" 79#include "../../../Family/ppp_defs.h" 80#include "../../../Family/if_ppp.h" 81#include "../../../Family/ppp_domain.h" 82#include "../PPTP-extension/PPTP.h" 83#include "../../../Helpers/pppd/pppd.h" 84#include "../../../Helpers/pppd/fsm.h" 85#include "../../../Helpers/pppd/lcp.h" 86#include "pptp.h" 87 88#if TARGET_OS_EMBEDDED 89#include <CoreTelephony/CTServerConnectionPriv.h> 90#endif 91 92/* ----------------------------------------------------------------------------- 93 Definitions 94----------------------------------------------------------------------------- */ 95 96#define MODE_CONNECT "connect" 97#define MODE_LISTEN "listen" 98#define MODE_ANSWER "answer" 99 100#define PPTP_MIN_HDR_SIZE 44 /* IPHdr(20) + GRE(16) + PPP/MPPE(8) */ 101 102#define PPTP_RETRY_CONNECT_CODE 1 103 104#define PPTP_DEFAULT_WAIT_IF_TIMEOUT 20 /* seconds */ 105 106#define MAX_CONNECT_RETRIES 10 107 108/* ----------------------------------------------------------------------------- 109 Forward declarations 110----------------------------------------------------------------------------- */ 111 112void pptp_process_extra_options(); 113void pptp_check_options(); 114int pptp_pre_start_link_check(); 115int pptp_connect(int *errorcode); 116void pptp_disconnect(); 117void pptp_close(); 118void pptp_cleanup(); 119int pptp_establish_ppp(int); 120void pptp_wait_input(); 121void pptp_disestablish_ppp(int); 122void pptp_link_down(void *arg, uintptr_t p); 123 124static void pptp_echo_check(); 125static void pptp_stop_echo_check(); 126static void pptp_echo_timeout(void *arg); 127static void pptp_send_echo_request(); 128static void pptp_link_failure(); 129static void closeall(); 130static u_long load_kext(char *kext, int byBundleID); 131static boolean_t host_gateway(int cmd, struct in_addr host, struct in_addr gateway, char *ifname, int isnet); 132static int pptp_set_peer_route(); 133static int pptp_clean_peer_route(); 134static void pptp_ip_up(void *arg, uintptr_t p); 135u_int32_t pptp_get_if_baudrate(char *if_name); 136u_int32_t pptp_get_if_media(char *if_name); 137u_int32_t pptp_get_if_mtu(char *if_name); 138static void pptp_start_wait_interface (); 139static void pptp_stop_wait_interface (); 140static void pptp_wait_interface_timeout (void *arg); 141static void enable_keepalive (int fd); 142 143 144/* ----------------------------------------------------------------------------- 145 PPP globals 146----------------------------------------------------------------------------- */ 147 148int interface_media = 0; 149 150static int ctrlsockfd = -1; /* control socket (TCP) file descriptor */ 151static int datasockfd = -1; /* data socket (GRE) file descriptor */ 152static int eventsockfd = -1; /* event socket to detect interface change */ 153static CFBundleRef bundle = 0; /* our bundle ref */ 154 155/* option variables */ 156static char *mode = MODE_CONNECT; /* connect mode by default */ 157static bool noload = 0; /* don't load the kernel extension */ 158 159static u_int16_t our_call_id = 0; /* pptp call id */ 160static u_int16_t peer_call_id = 0; /* pptp peer's calld id */ 161static u_int16_t our_window = PPTP_RECEIVE_WINDOW;/* our receive window size */ 162static u_int16_t peer_ppd = 0; /* peer packet processing delay */ 163static u_int16_t our_ppd = 0; /* our packet processing delay */ 164static u_int16_t peer_window = 0; /* peer's receive window size */ 165static u_int16_t maxtimeout = 64; /* Maximum adaptative timeout (in seconds) */ 166static struct in_addr peeraddress; /* the other side IP address */ 167static int num_alt_peer_address = 0; 168static struct in_addr alt_peer_address[MAX_CONNECT_RETRIES]; /* the other side IP address */ 169static struct sockaddr_in ouraddress; /* our side IP address */ 170static struct in_addr ip_zeros = { 0 }; 171static u_int8_t routeraddress[16]; 172static u_int8_t interface[17]; 173static pthread_t resolverthread = 0; 174static int resolverfds[2]; 175#if TARGET_OS_EMBEDDED 176static pthread_t edgethread = 0; 177static int edgefds[2]; 178#endif 179static bool linkdown = 0; /* flag set when we receive link down event */ 180static int peer_route_set = 0; /* has a route to the peer been set ? */ 181static int transport_up = 1; 182static int wait_interface_timer_running = 0; 183 184/* 185Fast echo request procedure is run when a networking change is detected 186Echos are sent every 5 seconds for 30 seconds, or until a reply is received 187If the network is detected dead, the the tunnel is disconnected. 188Echos are not sent during normal operation. 189*/ 190static int echo_interval = 5; /* Interval between echo-requests */ 191static int echo_fails = 6; /* Tolerance to unanswered echo-requests */ 192static int echo_timer_running = 0; 193static int echos_pending = 0; 194static int echo_identifier = 0; 195static int echo_active = 0; 196static int tcp_keepalive = 0; 197static int wait_if_timeout = PPTP_DEFAULT_WAIT_IF_TIMEOUT; 198static int scaled_wait_if_timeout = PPTP_DEFAULT_WAIT_IF_TIMEOUT; 199 200extern int kill_link; 201extern CFStringRef serviceidRef; /* from pppd/sys_MacOSX.c */ 202extern SCDynamicStoreRef cfgCache; /* from pppd/sys_MacOSX.c */ 203 204/* option descriptors */ 205option_t pptp_options[] = { 206 { "nopptpload", o_bool, &noload, 207 "Don't try to load the PPTP kernel extension", 1 }, 208 { "pptpmode", o_string, &mode, 209 "Configure configuration mode [connect, listen, answer]" }, 210 { "pptpmaxtimeout", o_int, &maxtimeout, 211 "Maximum adaptative timeout" }, 212 { "pptp-fast-echo-interval", o_int, &echo_interval, 213 "Fast echo interval to reassert link" }, 214 { "pptp-fast-echo-failure", o_int, &echo_fails, 215 "Fast echo failure to reassert link" }, 216 { "pptp-tcp-keepalive", o_int, &tcp_keepalive, 217 "TCP keepalive interval" }, 218 { "pptpwaitiftimeout", o_int, &wait_if_timeout, 219 "How long do we wait for our transport interface to come back after interface events" }, 220 { NULL } 221}; 222 223 224void pptp_init_session __P((char *, u_int32_t, struct in_addr *, link_failure_func)); 225 226static ppp_session_t pptp_session = PPP_SESSION_INITIALIZER(); 227 228/* ----------------------------------------------------------------------------- 229plugin entry point, called by pppd 230----------------------------------------------------------------------------- */ 231int start(CFBundleRef ref) 232{ 233 234 bundle = ref; 235 CFRetain(bundle); 236 237 // hookup our socket handlers 238 bzero(the_channel, sizeof(struct channel)); 239 the_channel->options = pptp_options; 240 the_channel->process_extra_options = pptp_process_extra_options; 241 the_channel->wait_input = pptp_wait_input; 242 the_channel->check_options = pptp_check_options; 243 the_channel->pre_start_link_check = pptp_pre_start_link_check; 244 the_channel->connect = pptp_connect; 245 the_channel->disconnect = pptp_disconnect; 246 the_channel->cleanup = pptp_cleanup; 247 the_channel->close = pptp_close; 248 the_channel->establish_ppp = pptp_establish_ppp; 249 the_channel->disestablish_ppp = pptp_disestablish_ppp; 250 // use the default config functions 251 the_channel->send_config = generic_send_config; 252 the_channel->recv_config = generic_recv_config; 253 254 add_notifier(&link_down_notifier, pptp_link_down, 0); 255 add_notifier(&ip_up_notify, pptp_ip_up, 0); 256 257 return 0; 258} 259 260/* ----------------------------------------------------------------------------- 261----------------------------------------------------------------------------- */ 262void pptp_process_extra_options() 263{ 264 if (!strcmp(mode, MODE_ANSWER)) { 265 // make sure we get a file descriptor > 2 so that pppd can detach and close 0,1,2 266 ctrlsockfd = dup(0); 267 } 268} 269 270/* ----------------------------------------------------------------------------- 271do consistency checks on the options we were given 272----------------------------------------------------------------------------- */ 273void pptp_check_options() 274{ 275 if (strcmp(mode, MODE_CONNECT) 276 && strcmp(mode, MODE_LISTEN) 277 && strcmp(mode, MODE_ANSWER)) { 278 error("PPTP incorrect mode : '%s'", mode ? mode : ""); 279 mode = MODE_CONNECT; 280 } 281 282 /* 283 reuse pppd redial functionality to retry connection 284 retry every 3 seconds for the duration of the extra time 285 do not report busy state 286 */ 287 if (extraconnecttime) { 288 busycode = PPTP_RETRY_CONNECT_CODE; 289 redialtimer = 3 ; 290 redialcount = extraconnecttime / redialtimer; 291 hasbusystate = 0; 292 } 293 294} 295 296/* ----------------------------------------------------------------------------- 297----------------------------------------------------------------------------- */ 298void pptp_link_down(void *arg, uintptr_t p) 299{ 300 linkdown = 1; 301} 302 303/* ----------------------------------------------------------------------------- 304----------------------------------------------------------------------------- */ 305static void pptp_start_wait_interface () 306{ 307 int timeout_scale_factor = 0; 308 309 if (!wait_underlying_interface_up && lcp_echo_interval) { 310 wait_underlying_interface_up = 1; 311 } 312 // the interface timer takes priority over the mapping timer 313 ppp_block_public_nat_port_mapping_timer(); 314 315 if (wait_interface_timer_running != 0) 316 return; 317 318#if !TARGET_OS_EMBEDDED 319 // increase the timeout if we're waiting for a wireless interface 320 if (IFM_TYPE(interface_media) == IFM_IEEE80211) { 321 timeout_scale_factor = 2; 322 } 323#endif /* !iPhone */ 324 scaled_wait_if_timeout = (wait_if_timeout << timeout_scale_factor); 325 notice("starting wait-interface timer for pptp: %d secs", scaled_wait_if_timeout); 326 TIMEOUT (pptp_wait_interface_timeout, 0, scaled_wait_if_timeout); 327 wait_interface_timer_running = 1; 328} 329 330/* ----------------------------------------------------------------------------- 331----------------------------------------------------------------------------- */ 332static void pptp_stop_wait_interface () 333{ 334 ppp_variable_echo_start(); 335 336 if (wait_interface_timer_running) { 337 UNTIMEOUT (pptp_wait_interface_timeout, 0); 338 wait_interface_timer_running = 0; 339 } 340 ppp_unblock_public_nat_port_mapping_timer(); 341} 342 343/* ----------------------------------------------------------------------------- 344----------------------------------------------------------------------------- */ 345static void pptp_wait_interface_timeout (void *arg) 346{ 347 if (wait_interface_timer_running != 0) { 348 wait_interface_timer_running = 0; 349 log_vpn_interface_address_event(__FUNCTION__, NULL, scaled_wait_if_timeout, interface, &ouraddress.sin_addr); 350 // our transport interface didn't come back, take down the connection 351 pptp_link_failure(); 352 } 353} 354 355/* ----------------------------------------------------------------------------- 356called back everytime we go out of select, and data needs to be read 357the hook is called and has a chance to get data out of its file descriptor 358in the case of PPTP, we get control data on the socket 359or get awaken when connection is closed 360----------------------------------------------------------------------------- */ 361void pptp_wait_input() 362{ 363 int err, found; 364 struct ifaddrs *ifap = NULL; 365 366#if 0 367 // Code removed. See radar 9129161 368 if (linkdown && !hungup) { 369 notice("PPTP linkdown"); 370 pptp_link_failure(); 371 return; 372 } 373#endif 374 375 if (eventsockfd != -1 && is_ready_fd(eventsockfd)) { 376 377 char buf[256] __attribute__ ((aligned(4))); // Wcast-align fix - force alignment 378 char ev_if[32]; 379 struct kern_event_msg *ev_msg; 380 struct kev_in_data *inetdata; 381 382 if (recv(eventsockfd, &buf, sizeof(buf), 0) != -1) { 383 ev_msg = ALIGNED_CAST(struct kern_event_msg *) &buf; 384 inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 385 log_vpn_interface_address_event(__FUNCTION__, ev_msg, wait_if_timeout, interface, &ouraddress.sin_addr); 386 switch (ev_msg->event_code) { 387 case KEV_INET_NEW_ADDR: 388 case KEV_INET_CHANGED_ADDR: 389 case KEV_INET_ADDR_DELETED: 390 snprintf(ev_if, sizeof(ev_if), "%s%d", inetdata->link_data.if_name, inetdata->link_data.if_unit); 391 // check if changes occured on the interface we are using 392 if (!strncmp(ev_if, (char*)interface, sizeof(interface))) { 393 if (inetdata->link_data.if_family == APPLE_IF_FAM_PPP 394 || echo_interval == 0 395 || echo_fails == 0) { 396 // disconnect immediatly 397 pptp_link_failure(); 398 } 399 else { 400 401 /* check if address still exist */ 402 found = 0; 403 if (getifaddrs(&ifap) == 0) { 404 struct ifaddrs *ifa; 405 for (ifa = ifap; ifa && !found ; ifa = ifa->ifa_next) { 406 found = (ifa->ifa_name 407 && ifa->ifa_addr 408 && !strncmp(ifa->ifa_name, (char*)interface, sizeof(interface)) 409 && ifa->ifa_addr->sa_family == AF_INET 410 && (ALIGNED_CAST(struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == ouraddress.sin_addr.s_addr); 411 } 412 freeifaddrs(ifap); 413 } 414 415 if (found) { 416 417 // no meaningful change, or address came back. Cancel timer if it was on. 418 if (transport_up == 0) { 419 420 /* 421 Our transport interface comes back with the same address. 422 Stop waiting for interface. 423 A smarter algorithm should be implemented here. 424 */ 425 transport_up = 1; 426 if (phase == PHASE_WAITING) 427 new_phase(PHASE_RUNNING); 428 pptp_stop_wait_interface(); 429 430 // give time to check for connectivity 431 /* Clear the parameters for generating echo frames */ 432 echos_pending = 0; 433 echo_active = 1; 434 435 /* If a timeout interval is specified then start the timer */ 436 if (echo_interval != 0) 437 pptp_echo_check(); 438 } 439 } 440 else { 441 // quick exit if there has been an unrecoverable change in interface/service 442 if (check_vpn_interface_or_service_unrecoverable(cfgCache, 443 __FUNCTION__, 444 ev_msg, 445 (char*)interface)) { 446 error("PPTP: the underlying interface/service has changed unrecoverably\n"); 447 transport_up = 0; 448 pptp_link_failure(); 449 break; 450 } 451 452 if (transport_up == 1) { 453 transport_up = 0; 454 if (phase == PHASE_RUNNING) 455 new_phase(PHASE_WAITING); 456 pptp_start_wait_interface(); 457 } else { 458 // transport is still down: check if there was a valid address change 459 if (check_vpn_interface_address_change(wait_interface_timer_running /* && !transport_up */, 460 ev_msg, 461 (char*)interface, 462 interface_media, 463 &ouraddress.sin_addr)) { 464 error("PPTP: the underlying interface %s address changed\n", 465 interface); 466 // disconnect immediately 467 pptp_link_failure(); 468 } 469 } 470 } 471 472 } 473 } else { 474 /* if transport is still down: ignore deletes, and check if this alternative interface has a valid address */ 475 if (check_vpn_interface_alternate((!transport_up && wait_interface_timer_running), 476 ev_msg, 477 (char*)interface)) { 478 error("PPTP: an alternative interface %s was detected while the underlying interface %s was down\n", 479 ev_if, interface); 480 // disconnect immediately 481 pptp_link_failure(); 482 } 483 } 484 break; 485 } 486 } 487 } 488 489 if (ctrlsockfd != -1 && is_ready_fd(ctrlsockfd)) { 490 491 err = pptp_data_in(ctrlsockfd); 492 if (err < 0) { 493 // looks like we have been disconnected... 494 // the status is updated only if link is not already down 495 if (linkdown == 0) { 496 notice("PPTP hangup"); 497 status = EXIT_HANGUP; 498 } 499 remove_fd(ctrlsockfd); 500 remove_fd(eventsockfd); 501 hungup = 1; 502 lcp_lowerdown(0); /* PPTP link is no longer available */ 503 link_terminated(0); 504 ppp_auxiliary_probe_stop(); 505 pptp_clear_nat_port_mapping(); 506 ppp_session_clear(&pptp_session); 507 session = NULL; 508 } 509 } 510 511 ppp_process_nat_port_mapping_events(); 512 ppp_process_auxiliary_probe_input(); 513} 514 515/* ----------------------------------------------------------------------------- 516----------------------------------------------------------------------------- */ 517void *pptp_resolver_thread(void *arg) 518{ 519 struct hostent *host; 520 char result = -1; 521 int count, fd; 522 u_int8_t rd8; 523 524 if (pthread_detach(pthread_self()) == 0) { 525 526 // try to resolve the name 527 if ((host = gethostbyname(remoteaddress))) { 528 529 for (count = 0; host->h_addr_list[count]; count++); 530 531 rd8 = 0; 532 fd = open("/dev/random", O_RDONLY); 533 if (fd) { 534 read(fd, &rd8, sizeof(rd8)); 535 close(fd); 536 } 537 538 bzero(&peeraddress, sizeof(peeraddress)); 539 if (count) 540 peeraddress = *ALIGNED_CAST(struct in_addr*)host->h_addr_list[rd8 % count]; 541 bzero(alt_peer_address, sizeof(alt_peer_address)); 542 num_alt_peer_address = 0; 543 if (count > 1) { 544 while (num_alt_peer_address < (count - 1) && 545 num_alt_peer_address < MAX_CONNECT_RETRIES) { 546 alt_peer_address[num_alt_peer_address] = *ALIGNED_CAST(struct in_addr*)host->h_addr_list[(rd8 + num_alt_peer_address + 1)% count]; 547 num_alt_peer_address++; 548 } 549 } 550 result = 0; 551 } 552 } 553 554 write(resolverfds[1], &result, 1); 555 return 0; 556} 557 558#if TARGET_OS_EMBEDDED 559static 560void callbackEDGE(CTServerConnectionRef connection, CFStringRef notification, CFDictionaryRef notificationInfo, void* info) { 561 562 /* not used */ 563} 564 565/* ----------------------------------------------------------------------------- 566 ----------------------------------------------------------------------------- */ 567void *pptp_edge_thread(void *arg) 568{ 569 char result = -1; 570 int count; 571 CTServerConnectionRef edgeConnection; 572 _CTServerConnectionContext ctxt = { 0, NULL, NULL, NULL, NULL }; 573 Boolean active = FALSE; 574 CTError cterror = { kCTErrorDomainNoError, 0 }; 575 576 if (pthread_detach(pthread_self()) == 0) { 577 578 edgeConnection = _CTServerConnectionCreate(kCFAllocatorDefault, callbackEDGE, &ctxt); 579 if (edgeConnection) { 580 _CTServerConnectionSetPacketContextActiveByServiceType(edgeConnection, kCTDataConnectionServiceTypeInternet, TRUE); 581 582 count = PPPD_WWAN_INTERFACE_TIMEOUT; 583 cterror = _CTServerConnectionGetPacketContextActive(edgeConnection, 0, &active); 584 while (!cterror.error && !active && count--) { 585 sleep(1); 586 cterror = _CTServerConnectionGetPacketContextActive(edgeConnection, 0, &active); 587 } 588 CFRelease(edgeConnection); 589 590 if (active) { 591 sleep(2); // additionnal 2 seconds for DNS information to be installed 592 result = 0; 593 } 594 } 595 } 596 597 598 write(edgefds[1], &result, 1); 599 return 0; 600} 601#endif 602 603int pptp_pre_start_link_check() 604{ 605 int reachable = FALSE; 606 SCNetworkReachabilityRef ref; 607 SCNetworkConnectionFlags flags; 608 609 ref = SCNetworkReachabilityCreateWithName(NULL, remoteaddress); 610 if (ref) { 611 if (SCNetworkReachabilityGetFlags(ref, &flags)) { 612 if (REACHABLE_NOW || REACHABLE_AUTOMATICALLY_WITHOUT_USER) { 613 reachable = TRUE; 614 } 615 } 616 CFRelease(ref); 617 } 618 619 if (reachable) { 620 return 0; 621 } 622 return -1; 623} 624 625static CFStringRef pptp_copy_str_at_index(CFStringRef key, int index) 626{ 627 CFArrayRef components; 628 CFStringRef foundstr = NULL; 629 630 components = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/")); 631 if (index < CFArrayGetCount(components)) { 632 if ((foundstr = CFArrayGetValueAtIndex(components, index))){ 633 CFRetain(foundstr); 634 } 635 } 636 CFRelease(components); 637 return foundstr; 638} 639 640static void pptp_get_router_address(CFStringRef serviceID) 641{ 642 CFStringRef routerAddress = NULL; 643 CFStringRef ipv4Key = NULL; 644 CFDictionaryRef ipv4Dict = NULL; 645 646 if (serviceID == NULL) { 647 goto done; 648 } 649 warning("pptp_get_router_address\n"); 650 ipv4Key = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault, 651 kSCDynamicStoreDomainState, 652 serviceID, 653 kSCEntNetIPv4); 654 if (ipv4Key == NULL) { 655 goto done; 656 } 657 658 ipv4Dict = SCDynamicStoreCopyValue(NULL, ipv4Key); 659 if (ipv4Dict == NULL) { 660 goto done; 661 } 662 663 routerAddress = CFDictionaryGetValue(ipv4Dict, kSCPropNetIPv4Router); 664 if (routerAddress) { 665 CFStringGetCString(routerAddress, (char*)routeraddress, sizeof(routeraddress), kCFStringEncodingUTF8); 666 warning("pptp_get_router_address %s\n", routeraddress); 667 } 668 669done: 670 if (ipv4Key) { 671 CFRelease(ipv4Key); 672 } 673 if (ipv4Dict) { 674 CFRelease(ipv4Dict); 675 } 676} 677 678static void pptp_get_router_address_for_interface(void) 679{ 680 CFDictionaryRef dict = NULL; 681 CFStringRef pattern = NULL; 682 CFMutableArrayRef patterns = NULL; 683 CFStringRef *keys = NULL; 684 CFDictionaryRef *values = NULL; 685 CFIndex count = 0; 686 CFIndex i = 0; 687 CFStringRef serviceID = NULL; 688 689 if (interface == NULL || interface[0] == 0) { 690 goto done; 691 } 692 693 patterns = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 694 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault, 695 kSCDynamicStoreDomainState, 696 kSCCompAnyRegex, 697 kSCEntNetIPv4); 698 699 if (patterns == NULL || pattern == NULL) 700 goto done; 701 CFArrayAppendValue(patterns, pattern); 702 703 dict = SCDynamicStoreCopyMultiple(NULL, NULL, patterns); 704 if (dict == NULL) 705 goto done; 706 707 count = CFDictionaryGetCount(dict); 708 709 keys = calloc(count, sizeof(CFStringRef)); 710 values = calloc(count, sizeof(CFDictionaryRef)); 711 if (keys == NULL || values == NULL) 712 goto done; 713 CFDictionaryGetKeysAndValues(dict, (const void**)keys, (const void**)values); 714 for (i=0; i < count; i++) { 715 CFDictionaryRef ipv4Dict = NULL; 716 CFStringRef ipv4Key = NULL; 717 718 ipv4Key = keys[i]; 719 ipv4Dict = values[i]; 720 721 if (ipv4Key == NULL || ipv4Dict == NULL) { 722 continue; 723 } 724 725 /* Match interface name here */ 726 CFStringRef ifnameRef = CFDictionaryGetValue(ipv4Dict, kSCPropInterfaceName); 727 if (ifnameRef) { 728 char ifname[IFNAMSIZ] = { 0 }; 729 CFStringGetCString(ifnameRef, ifname, sizeof(ifname), kCFStringEncodingASCII); 730 if (!strcmp(ifname, interface)) { 731 if ((CFStringHasPrefix(ipv4Key, kSCDynamicStoreDomainState)) && (CFStringHasSuffix(ipv4Key, kSCEntNetIPv4))) { 732 // Fetch the serviceID, then the router address 733 serviceID = pptp_copy_str_at_index(ipv4Key, 3); 734 pptp_get_router_address(serviceID); 735 break; 736 } 737 } 738 } 739 } 740 741done: 742 if (serviceID) { 743 CFRelease(serviceID); 744 } 745 if (pattern) { 746 CFRelease(pattern); 747 } 748 if (patterns) { 749 CFRelease(patterns); 750 } 751 if (dict) { 752 CFRelease(dict); 753 } 754 if (keys) { 755 free(keys); 756 } 757 if (values) { 758 free(values); 759 } 760} 761 762/* ----------------------------------------------------------------------------- 763get the socket ready to start doing PPP. 764That is, open the socket and start the PPTP dialog 765----------------------------------------------------------------------------- */ 766int pptp_connect(int *errorcode) 767{ 768 char dev[32], name[MAXPATHLEN], c; 769 int err = 0, fd, val; 770 uint32_t len; 771 CFURLRef url; 772 CFDictionaryRef dict; 773 CFStringRef string, key; 774 struct sockaddr_in addr; 775 struct kev_request kev_req; 776 u_int32_t baudrate; 777 int num_connect_retries = 0; 778 int connect_timeout = 15; 779 780 *errorcode = 0; 781 782 if (cfgCache == NULL || serviceidRef == NULL) { 783 goto fail; 784 } 785 786 snprintf(dev, sizeof(dev), "socket[%d:%d]", PF_PPP, PPPPROTO_PPTP); 787 strlcpy(ppp_devnam, dev, sizeof(ppp_devnam)); 788 789 hungup = 0; 790 kill_link = 0; 791 linkdown = 0; 792 our_call_id = getpid(); 793 routeraddress[0] = 0; 794 interface[0] = 0; 795 796 if (ifscope && ifscope[0]) { 797 strcpy(interface, ifscope); 798 pptp_get_router_address_for_interface(); 799 } else { 800 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); 801 if (key) { 802 dict = SCDynamicStoreCopyValue(cfgCache, key); 803 CFRelease(key); 804 if (dict) { 805 if ((string = CFDictionaryGetValue(dict, kSCPropNetIPv4Router))) 806 CFStringGetCString(string, (char*)routeraddress, sizeof(routeraddress), kCFStringEncodingUTF8); 807 if ((string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface))) 808 CFStringGetCString(string, (char*)interface, sizeof(interface), kCFStringEncodingUTF8); 809 CFRelease(dict); 810 } 811 } 812 } 813 814 /* now that we know our interface, adjust the MTU if necessary */ 815 if (interface[0]) { 816 int min_mtu = pptp_get_if_mtu((char*)interface) - PPTP_MIN_HDR_SIZE; 817 if (lcp_allowoptions[0].mru > min_mtu) /* defines out mtu */ 818 lcp_allowoptions[0].mru = min_mtu; 819 820 /* Don't adjust MRU, radar 3974763 */ 821#if 0 822 if (lcp_wantoptions[0].mru > min_mtu) /* defines out mru */ 823 lcp_wantoptions[0].mru = min_mtu; 824 if (lcp_wantoptions[0].neg_mru > min_mtu) /* defines our mru */ 825 lcp_wantoptions[0].neg_mru = min_mtu; 826#endif 827 } 828 829#if !TARGET_OS_EMBEDDED 830 interface_media = pptp_get_if_media((char*)interface); 831#endif /* !iPhone */ 832 833 /* let's say our underlying transport is up */ 834 transport_up = 1; 835 wait_interface_timer_running = 0; 836 wait_underlying_interface_up = 0; 837 ppp_session_clear(&pptp_session); 838 session = NULL; 839 840 eventsockfd = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT); 841 if (eventsockfd != -1) { 842 // PPTP can survive without event socket anyway 843 kev_req.vendor_code = KEV_VENDOR_APPLE; 844 kev_req.kev_class = KEV_NETWORK_CLASS; 845 kev_req.kev_subclass = KEV_INET_SUBCLASS; 846 ioctl(eventsockfd, SIOCSKEVFILT, &kev_req); 847 } 848 849 /* -------------------------------------------------------------*/ 850 /* connect mode : we need a valid remote address or name */ 851 if (!strcmp(mode, MODE_CONNECT)) { 852 if (remoteaddress == 0) { 853 error("PPTP: No remote address supplied...\n"); 854 devstatus = EXIT_PPTP_NOSERVER; 855 goto fail; 856 } 857 858 set_network_signature("VPN.RemoteAddress", remoteaddress, 0, 0); 859 860#if TARGET_OS_EMBEDDED 861 { 862 /* first, bring up EDGE */ 863 int need_edge = FALSE; 864 SCNetworkReachabilityRef ref = NULL; 865 SCNetworkConnectionFlags flags; 866 867 ref = SCNetworkReachabilityCreateWithName(NULL, remoteaddress); 868 if (ref) { 869 870 if (SCNetworkReachabilityGetFlags(ref, &flags)) { 871 if ((flags & kSCNetworkReachabilityFlagsReachable) && 872 (flags & kSCNetworkReachabilityFlagsConnectionRequired) && 873 (flags & kSCNetworkReachabilityFlagsIsWWAN)) { 874 need_edge = TRUE; 875 } 876 } 877 CFRelease(ref); 878 } 879 880 if (need_edge) { 881 882 if (pipe(edgefds) < 0) { 883 error("PPTP: failed to create pipe for starting edge...\n"); 884 goto fail; 885 } 886 887 if (pthread_create(&edgethread, NULL, pptp_edge_thread, NULL)) { 888 error("PPTP: failed to create thread for starting edge...\n"); 889 close(edgefds[0]); 890 close(edgefds[1]); 891 goto fail; 892 } 893 894 while (read(edgefds[0], &c, 1) != 1) { 895 if (kill_link) { 896 pthread_cancel(edgethread); 897 break; 898 } 899 } 900 901 close(edgefds[0]); 902 close(edgefds[1]); 903 904 if (kill_link) 905 goto fail1; 906 907 if (c) { 908 error("PPTP: Cannot start EDGE connection...\n"); 909 *errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */ 910 devstatus = EXIT_PPTP_NOEDGE; 911 goto fail; 912 } 913 914 } 915 916 } 917#endif 918 919 if (inet_aton(remoteaddress, &peeraddress) == 0) { 920 921 if (pipe(resolverfds) < 0) { 922 error("PPTP: failed to create pipe for gethostbyname...\n"); 923 goto fail; 924 } 925 926 if (pthread_create(&resolverthread, NULL, pptp_resolver_thread, NULL)) { 927 error("PPTP: failed to create thread for gethostbyname...\n"); 928 close(resolverfds[0]); 929 close(resolverfds[1]); 930 goto fail; 931 } 932 933 while (read(resolverfds[0], &c, 1) != 1) { 934 if (kill_link) { 935 pthread_cancel(resolverthread); 936 break; 937 } 938 } 939 940 close(resolverfds[0]); 941 close(resolverfds[1]); 942 943 if (kill_link) 944 goto fail1; 945 946 if (c) { 947 error("PPTP: Host '%s' not found...\n", remoteaddress); 948 *errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */ 949 devstatus = EXIT_PPTP_NOSERVER; 950 goto fail; 951 } 952 } 953 954 notice("PPTP connecting to server '%s' (%s)...\n", remoteaddress, inet_ntoa(peeraddress)); 955 956 set_server_peer(peeraddress); 957 958 if ((ctrlsockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { 959 error("PPTP can't create control socket...\n"); 960 goto fail; 961 } 962 // TODO: make connection_timeout configurable 963 if (setsockopt(ctrlsockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &connect_timeout, sizeof(connect_timeout))) { 964 error("PPTP can't set control socket's maximum timeout ...\n"); 965 // prevent retries since the default 90 sec is *too* long 966 num_alt_peer_address = 0; 967 } 968 969 /* connect to the pptp server */ 970 bzero(&addr, sizeof(addr)); 971 addr.sin_len = sizeof(addr); 972 addr.sin_family = AF_INET; 973 addr.sin_port = htons(PPTP_TCP_PORT); 974 addr.sin_addr = peeraddress; 975 976 uint32_t ifindex = 0; 977 if (ifscope && ifscope[0]) { 978 ifindex = if_nametoindex(ifscope); 979 } 980 while (connectx(ctrlsockfd, NULL, 0, (struct sockaddr *)&addr, sizeof(addr), ifindex, ASSOCID_ANY, CONNID_ANY)) { 981 if (errno != EINTR) { 982 error("PPTP connect errno = %d %m\n", errno); 983 if ((errno == ETIMEDOUT || errno == ECONNREFUSED) && 984 num_connect_retries < num_alt_peer_address) { 985 peeraddress = alt_peer_address[num_connect_retries]; 986 notice("PPTP connecting to alternate server '%s' (%s)...\n", remoteaddress, inet_ntoa(peeraddress)); 987 set_server_peer(peeraddress); 988 addr.sin_addr = peeraddress; 989 num_connect_retries++; 990 continue; 991 } 992 *errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */ 993 devstatus = EXIT_PPTP_NOANSWER; 994 goto fail; 995 } 996 if (kill_link) 997 goto fail1; 998 } 999 1000 /* enable keepalive on control connection. need to be done before sending data */ 1001 enable_keepalive(ctrlsockfd); 1002 1003 err = pptp_outgoing_call(ctrlsockfd, 1004 our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd); 1005 1006 /* setup the specific route */ 1007 pptp_set_peer_route(); 1008 } 1009 /* -------------------------------------------------------------*/ 1010 /* answer mode : we need a valid remote address or name */ 1011 else if (!strcmp(mode, MODE_ANSWER)) { 1012 len = sizeof(addr); 1013 if (getpeername(ctrlsockfd, (struct sockaddr *)&addr, &len) < 0) { 1014 error("PPTP: cannot get client address... %m\n"); 1015 //devstatus = EXIT_PPTP_NOSERVER; 1016 goto fail; 1017 } 1018 peeraddress = addr.sin_addr; 1019 remoteaddress = inet_ntoa(peeraddress); 1020 1021 notice("PPTP incoming call in progress from '%s'...", remoteaddress); 1022 1023 /* enable keepalive on control connection. need to be done before sending data */ 1024 enable_keepalive(ctrlsockfd); 1025 1026 err = pptp_incoming_call(ctrlsockfd, 1027 our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd); 1028 } 1029 /* -------------------------------------------------------------*/ 1030 else if (!strcmp(mode, MODE_LISTEN)) { 1031 1032 notice("PPTP listening...\n"); 1033 1034 if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { 1035 error("PPTP can't create listening socket...\n"); 1036 goto fail; 1037 } 1038 1039 val = 1; 1040 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 1041 1042 bzero(&addr, sizeof(addr)); 1043 addr.sin_len = sizeof(addr); 1044 addr.sin_family = AF_INET; 1045 addr.sin_port = htons(PPTP_TCP_PORT); 1046 addr.sin_addr.s_addr = INADDR_ANY; 1047 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 1048 error("PPTP bind failed, %m"); 1049 goto fail; 1050 } 1051 1052 if (listen(fd, 10) < 0) { 1053 error("PPTP listen failed, %m"); 1054 return errno; 1055 } 1056 1057 len = sizeof(addr); 1058 ctrlsockfd = accept(fd, (struct sockaddr *)&addr, &len); 1059 close(fd); // close the socket used for listening 1060 if (ctrlsockfd < 0) { 1061 error("PPTP accept failed, %m"); 1062 goto fail; 1063 } 1064 1065 peeraddress = addr.sin_addr; 1066 remoteaddress = inet_ntoa(peeraddress); 1067 1068 notice("PPTP incoming call in progress from '%s'...", remoteaddress); 1069 1070 /* enable keepalive on control connection. need to be done before sending data */ 1071 enable_keepalive(ctrlsockfd); 1072 1073 err = pptp_incoming_call(ctrlsockfd, 1074 our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd); 1075 } 1076 1077 if (err) { 1078 if (err != -2) { 1079 if (err != -1) 1080 devstatus = err; 1081 goto fail; 1082 } 1083 goto fail1; 1084 } 1085 1086 notice("PPTP connection established."); 1087 1088 bzero(&ouraddress, sizeof(ouraddress)); 1089 len = sizeof(ouraddress); 1090 getsockname(ctrlsockfd, (struct sockaddr *)&ouraddress, &len); 1091 1092 /* get reachability flags of peer */ 1093 bzero(&addr, sizeof(addr)); 1094 addr.sin_len = sizeof(addr); 1095 addr.sin_family = AF_INET; 1096 addr.sin_port = htons(PPTP_TCP_PORT); 1097 addr.sin_addr = peeraddress; 1098 1099 /* open the data socket */ 1100 datasockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_PPTP); 1101 if (datasockfd < 0) { 1102 if (!noload) { 1103 if ((url = CFBundleCopyBundleURL(bundle))) { 1104 name[0] = 0; 1105 CFURLGetFileSystemRepresentation(url, 0, (UInt8 *)name, MAXPATHLEN - 1); 1106 CFRelease(url); 1107 strlcat(name, "/", sizeof(name)); 1108 if ((url = CFBundleCopyBuiltInPlugInsURL(bundle))) { 1109 CFURLGetFileSystemRepresentation(url, 0, (UInt8 *)(name + strlen(name)), 1110 MAXPATHLEN - strlen(name) - strlen(PPTP_NKE) - 1); 1111 CFRelease(url); 1112 strlcat(name, "/", sizeof(name)); 1113 strlcat(name, PPTP_NKE, sizeof(name)); 1114#if !TARGET_OS_EMBEDDED 1115 if (!load_kext(name, 0)) 1116#else 1117 if (!load_kext(PPTP_NKE_ID, 1)) 1118#endif 1119 datasockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_PPTP); 1120 } 1121 } 1122 } 1123 if (datasockfd < 0) { 1124 error("Failed to open PPTP socket: %m"); 1125 goto fail; 1126 } 1127 } 1128 1129 if (kdebugflag & 1) { 1130 u_int32_t flags; 1131 flags = debug ? PPTP_FLAG_DEBUG : 0; 1132 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_FLAGS, &flags, 4)) { 1133 error("PPTP can't set PPTP flags...\n"); 1134 goto fail; 1135 } 1136 } 1137 1138 len = sizeof(addr); 1139 if (getsockname(ctrlsockfd, (struct sockaddr *)&addr, &len) < 0) { 1140 error("PPTP: cannot get our address... %m\n"); 1141 goto fail; 1142 } 1143 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_OURADDRESS, &addr.sin_addr.s_addr, 4)) { 1144 error("PPTP can't set our PPTP address...\n"); 1145 goto fail; 1146 } 1147 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEERADDRESS, &peeraddress.s_addr, 4)) { 1148 error("PPTP can't set PPTP server address...\n"); 1149 goto fail; 1150 } 1151 1152 baudrate = pptp_get_if_baudrate((char*)interface); 1153 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_BAUDRATE, &baudrate, 4)) { 1154 error("PPTP can't set our baudrate...\n"); 1155 goto fail; 1156 } 1157 1158 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_CALL_ID, &our_call_id, 2)) { 1159 error("PPTP can't set our call id...\n"); 1160 goto fail; 1161 } 1162 1163 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_CALL_ID, &peer_call_id, 2)) { 1164 error("PPTP can't set peer call id...\n"); 1165 goto fail; 1166 } 1167 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_WINDOW, &our_window, 2)) { 1168 error("PPTP can't set our receive window size...\n"); 1169 goto fail; 1170 } 1171 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_WINDOW, &peer_window, 2)) { 1172 error("PPTP can't set peer receive window size...\n"); 1173 goto fail; 1174 } 1175 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_PPD, &peer_ppd, 2)) { 1176 error("PPTP can't set peer packet processing delay ...\n"); 1177 goto fail; 1178 } 1179 if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_MAXTIMEOUT, &maxtimeout, 2)) { 1180 error("PPTP can't set adaptative maximum timeout ...\n"); 1181 goto fail; 1182 } 1183 1184 if (!strcmp(mode, MODE_CONNECT)) { 1185 pptp_init_session((char *)interface, sizeof(interface), &ouraddress.sin_addr, ppp_variable_echo_start); 1186 pptp_set_nat_port_mapping(); 1187 } 1188 1189 return datasockfd; 1190 1191fail: 1192 status = EXIT_CONNECT_FAILED; 1193fail1: 1194 if (eventsockfd != -1) { 1195 close(eventsockfd); 1196 eventsockfd = -1; 1197 } 1198 if (ctrlsockfd != -1) { 1199 close(ctrlsockfd); 1200 ctrlsockfd = -1; 1201 } 1202 return -1; 1203} 1204 1205/* ----------------------------------------------------------------------------- 1206run the disconnector 1207----------------------------------------------------------------------------- */ 1208void pptp_disconnect() 1209{ 1210 notice("PPTP disconnecting...\n"); 1211 1212 if (eventsockfd != -1) { 1213 close(eventsockfd); 1214 eventsockfd = -1; 1215 } 1216 if (ctrlsockfd >= 0) { 1217 close(ctrlsockfd); 1218 ctrlsockfd = -1; 1219 } 1220 1221 ppp_auxiliary_probe_stop(); 1222 pptp_clear_nat_port_mapping(); 1223 ppp_session_clear(&pptp_session); 1224 session = NULL; 1225 1226 notice("PPTP disconnected\n"); 1227} 1228 1229/* ----------------------------------------------------------------------------- 1230close the socket descriptors 1231----------------------------------------------------------------------------- */ 1232void pptp_close() 1233{ 1234 1235 pptp_stop_echo_check(); 1236 1237 if (eventsockfd != -1) { 1238 close(eventsockfd); 1239 eventsockfd = -1; 1240 } 1241 if (datasockfd >= 0) { 1242 close(datasockfd); 1243 datasockfd = -1; 1244 } 1245 if (ctrlsockfd >= 0) { 1246 close(ctrlsockfd); 1247 ctrlsockfd = -1; 1248 } 1249} 1250 1251/* ----------------------------------------------------------------------------- 1252clean up before quitting 1253----------------------------------------------------------------------------- */ 1254void pptp_cleanup() 1255{ 1256 pptp_close(); 1257 pptp_clean_peer_route(); 1258} 1259 1260/* ----------------------------------------------------------------------------- 1261establish the socket as a ppp link 1262----------------------------------------------------------------------------- */ 1263int pptp_establish_ppp(int fd) 1264{ 1265 int x, new_fd; 1266 1267 if (ioctl(fd, PPPIOCATTACH, &x) < 0) { 1268 error("Couldn't attach socket to the link layer: %m"); 1269 return -1; 1270 } 1271 1272 new_fd = generic_establish_ppp(fd, interface); 1273 if (new_fd == -1) 1274 return -1; 1275 1276 // add just the control socket to the select 1277 // the data socket is just for moving data in the kernel 1278 add_fd(ctrlsockfd); 1279 add_fd(eventsockfd); 1280 return new_fd; 1281} 1282 1283/* ----------------------------------------------------------------------------- 1284disestablish the socket as a ppp link 1285----------------------------------------------------------------------------- */ 1286void pptp_disestablish_ppp(int fd) 1287{ 1288 int x; 1289 1290 remove_fd(ctrlsockfd); 1291 remove_fd(eventsockfd); 1292 1293 if (ioctl(fd, PPPIOCDETACH, &x) < 0) 1294 error("Couldn't detach socket from link layer: %m"); 1295 1296 generic_disestablish_ppp(fd); 1297} 1298 1299/* ----------------------------------------------------------------------------- 1300----------------------------------------------------------------------------- */ 1301void closeall() 1302{ 1303 int i; 1304 1305 for (i = getdtablesize() - 1; i >= 0; i--) close(i); 1306 open("/dev/null", O_RDWR, 0); 1307 dup(0); 1308 dup(0); 1309 return; 1310} 1311 1312/* ----------------------------------------------------------------------------- 1313----------------------------------------------------------------------------- */ 1314u_long load_kext(char *kext, int byBundleID) 1315{ 1316 int pid; 1317 1318 if ((pid = fork()) < 0) 1319 return 1; 1320 1321 if (pid == 0) { 1322 closeall(); 1323 // PPP kernel extension not loaded, try load it... 1324 if (byBundleID) 1325 execle("/sbin/kextload", "kextload", "-b", kext, (char *)0, (char *)0); 1326 else 1327 execle("/sbin/kextload", "kextload", kext, (char *)0, (char *)0); 1328 exit(1); 1329 } 1330 1331 while (waitpid(pid, 0, 0) < 0) { 1332 if (errno == EINTR) 1333 continue; 1334 return 1; 1335 } 1336 return 0; 1337} 1338 1339/* ----------------------------------------------------------------------------- 1340get the MTU on the network interface 1341----------------------------------------------------------------------------- */ 1342u_int32_t 1343pptp_get_if_mtu(char *if_name) 1344{ 1345 struct ifreq ifr; 1346 int s, err; 1347 1348 ifr.ifr_mtu = 1500; 1349 1350 s = socket(AF_INET, SOCK_DGRAM, 0); 1351 if (s >= 0) { 1352 strlcpy(ifr.ifr_name, if_name, sizeof (ifr.ifr_name)); 1353 if ((err = ioctl(s, SIOCGIFMTU, (caddr_t) &ifr)) < 0) 1354 error("PPTP: can't get interface '%s' mtu, err %d (%m)", if_name, err); 1355 close(s); 1356 } 1357 return ifr.ifr_mtu; 1358} 1359 1360/* ----------------------------------------------------------------------------- 1361 Get the media of an interface. 1362 1363 Parameters: 1364 if_name: interface we want information about. 1365 1366 Return code: 1367 media for the interface. 1368 ----------------------------------------------------------------------------- */ 1369u_int32_t 1370pptp_get_if_media(char *if_name) 1371{ 1372 struct ifmediareq ifr; 1373 int s, err; 1374 1375 if (!if_name || !if_name[0]) { 1376 return 0; 1377 } 1378 1379 bzero(&ifr, sizeof(ifr)); 1380 1381 s = socket(AF_INET, SOCK_DGRAM, 0); 1382 if (s >= 0) { 1383 strlcpy(ifr.ifm_name, if_name, sizeof (ifr.ifm_name)); 1384 if ((err = ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifr)) < 0) { 1385 error("PPTP: can't get interface '%s' media, err %d (%m)", if_name, err); 1386 } 1387 close(s); 1388 } 1389 return ifr.ifm_current; 1390} 1391 1392/* ----------------------------------------------------------------------------- 1393----------------------------------------------------------------------------- */ 1394u_int32_t 1395pptp_get_if_baudrate(char *if_name) 1396{ 1397 char * buf = NULL; 1398 size_t buf_len = 0; 1399 struct if_msghdr * ifm; 1400 unsigned int if_index; 1401 u_int32_t baudrate = 0; 1402 int mib[6]; 1403 1404 /* get the interface index */ 1405 1406 if_index = if_nametoindex(if_name); 1407 if (if_index == 0) { 1408 goto done; // if unknown interface 1409 } 1410 1411 /* get information for the specified device */ 1412 1413 mib[0] = CTL_NET; 1414 mib[1] = PF_ROUTE; 1415 mib[2] = 0; 1416 mib[3] = AF_LINK; 1417 mib[4] = NET_RT_IFLIST; 1418 mib[5] = if_index; /* ask for exactly one interface */ 1419 1420 if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) < 0) { 1421 goto done; 1422 } 1423 buf = malloc(buf_len); 1424 if (sysctl(mib, 6, buf, &buf_len, NULL, 0) < 0) { 1425 goto done; 1426 } 1427 1428 /* get the baudrate for the interface */ 1429 1430 ifm = ALIGNED_CAST(struct if_msghdr *)buf; 1431 switch (ifm->ifm_type) { 1432 case RTM_IFINFO : { 1433 baudrate = ifm->ifm_data.ifi_baudrate; 1434 break; 1435 } 1436 } 1437 1438done : 1439 1440 if (buf != NULL) 1441 free(buf); 1442 1443 return baudrate; 1444} 1445 1446/* ----------------------------------------------------------------------------- 1447----------------------------------------------------------------------------- */ 1448int pptp_set_peer_route() 1449{ 1450 SCNetworkReachabilityRef ref; 1451 SCNetworkConnectionFlags flags; 1452 bool is_peer_local; 1453 struct in_addr gateway; 1454 struct sockaddr_in addr; 1455 1456 if (peeraddress.s_addr == 0) 1457 return -1; 1458 1459 /* check if is peer on our local subnet */ 1460 bzero(&addr, sizeof(addr)); 1461 addr.sin_len = sizeof(addr); 1462 addr.sin_family = AF_INET; 1463 addr.sin_port = htons(PPTP_TCP_PORT); 1464 addr.sin_addr = peeraddress; 1465 ref = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&addr); 1466 is_peer_local = SCNetworkReachabilityGetFlags(ref, &flags) && (flags & kSCNetworkFlagsIsDirect); 1467 CFRelease(ref); 1468 1469 host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, 0); 1470 1471 if (is_peer_local 1472 || routeraddress[0] == 0 1473 || inet_aton((char*)routeraddress, &gateway) != 1) { 1474 1475 if (interface[0]) { 1476 bzero(&gateway, sizeof(gateway)); 1477 /* subnet route */ 1478 host_gateway(RTM_ADD, peeraddress, gateway, (char*)interface, 1); 1479 peer_route_set = 2; 1480 } 1481 } 1482 else { 1483 /* host route */ 1484 host_gateway(RTM_ADD, peeraddress, gateway, 0, 0); 1485 peer_route_set = 1; 1486 } 1487 1488 return 0; 1489} 1490 1491/* ----------------------------------------------------------------------------- 1492----------------------------------------------------------------------------- */ 1493int pptp_clean_peer_route() 1494{ 1495 1496 if (peeraddress.s_addr == 0) 1497 return -1; 1498 1499 if (peer_route_set) { 1500 host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, peer_route_set == 1 ? 0 : 1); 1501 peer_route_set = 0; 1502 } 1503 1504 return 0; 1505} 1506 1507/* ----------------------------------------------------------------------------- 1508----------------------------------------------------------------------------- */ 1509void pptp_ip_up(void *arg, uintptr_t p) 1510{ 1511 1512 if (peer_route_set == 2) { 1513 /* in the link local case, delete the route to the server, 1514 in case it conflicts with the one from the ppp interface */ 1515 host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, 0); 1516 } 1517} 1518 1519/* ----------------------------------------------------------------------------- 1520add/remove a host route 1521----------------------------------------------------------------------------- */ 1522static boolean_t 1523host_gateway(int cmd, struct in_addr host, struct in_addr gateway, char *ifname, int isnet) 1524{ 1525 int len; 1526 int rtm_seq = 0; 1527 struct { 1528 struct rt_msghdr hdr; 1529 struct sockaddr_in dst; 1530 struct sockaddr_in gway; 1531 struct sockaddr_in mask; 1532 struct sockaddr_dl link; 1533 } rtmsg; 1534 int sockfd = -1; 1535 1536 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) { 1537 syslog(LOG_INFO, "host_gateway: open routing socket failed, %s", 1538 strerror(errno)); 1539 return (FALSE); 1540 } 1541 1542 memset(&rtmsg, 0, sizeof(rtmsg)); 1543 rtmsg.hdr.rtm_type = cmd; 1544 rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC; 1545 if (isnet) 1546 rtmsg.hdr.rtm_flags |= RTF_CLONING; 1547 else 1548 rtmsg.hdr.rtm_flags |= RTF_HOST; 1549 if (gateway.s_addr) 1550 rtmsg.hdr.rtm_flags |= RTF_GATEWAY; 1551 rtmsg.hdr.rtm_version = RTM_VERSION; 1552 rtmsg.hdr.rtm_seq = ++rtm_seq; 1553 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_NETMASK; 1554 rtmsg.dst.sin_len = sizeof(rtmsg.dst); 1555 rtmsg.dst.sin_family = AF_INET; 1556 rtmsg.dst.sin_addr = host; 1557 rtmsg.hdr.rtm_addrs |= RTA_GATEWAY; 1558 rtmsg.gway.sin_len = sizeof(rtmsg.gway); 1559 rtmsg.gway.sin_family = AF_INET; 1560 rtmsg.gway.sin_addr = gateway; 1561 rtmsg.mask.sin_len = sizeof(rtmsg.mask); 1562 rtmsg.mask.sin_family = AF_INET; 1563 rtmsg.mask.sin_addr.s_addr = 0xFFFFFFFF; 1564 1565 len = sizeof(rtmsg); 1566 if (ifname) { 1567 rtmsg.link.sdl_len = sizeof(rtmsg.link); 1568 rtmsg.link.sdl_family = AF_LINK; 1569 rtmsg.link.sdl_nlen = MIN(strlen(ifname), sizeof(rtmsg.link.sdl_data)); 1570 rtmsg.hdr.rtm_addrs |= RTA_IFP; 1571 bcopy(ifname, rtmsg.link.sdl_data, rtmsg.link.sdl_nlen); 1572 } 1573 else { 1574 /* no link information */ 1575 len -= sizeof(rtmsg.link); 1576 } 1577 rtmsg.hdr.rtm_msglen = len; 1578 if (write(sockfd, &rtmsg, len) < 0) { 1579 syslog(LOG_DEBUG, "host_gateway: write routing socket failed, %s", 1580 strerror(errno)); 1581 close(sockfd); 1582 return (FALSE); 1583 } 1584 1585 close(sockfd); 1586 return (TRUE); 1587} 1588 1589/* ----------------------------------------------------------------------------- 1590----------------------------------------------------------------------------- */ 1591static void pptp_echo_check () 1592{ 1593 if (echo_active == 0 || echo_timer_running != 0) 1594 return; 1595 1596 pptp_send_echo_request (); 1597 1598 TIMEOUT (pptp_echo_timeout, 0, echo_interval); 1599 echo_timer_running = 1; 1600} 1601 1602/* ----------------------------------------------------------------------------- 1603----------------------------------------------------------------------------- */ 1604static void pptp_stop_echo_check () 1605{ 1606 echo_active = 0; 1607 if (echo_timer_running) { 1608 UNTIMEOUT (pptp_echo_timeout, 0); 1609 echo_timer_running = 0; 1610 } 1611} 1612 1613/* ----------------------------------------------------------------------------- 1614----------------------------------------------------------------------------- */ 1615static void pptp_echo_timeout (void *arg) 1616{ 1617 if (echo_timer_running != 0) { 1618 echo_timer_running = 0; 1619 pptp_echo_check (); 1620 } 1621} 1622 1623/* ----------------------------------------------------------------------------- 1624----------------------------------------------------------------------------- */ 1625void pptp_received_echo_reply(u_int32_t identifier, u_int8_t result, u_int8_t error) 1626{ 1627 // not really interested in the content 1628 // we just know our link is still alive 1629 dbglog("PPTP received Echo Reply, id = %d", identifier); 1630 /* Reset the number of outstanding echo frames */ 1631 echos_pending = 0; 1632 echo_active = 0; 1633} 1634 1635/* ----------------------------------------------------------------------------- 1636----------------------------------------------------------------------------- */ 1637static void pptp_link_failure () 1638{ 1639 // major change happen on the interface we are using. 1640 // disconnect PPTP 1641 // Enhancement : should check if link is still usable 1642 notice("PPTP has detected change in the network and lost connection with the server."); 1643 devstatus = EXIT_PPTP_NETWORKCHANGED; 1644 status = EXIT_HANGUP; 1645 remove_fd(ctrlsockfd); 1646 remove_fd(eventsockfd); 1647 hungup = 1; 1648 lcp_lowerdown(0); /* PPTP link is no longer available */ 1649 link_terminated(0); 1650 ppp_auxiliary_probe_stop(); 1651 pptp_clear_nat_port_mapping(); 1652 ppp_session_clear(&pptp_session); 1653 session = NULL; 1654} 1655 1656/* ----------------------------------------------------------------------------- 1657----------------------------------------------------------------------------- */ 1658static void pptp_send_echo_request () 1659{ 1660 /* 1661 * Detect the failure of the peer at this point. 1662 */ 1663 if (echo_fails != 0) { 1664 if (echos_pending >= echo_fails) { 1665 pptp_link_failure(); 1666 echos_pending = 0; 1667 } 1668 } 1669 1670 /* 1671 * Make and send the echo request frame. 1672 */ 1673 dbglog("PPTP sent Echo Request, id = %d", echo_identifier); 1674 if (pptp_echo(ctrlsockfd, echo_identifier++) == -1) 1675 pptp_link_failure(); 1676 echos_pending++; 1677} 1678 1679/* ----------------------------------------------------------------------------- 1680----------------------------------------------------------------------------- */ 1681static void enable_keepalive (int fd) 1682{ 1683 int val; 1684 1685 if (tcp_keepalive) { 1686 val = 1; 1687 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); 1688 setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepalive, sizeof(tcp_keepalive)); 1689 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); 1690 } 1691} 1692 1693/* ----------------------------------------------------------------------------- 1694 ----------------------------------------------------------------------------- */ 1695int 1696pptp_ip_probe_init (struct sockaddr_in *probe_addrs, 1697 int *probe_fds, 1698 int num) 1699{ 1700 int scope; 1701 1702 if (!probe_addrs || !probe_fds || num < 3) { 1703 return -1; 1704 } 1705 1706 scope = if_nametoindex((char *)interface); 1707 1708 bzero(probe_addrs, (sizeof(*probe_addrs) * num)); 1709 probe_addrs[GOOG_DNS_PROBE].sin_len = sizeof(struct in_addr); 1710 probe_addrs[GOOG_DNS_PROBE].sin_family = AF_INET; 1711 probe_addrs[GOOG_DNS_PROBE].sin_port = 0; 1712 probe_addrs[GOOG_DNS_PROBE].sin_addr.s_addr = GOOG_DNS_PROBE_ADDR_A; // google-public-dns-a.google.com 1713 if (peeraddress.s_addr) { 1714 probe_addrs[PEER_ADDR_PROBE].sin_len = sizeof(peeraddress); 1715 probe_addrs[PEER_ADDR_PROBE].sin_family = AF_INET; 1716 probe_addrs[PEER_ADDR_PROBE].sin_port = 0; 1717 probe_addrs[PEER_ADDR_PROBE].sin_addr = peeraddress; 1718 if (num_alt_peer_address) { 1719 probe_addrs[ALT_PEER_ADDR_PROBE].sin_len = sizeof(peeraddress); 1720 probe_addrs[ALT_PEER_ADDR_PROBE].sin_family = AF_INET; 1721 probe_addrs[ALT_PEER_ADDR_PROBE].sin_port = 0; 1722 probe_addrs[ALT_PEER_ADDR_PROBE].sin_addr = alt_peer_address[(arc4random() % num_alt_peer_address)]; 1723 } 1724 } 1725 probe_fds[GOOG_DNS_PROBE] = -1; 1726 probe_fds[PEER_ADDR_PROBE] = -1; 1727 probe_fds[ALT_PEER_ADDR_PROBE] = -1; 1728 return 0; 1729} 1730 1731static char *pptp_sd_name = "PPTP"; 1732void 1733pptp_init_session (char *interface_name, 1734 u_int32_t interface_name_siz, 1735 struct in_addr *addr, 1736 link_failure_func func) 1737{ 1738 ppp_session_clear(&pptp_session); 1739 pptp_session.sd_name = pptp_sd_name; 1740 pptp_session.interface_name = interface_name; 1741 pptp_session.interface_name_siz = interface_name_siz; 1742 pptp_session.interface_address.s_addr = addr->s_addr; 1743 pptp_session.failure_func = func; 1744 //sess->probe_timer_running = 0; 1745 pptp_ip_probe_init(pptp_session.probe_addrs, pptp_session.probe_fds, MAX_PROBE_ADDRS); 1746 pptp_session.valid = 1; 1747 session = &pptp_session; 1748} 1749