1/* 2 * Copyright (c) 2003, 2014 Apple 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 * sys-bsd.c - System-dependent procedures for setting up 25 * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.) 26 * 27 * Copyright (c) 1989 Carnegie Mellon University. 28 * Copyright (c) 1995 The Australian National University. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms are permitted 32 * provided that the above copyright notice and this paragraph are 33 * duplicated in all such forms and that any documentation, 34 * advertising materials, and other materials related to such 35 * distribution and use acknowledge that the software was developed 36 * by Carnegie Mellon University and The Australian National University. 37 * The names of the Universities may not be used to endorse or promote 38 * products derived from this software without specific prior written 39 * permission. 40 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 41 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 42 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 43 */ 44 45#define RCSID "$Id: sys-MacOSX.c,v 1.40 2006/02/16 01:47:04 lindak Exp $" 46 47/* ----------------------------------------------------------------------------- 48 Includes 49----------------------------------------------------------------------------- */ 50 51#include <stdio.h> 52#include <string.h> 53#include <stdlib.h> 54#include <unistd.h> 55#include <errno.h> 56#include <fcntl.h> 57#include <termios.h> 58#include <signal.h> 59#include <util.h> 60#include <sys/ioctl.h> 61#include <sys/types.h> 62#include <sys/socket.h> 63#include <sys/sockio.h> 64#include <sys/time.h> 65#include <sys/stat.h> 66#include <sys/param.h> 67#include <sys/wait.h> 68#include <sys/un.h> 69#include <sys/ucred.h> 70#import "acsp.h" 71#ifdef PPP_FILTER 72#include <net/bpf.h> 73#endif 74#include <net/if.h> 75#include <net/if_types.h> 76#include <mach-o/dyld.h> 77#include <dirent.h> 78#include <NSSystemDirectories.h> 79#include <mach/mach_time.h> 80#include <SystemConfiguration/SystemConfiguration.h> 81#include <SystemConfiguration/SCPrivate.h> 82#include <CoreFoundation/CFBundle.h> 83#include <CoreFoundation/CFXPCBridge.h> 84#include <ppp_defs.h> 85#include <ppp_domain.h> 86#include <ppp_msg.h> 87#include <ppp_privmsg.h> 88#include <if_ppp.h> 89#include <net/route.h> 90#include <net/if_dl.h> 91#include <netinet/in.h> 92#include <netinet/in_var.h> 93#include <netinet6/nd6.h> 94#include <netinet/if_ether.h> 95#include <syslog.h> 96#include <sys/un.h> 97#include <pthread.h> 98#include <notify.h> 99#include <IOKit/IOKitLib.h> 100#include <IOKit/network/IOEthernetInterface.h> 101#include <IOKit/network/IONetworkInterface.h> 102#include <IOKit/network/IOEthernetController.h> 103#include <servers/bootstrap.h> 104#include <arpa/inet.h> 105#include <bsm/libbsm.h> 106#include <ifaddrs.h> 107#include <netinet/ip.h> 108#include <netinet/ip_icmp.h> 109 110#include <ne_session.h> 111 112#include "pppcontroller.h" 113#include <ppp/pppcontroller_types.h> 114#include "scnc_utils_common.h" 115 116#include "../vpnd/RASSchemaDefinitions.h" 117 118 119#include "pppd.h" 120#include "fsm.h" 121#include "ipcp.h" 122#include "lcp.h" 123#include "eap.h" 124#include "../vpnd/RASSchemaDefinitions.h" 125 126#include "acscp.h" 127 128/* ----------------------------------------------------------------------------- 129 Definitions 130----------------------------------------------------------------------------- */ 131 132#define IP_FORMAT "%d.%d.%d.%d" 133#define IP_CH(ip) ((u_char *)(ip)) 134#define IP_LIST(ip) IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3] 135 136#define PPP_NKE_PATH "/System/Library/Extensions/PPP.kext" 137#define PPP_NKE_ID "com.apple.nke.ppp" 138 139/* We can get an EIO error on an ioctl if the modem has hung up */ 140#define ok_error(num) ((num)==EIO) 141 142#ifndef N_SYNC_PPP 143#define N_SYNC_PPP 14 144#endif 145 146/* 147 * If PPP_DRV_NAME is not defined, use the default "ppp" as the device name. 148 */ 149#if !defined(PPP_DRV_NAME) 150#define PPP_DRV_NAME "ppp" 151#endif /* !defined(PPP_DRV_NAME) */ 152 153/* ----------------------------------------------------------------------------- 154 Forward declarations 155----------------------------------------------------------------------------- */ 156 157static int get_flags (int fd); 158static void set_flags (int fd, int flags); 159static int set_kdebugflag(int level); 160static int make_ppp_unit(void); 161/* Prototypes for procedures local to this file. */ 162static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *)); 163static int connect_pfppp(); 164//static void sys_pidchange(void *arg, int pid); 165static void sys_phasechange(void *arg, uintptr_t phase); 166static void sys_exitnotify(void *arg, uintptr_t exitcode); 167int publish_keyentry(CFStringRef key, CFStringRef entry, CFTypeRef value); 168int publish_dictnumentry(CFStringRef dict, CFStringRef entry, int val); 169int publish_dictstrentry(CFStringRef dict, CFStringRef entry, char *str, int encoding); 170int unpublish_keyentry(CFStringRef key, CFStringRef entry); 171int unpublish_dict(CFStringRef dict); 172int publish_dns_wins_entry(CFStringRef entity, CFStringRef property1, CFTypeRef ref1, CFTypeRef ref1a, 173 CFStringRef property2, CFTypeRef ref2, 174 CFStringRef property3, CFTypeRef ref3, int clean); 175int unpublish_dictentry(CFStringRef dict, CFStringRef entry); 176static void sys_eventnotify(void *param, uintptr_t code); 177static void sys_timeremaining(void *param, uintptr_t info); 178static void sys_authpeersuccessnotify(void *param, uintptr_t info); 179static int update_stateaddr(u_int32_t o, u_int32_t h, u_int32_t m); 180int publish_stateaddr(u_int32_t o, u_int32_t h, u_int32_t m); 181int route_interface(int cmd, struct in_addr host, struct in_addr mask, char iftype, char *ifname, int is_host); 182int route_gateway(int cmd, struct in_addr dest, struct in_addr mask, struct in_addr gateway, int use_gway_flag); 183static void ppp_ip_probe_timeout (void *arg); 184static void republish_dict(); 185static int commit_publish_dict(); 186 187extern bool nelog_is_logging_at_level(int level); 188extern void nelogv(int level, const char *format, va_list args) __attribute__((format(__printf__, 2, 0))); 189 190/* ----------------------------------------------------------------------------- 191 Globals 192----------------------------------------------------------------------------- */ 193#ifndef lint 194static const char rcsid[] = RCSID; 195#endif 196 197static int ttydisc = TTYDISC; /* The default tty discipline */ 198static int pppdisc = PPPDISC; /* The PPP sync or async discipline */ 199 200static int initfdflags = -1; /* Initial file descriptor flags for ppp_fd */ 201static int ppp_fd = -1; /* fd which is set to PPP discipline */ 202static int rtm_seq; 203 204static int restore_term; /* 1 => we've munged the terminal */ 205static struct termios inittermios; /* Initial TTY termios */ 206static struct winsize wsinfo; /* Initial window size info */ 207 208static int ip_sockfd; /* socket for doing interface ioctls */ 209 210static fd_set in_fds; /* set of fds that wait_input waits for */ 211static fd_set ready_fds; /* set of fds currently ready (out of select) */ 212static int max_in_fd; /* highest fd set in in_fds */ 213 214static int if_is_up; /* the interface is currently up */ 215static int ipv4_plumbed = 0; /* is ipv4 plumbed on the interface ? */ 216static u_int32_t ifaddrs[2]; /* local and remote addresses we set */ 217static u_int32_t default_route_gateway; /* gateway addr for default route */ 218static u_int32_t proxy_arp_addr; /* remote addr for proxy arp */ 219SCDynamicStoreRef cfgCache = 0; /* configd session */ 220CFRunLoopSourceRef rls = 0; /* runloop source */ 221CFStringRef serviceidRef = 0; /* service id ref */ 222CFStringRef serveridRef = 0; /* server id ref */ 223 224extern u_char inpacket_buf[]; /* borrowed from main.c */ 225 226static u_int32_t connecttime; /* time when connection occured */ 227int looped; /* 1 if using loop */ 228int ppp_sockfd = -1; /* fd for PF_PPP socket */ 229char *serviceid = NULL; /* configuration service ID to publish */ 230char *serverid = NULL; /* server ID that spwaned this service */ 231static CFStringRef server_peer = NULL; /* remote peer address for server */ 232static char *network_signature = NULL; /* network signature */ 233bool noload = 0; /* don't load the kernel extension */ 234bool looplocal = 0; /* Don't loop local traffic destined to the local address some applications rely on this default behavior */ 235bool addifroute = 0; /* install route for the netmask of the interface */ 236bool noipv6override = 0; /* don't override IPv6 traffic if IPv4 is primary */ 237 238static struct in_addr ifroute_address; 239static struct in_addr ifroute_mask; 240static int ifroute_installed = 0; 241 242double timeScaleSeconds; /* scale factor for machine absolute time to seconds */ 243double timeScaleMicroSeconds; /* scale factor for machine absolute time to microseconds */ 244 245CFPropertyListRef userOptions = NULL; 246CFPropertyListRef systemOptions = NULL; 247 248CFMutableDictionaryRef publish_dict = NULL; 249 250option_t sys_options[] = { 251 { "serviceid", o_string, &serviceid, 252 "Service ID to publish"}, 253 { "serverid", o_string, &serverid, 254 "Server ID that spawned this service."}, 255 { "nopppload", o_bool, &noload, 256 "Don't try to load PPP NKE", 1}, 257 { "looplocal", o_bool, &looplocal, 258 "Loop local traffic destined to the local address", 1}, 259 { "noifroute", o_bool, &addifroute, 260 "Don't install route for the interface", 0}, 261 { "addifroute", o_bool, &addifroute, 262 "Install route for the interface", 1}, 263 { "nolooplocal", o_bool, &looplocal, 264 "Don't loop local traffic destined to the local address", 0}, 265 { "noipv6override", o_bool, &noipv6override, 266 "Don't override other IPv6 interfaces if ppp is default for IPv4", 1}, 267 { NULL } 268}; 269 270ppp_session_t *session = NULL; 271static int ppp_auxiliary_probe_echos_pending = 0; 272static int ppp_auxiliary_probe_success = 0; 273static int ppp_auxiliary_probe_ip_notify_init = 0; 274static int ppp_auxiliary_probe_ip = 0; 275 276static int override_primary = 0; 277static int wait_port_mapping_changed = 0; 278 279extern int kill_link; 280 281extern bool acsp_use_dhcp; // To check if we need to wait for DHCP information 282/* These booleans are meant to be set when the notifiers respond. */ 283static bool protocols_ready = false; 284static bool acspdhcp_ready = false; 285 286static bool 287ne_is_controller(void) 288{ 289 static bool result = false; 290 static dispatch_once_t init_check = 0; 291 292 dispatch_once(&init_check, ^{ result = (getenv(NESMControllerKey) != NULL); }); 293 294 return result; 295} 296 297static ne_session_t 298ne_get_session(void) 299{ 300 static ne_session_t session = NULL; 301 static dispatch_once_t session_init = 0; 302 303 dispatch_once(&session_init, 304 ^{ 305 char *env = getenv(NESMControllerKey); 306 if (env != NULL) { 307 uuid_t service_id; 308 if (uuid_parse(env, service_id) == 0) { 309 session = ne_session_create(service_id, NESessionTypeVPN); 310 } 311 } 312 }); 313 314 return session; 315} 316 317static bool 318ne_setup_security_session(void) 319{ 320 mach_port_t bootstrap_port = MACH_PORT_NULL; 321 mach_port_t audit_session_port = MACH_PORT_NULL; 322 ne_session_t session = ne_get_session(); 323 bool success; 324 325 success = (session != NULL && 326 ne_session_copy_security_session_info(session, &bootstrap_port, &audit_session_port) && 327 bootstrap_port != MACH_PORT_NULL && 328 audit_session_port != MACH_PORT_NULL && 329 task_set_bootstrap_port(mach_task_self(), bootstrap_port) == KERN_SUCCESS && 330 audit_session_join(audit_session_port) != AU_DEFAUDITSID); 331 332 if (bootstrap_port != MACH_PORT_NULL) { 333 mach_port_deallocate(mach_task_self(), bootstrap_port); 334 } 335 if (audit_session_port != MACH_PORT_NULL) { 336 mach_port_deallocate(mach_task_self(), audit_session_port); 337 } 338 339 return success; 340} 341 342static void 343ne_copy_controller_data(void) 344{ 345 ne_session_t session = ne_get_session(); 346 if (session != NULL) { 347 __block xpc_object_t configuration = NULL; 348 dispatch_semaphore_t ne_sema = dispatch_semaphore_create(0); 349 ne_session_get_info(session, NESessionInfoTypeConfiguration, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 350 ^(xpc_object_t result) { 351 if (result != NULL) { 352 configuration = xpc_retain(result); 353 } 354 dispatch_semaphore_signal(ne_sema); 355 }); 356 dispatch_semaphore_wait(ne_sema, DISPATCH_TIME_FOREVER); 357 dispatch_release(ne_sema); 358 359 if (configuration && xpc_get_type(configuration) == XPC_TYPE_DICTIONARY) { 360 xpc_object_t plist = xpc_dictionary_get_value(configuration, NESMSessionLegacyServiceConfigurationKey); 361 362 if (plist) { 363 systemOptions = _CFXPCCreateCFObjectFromXPCObject(plist); 364 } 365 366 plist = xpc_dictionary_get_value(configuration, NESMSessionLegacyUserConfigurationKey); 367 368 if (plist) { 369 userOptions = _CFXPCCreateCFObjectFromXPCObject(plist); 370 } 371 } 372 373 if (configuration != NULL) { 374 xpc_release(configuration); 375 } 376 } 377} 378 379/* ----------------------------------------------------------------------------- 380----------------------------------------------------------------------------- */ 381void closeall() 382{ 383 int i; 384 385 for (i = getdtablesize() - 1; i >= 0; i--) close(i); 386 open("/dev/null", O_RDWR, 0); 387 dup(0); 388 dup(0); 389 return; 390} 391 392/* ----------------------------------------------------------------------------- 393close all file descriptor above 'from' 394----------------------------------------------------------------------------- */ 395void closeallfrom(int from) 396{ 397 int fd; 398 struct dirent entry, *entryp; 399 400 DIR *dirp = opendir("/dev/fd"); 401 if (dirp == NULL) { 402 /* perhaps fall back on getdtablesize method */ ; 403 for (fd = from; fd < getdtablesize(); ++fd) close(fd); 404 return; 405 } 406 407 while (readdir_r(dirp, &entry, &entryp) == 0 && entryp != NULL) { 408 fd = atoi(entryp->d_name); 409 if (fd >= from && fd != dirp->__dd_fd) 410 close(fd); 411 } 412 closedir(dirp); 413} 414 415/* ----------------------------------------------------------------------------- 416----------------------------------------------------------------------------- */ 417u_long load_kext(char *kext, int byBundleID) 418{ 419 int pid; 420 421 if ((pid = fork()) < 0) 422 return 1; 423 424 if (pid == 0) { 425 closeall(); 426 // PPP kernel extension not loaded, try load it... 427 if (byBundleID) 428 execle("/sbin/kextload", "kextload", "-b", kext, (char *)0, (char *)0); 429 else 430 execle("/sbin/kextload", "kextload", kext, (char *)0, (char *)0); 431 exit(1); 432 } 433 434 while (waitpid(pid, 0, 0) < 0) { 435 if (errno == EINTR) 436 continue; 437 return 1; 438 } 439 return 0; 440} 441 442void sys_install(void) 443{ 444 if (ne_is_controller()) { 445 notice("Committed PPP store on install command\n"); 446 SCDynamicStoreSetMultiple(cfgCache, publish_dict, NULL, NULL); 447 } 448} 449 450void sys_uninstall(void) 451{ 452 if (ne_is_controller()) { 453 notice("Received uninstall command\n"); 454 if (publish_dict) { 455 CFIndex count = CFDictionaryGetCount(publish_dict); 456 if (count > 0) { 457 CFStringRef *keys = CFAllocatorAllocate(kCFAllocatorDefault, count * sizeof(*keys), 0); 458 if (keys != NULL) { 459 CFDictionaryGetKeysAndValues(publish_dict, (const void **)keys, NULL); 460 CFArrayRef keyArray = CFArrayCreate(kCFAllocatorDefault, (const void **)keys, count, &kCFTypeArrayCallBacks); 461 SCDynamicStoreSetMultiple(cfgCache, NULL, keyArray, NULL); 462 if (keyArray) { 463 CFRelease(keyArray); 464 } 465 CFAllocatorDeallocate(kCFAllocatorDefault, keys); 466 } 467 } 468 } 469 } 470} 471 472/* ----------------------------------------------------------------------------- 473preinitialize options, called before sysinit 474----------------------------------------------------------------------------- */ 475void sys_install_options() 476{ 477 add_options(sys_options); 478} 479 480/* ----------------------------------------------------------------------------- 481----------------------------------------------------------------------------- */ 482int sys_check_controller() 483{ 484 mach_port_t server; 485 kern_return_t status; 486 int result; 487 audit_token_t audit_token; 488 uid_t euid; 489 490 if (ne_is_controller()) { 491 sys_log(LOG_NOTICE, "NetworkExtension is the controller"); 492 return true; 493 } 494 495 status = bootstrap_look_up(bootstrap_port, PPPCONTROLLER_SERVER_PRIV, &server); 496 switch (status) { 497 case BOOTSTRAP_SUCCESS : 498 /* service currently registered, "a good thing" (tm) */ 499 break; 500 case BOOTSTRAP_UNKNOWN_SERVICE : 501 /* service not currently registered, try again later */ 502 return 0; 503 default : 504 return 0; 505 } 506 507 status = pppcontroller_iscontrolled(server, &result, &audit_token); 508 509 if (status == KERN_SUCCESS) { 510 audit_token_to_au32(audit_token, 511 NULL, // auidp 512 &euid, // euid 513 NULL, // egid 514 NULL, // ruid 515 NULL, // rgid 516 NULL, // pid 517 NULL, // asid 518 NULL); // tid 519 520 return ((result == kSCStatusOK) && (euid == 0)); 521 } 522 523 return 0; 524} 525 526/* ------------------------------------------------------------------------------------------- 527------------------------------------------------------------------------------------------- */ 528CFPropertyListRef Unserialize(void *data, u_int32_t dataLen) 529{ 530 CFDataRef xml; 531 CFPropertyListRef ref = 0; 532 533 xml = CFDataCreate(NULL, data, dataLen); 534 if (xml) { 535 ref = CFPropertyListCreateFromXMLData(NULL, 536 xml, kCFPropertyListImmutable, NULL); 537 CFRelease(xml); 538 } 539 540 return ref; 541} 542 543/* ----------------------------------------------------------------------------- 544----------------------------------------------------------------------------- */ 545void CopyControllerData() 546{ 547 mach_port_t server; 548 kern_return_t status; 549 void *data = NULL; 550 unsigned int datalen; 551 int result = kSCStatusFailed; 552 audit_token_t audit_token; 553 uid_t euid; 554 555 status = bootstrap_look_up(bootstrap_port, PPPCONTROLLER_SERVER_PRIV, &server); 556 switch (status) { 557 case BOOTSTRAP_SUCCESS : 558 /* service currently registered, "a good thing" (tm) */ 559 break; 560 case BOOTSTRAP_UNKNOWN_SERVICE : 561 /* service not currently registered, try again later */ 562 return ; 563 default : 564 return; 565 } 566 567 status = pppcontroller_copyprivoptions(server, 0, (xmlDataOut_t *)&data, &datalen, &result, &audit_token); 568 569 if (status != KERN_SUCCESS 570 || result != kSCStatusOK) { 571 error("cannot get private system options from controller\n"); 572 return; 573 } 574 audit_token_to_au32(audit_token, 575 NULL, // auidp 576 &euid, // euid 577 NULL, // egid 578 NULL, // ruid 579 NULL, // rgid 580 NULL, // pid 581 NULL, // asid 582 NULL); // tid 583 if (euid != 0) { 584 error("cannot authenticate private system options from controller\n"); 585 return; 586 } 587 588 systemOptions = Unserialize(data, datalen); 589 590 status = pppcontroller_copyprivoptions(server, 1, (xmlDataOut_t *)&data, &datalen, &result, &audit_token); 591 592 if (status != KERN_SUCCESS 593 || result != kSCStatusOK) { 594 error("cannot get private user options from controller\n"); 595 return; 596 } 597 audit_token_to_au32(audit_token, 598 NULL, // auidp 599 &euid, // euid 600 NULL, // egid 601 NULL, // ruid 602 NULL, // rgid 603 NULL, // pid 604 NULL, // asid 605 NULL); // tid 606 if (euid != 0) { 607 error("cannot authenticate private user options from controller\n"); 608 return; 609 } 610 611 userOptions = Unserialize(data, datalen); 612} 613 614/* ----------------------------------------------------------------------------- 615----------------------------------------------------------------------------- */ 616void CopyServerData() 617{ 618 SCPreferencesRef prefs = 0; 619 CFPropertyListRef servers_list; 620 621 // open the prefs file 622 prefs = SCPreferencesCreate(0, CFSTR("pppd"), kRASServerPrefsFileName); 623 if (prefs == NULL) { 624 fatal("Cannot open servers plist\n"); 625 return; 626 } 627 628 // get servers list from the plist 629 servers_list = SCPreferencesGetValue(prefs, kRASServers); 630 if (servers_list == NULL) { 631 fatal("No servers found in servers plist\n"); 632 CFRelease(prefs); 633 return; 634 } 635 636 systemOptions = CFDictionaryGetValue(servers_list, serveridRef); 637 if (!systemOptions || CFGetTypeID(systemOptions) != CFDictionaryGetTypeID()) { 638 fatal("Server ID '%s' not found in servers plist\n", serverid); 639 systemOptions = 0; 640 CFRelease(prefs); 641 return; 642 } 643 644 CFRetain(systemOptions); 645 CFRelease(prefs); 646} 647 648/* ----------------------------------------------------------------------------- 649 ----------------------------------------------------------------------------- */ 650void sys_protocolsreadynotify(void *param, uintptr_t info) 651{ 652 protocols_ready = true; 653 dbglog("Received protocol dictionaries\n"); 654 commit_publish_dict(); 655} 656 657/* ----------------------------------------------------------------------------- 658 ----------------------------------------------------------------------------- */ 659void sys_acspdhcpreadynotify(void *param, uintptr_t info) 660{ 661 acspdhcp_ready = true; 662 dbglog("Received acsp/dhcp dictionaries\n"); 663 commit_publish_dict(); 664} 665 666/************************************************************************** 667 To be called whenever we are potentially ready to update system config. 668 Particularly, these times are: 669 - Move into RUNNING state 670 - Receive DHCP or ACSP info 671 - Republish dictionary 672*************************************************************************/ 673static int commit_publish_dict() 674{ 675 /* Only publish one-at-a-time for demand mode */ 676 if (demand) { 677 goto fail; 678 } 679 680 /* Check if we are RUNNING, there are NO WAITING protocols, and NO WAITING DHCP info */ 681 int result = 1; 682 683 /* Make sure we're RUNNING */ 684 if (phase != PHASE_RUNNING) { 685 goto fail; 686 } 687 688 /* Make sure all protocols ready */ 689 if (!protocols_ready) { 690 goto fail; 691 } 692 693 /* Make sure all DHCP info acquired */ 694 if ((acsp_use_dhcp || acscp_protent.enabled_flag) && !acspdhcp_ready) { 695 goto fail; 696 } 697 698 /* Publish! */ 699 if (publish_dict) { 700 if (ne_is_controller()) { 701 sys_eventnotify((void*)PPP_EVT_REQUEST_INSTALL, override_primary); 702 } else { 703 notice("Committed PPP store\n"); 704 if (!SCDynamicStoreSetMultiple(cfgCache, publish_dict, NULL, NULL)) 705 result = 0; 706 } 707 } 708 709 return result; 710 711fail: 712 return 0; 713} 714 715/* ----------------------------------------------------------------------------- 716 Change dictionary to be published 717 ----------------------------------------------------------------------------- */ 718static int update_publish_dict(CFStringRef key, CFMutableDictionaryRef dict) 719{ 720 int result = 1; 721 722 if (demand) { 723 if (SCDynamicStoreSetValue(cfgCache, key, dict) == 0) 724 result = 0; 725 } 726 727 if (publish_dict) { 728 CFDictionarySetValue(publish_dict, key, dict); 729 } else { 730 result = 0; 731 } 732 733 return result; 734} 735 736/* ----------------------------------------------------------------------------- 737System-dependent initialization 738----------------------------------------------------------------------------- */ 739void sys_init() 740{ 741 int flags; 742 mach_timebase_info_data_t timebaseInfo; 743 744 openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); 745 setlogmask(LOG_UPTO(LOG_INFO)); 746 if (debug) 747 setlogmask(LOG_UPTO(LOG_DEBUG)); 748 749 // establish pppd as session leader 750 // if started via terminal, setsid will fail, which doesn't matter 751 // if started via configd, setsid will succeed and will allow reception of SIGHUP 752 setsid(); 753 754 // open a socket to the PF_PPP protocol 755 ppp_sockfd = connect_pfppp(); 756 if (ppp_sockfd < 0) 757 fatal("Couldn't open PF_PPP: %m"); 758 759 flags = fcntl(ppp_sockfd, F_GETFL); 760 if (flags == -1 761 || fcntl(ppp_sockfd, F_SETFL, flags | O_NONBLOCK) == -1) 762 warning("Couldn't set PF_PPP to nonblock: %m"); 763 764 // Get an internet socket for doing socket ioctls 765 ip_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 766 if (ip_sockfd < 0) 767 fatal("Couldn't create IP socket: %m(%d)", errno); 768 769 // serviceid is required if we want pppd to publish information into the cache 770 if (!serviceid) { 771 CFUUIDRef uuid; 772 CFStringRef strref; 773 char str[100]; 774 775 uuid = CFUUIDCreate(NULL); 776 strref = CFUUIDCreateString(NULL, uuid); 777 CFStringGetCString(strref, str, sizeof(str), kCFStringEncodingUTF8); 778 779 if ((serviceid = strdup(str)) == NULL) 780 fatal("Couldn't allocate memory to create temporary service id: %m(%d)", errno); 781 782 CFRelease(strref); 783 CFRelease(uuid); 784 } 785 786 serviceidRef = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), serviceid); 787 if (!serviceidRef) 788 fatal("Couldn't allocate memory to create service id reference: %m(%d)", errno); 789 790 /* if started as a client by PPPController 791 copy user and system options from the controller */ 792 if (controlled) { 793 if (ne_is_controller()) { 794 ne_copy_controller_data(); 795 } else { 796 CopyControllerData(); 797 } 798 } 799 800 //sys_pidchange(0, getpid()); 801 cfgCache = SCDynamicStoreCreate(0, CFSTR("pppd"), 0, 0); 802 if (cfgCache == 0) 803 fatal("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); 804 // if we are going to detach, wait to publish pid 805 if (nodetach) 806 publish_dictnumentry(kSCEntNetPPP, CFSTR("pid"), getpid()); 807 808 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPStatus, phase); 809 if (serverid) { 810 serveridRef = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), serverid); 811 if (!serveridRef) 812 fatal("Couldn't allocate memory to create server id reference: %m(%d)", errno); 813 /* copy system options from the server plist */ 814 CopyServerData(); 815 publish_dictstrentry(kSCEntNetInterface, CFSTR("ServerID"), serverid, kCFStringEncodingMacRoman); 816 } 817 818 publish_dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 819 if (!controlled && publish_dict){ 820 rls = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, cfgCache, 0); 821 if ( rls == NULL ){ 822 notice("SCDynamicStoreCreateRunLoopSource FAILED %s", SCErrorString(SCError())); 823 } else { 824 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 825 } 826 SCDynamicStoreSetDisconnectCallBack(cfgCache, republish_dict); 827 } 828 829 830 //add_notifier(&pidchange, sys_pidchange, 0); 831 add_notifier(&phasechange, sys_phasechange, 0); 832 add_notifier(&exitnotify, sys_exitnotify, 0); 833 834 // only send event if started when we are started by the PPPController 835 if (statusfd != -1) { 836 837 add_notifier(&ip_up_notify, sys_eventnotify, (void*)PPP_EVT_IPCP_UP); 838 add_notifier(&ip_down_notify, sys_eventnotify, (void*)PPP_EVT_IPCP_DOWN); 839 add_notifier(&lcp_up_notify, sys_eventnotify, (void*)PPP_EVT_LCP_UP); 840 add_notifier(&lcp_down_notify, sys_eventnotify, (void*)PPP_EVT_LCP_DOWN); 841 add_notifier(&lcp_lowerup_notify, sys_eventnotify, (void*)PPP_EVT_LOWERLAYER_UP); 842 add_notifier(&lcp_lowerdown_notify, sys_eventnotify, (void*)PPP_EVT_LOWERLAYER_DOWN); 843 add_notifier(&auth_start_notify, sys_eventnotify, (void*)PPP_EVT_AUTH_STARTED); 844 add_notifier(&auth_withpeer_fail_notify, sys_eventnotify, (void*)PPP_EVT_AUTH_FAILED); 845 add_notifier(&auth_withpeer_success_notify, sys_eventnotify, (void*)PPP_EVT_AUTH_SUCCEDED); 846 add_notifier(&connectscript_started_notify, sys_eventnotify, (void*)PPP_EVT_CONNSCRIPT_STARTED); 847 add_notifier(&connectscript_finished_notify, sys_eventnotify, (void*)PPP_EVT_CONNSCRIPT_FINISHED); 848 add_notifier(&terminalscript_started_notify, sys_eventnotify, (void*)PPP_EVT_TERMSCRIPT_STARTED); 849 add_notifier(&terminalscript_finished_notify, sys_eventnotify, (void*)PPP_EVT_TERMSCRIPT_FINISHED); 850 add_notifier(&connect_started_notify, sys_eventnotify, (void*)PPP_EVT_CONN_STARTED); 851 add_notifier(&connect_success_notify, sys_eventnotify, (void*)PPP_EVT_CONN_SUCCEDED); 852 add_notifier(&connect_fail_notify, sys_eventnotify, (void*)PPP_EVT_CONN_FAILED); 853 add_notifier(&disconnect_started_notify, sys_eventnotify, (void*)PPP_EVT_DISC_STARTED); 854 add_notifier(&disconnect_done_notify, sys_eventnotify, (void*)PPP_EVT_DISC_FINISHED); 855 add_notifier(&stop_notify, sys_eventnotify, (void*)PPP_EVT_STOPPED); 856 add_notifier(&cont_notify, sys_eventnotify, (void*)PPP_EVT_CONTINUED); 857 } 858 859 add_notifier(&lcp_timeremaining_notify, sys_timeremaining, 0); 860 add_notifier(&auth_peer_success_notify, sys_authpeersuccessnotify, 0); 861 862 add_notifier(&protocolsready_notifier, sys_protocolsreadynotify, 0); 863 add_notifier(&acspdhcpready_notifier, sys_acspdhcpreadynotify, 0); 864 865 if (mach_timebase_info(&timebaseInfo) == KERN_SUCCESS) { // returns scale factor for ns 866 timeScaleMicroSeconds = ((double) timebaseInfo.numer / (double) timebaseInfo.denom) / 1000; 867 timeScaleSeconds = timeScaleMicroSeconds / 1000000; 868 } 869 870 FD_ZERO(&in_fds); 871 FD_ZERO(&ready_fds); 872 max_in_fd = 0; 873} 874 875/* ----------------------------------------------------------------------------- 876 sys_cleanup - restore any system state we modified before exiting: 877 mark the interface down, delete default route and/or proxy arp entry. 878 This should call die() because it's called from die() 879----------------------------------------------------------------------------- */ 880void sys_cleanup() 881{ 882 struct ifreq ifr; 883 884 if (!controlled && rls) { 885 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 886 CFRunLoopSourceInvalidate(rls); 887 CFRelease(rls); 888 rls = NULL; 889 } 890 891 cifroute(); 892 893 if (if_is_up) { 894 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 895 if (ioctl(ip_sockfd, SIOCGIFFLAGS, &ifr) >= 0 896 && ((ifr.ifr_flags & IFF_UP) != 0)) { 897 ifr.ifr_flags &= ~IFF_UP; 898 ioctl(ip_sockfd, SIOCSIFFLAGS, &ifr); 899 } 900 } 901 902 if (ifaddrs[0] != 0) 903 cifaddr(0, ifaddrs[0], ifaddrs[1]); 904 905 if (default_route_gateway) 906 cifdefaultroute(0, 0, default_route_gateway); 907 if (proxy_arp_addr) 908 cifproxyarp(0, proxy_arp_addr); 909} 910 911/* ----------------------------------------------------------------------------- 912 sys_runloop - called from main loop 913----------------------------------------------------------------------------- */ 914void sys_runloop() 915{ 916 if (!controlled && rls) { 917 if (kill_link) 918 CFRunLoopStop(CFRunLoopGetCurrent()); 919 else 920 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); 921 } 922} 923 924/* ----------------------------------------------------------------------------- 925----------------------------------------------------------------------------- */ 926void set_network_signature(char *key1, char *val1, char *key2, char *val2) 927{ 928 int len = 0; 929 930 if (network_signature) { 931 free(network_signature); 932 network_signature = 0; 933 } 934 935 if (key1) 936 len += strlen(key1) + strlen(val1) + 1; 937 if (key2) { 938 if (key1) len++; // add separator ";" 939 len += strlen(key2) + strlen(val2) + 1; 940 } 941 942 if (len) { 943 network_signature = malloc(len + 1); 944 if (!network_signature) { 945 warning("no memory to create network signature"); 946 return; 947 } 948 network_signature[0] = 0; 949 if (key1) { 950 strlcat(network_signature, key1, len + 1); 951 strlcat(network_signature, "=", len + 1); 952 strlcat(network_signature, val1, len + 1); 953 } 954 if (key2) { 955 if (key1) strlcat(network_signature, ";", len + 1); 956 strlcat(network_signature, key2, len + 1); 957 strlcat(network_signature, "=", len + 1); 958 strlcat(network_signature, val2, len + 1); 959 } 960 } 961} 962 963 964/* ----------------------------------------------------------------------------- 965 ----------------------------------------------------------------------------- */ 966void set_server_peer(struct in_addr peer) 967{ 968 if (server_peer) { 969 CFRelease(server_peer); 970 server_peer = NULL; 971 } 972 973 server_peer = CFStringCreateWithCString(NULL, inet_ntoa(peer), kCFStringEncodingASCII); 974} 975 976 977/* ----------------------------------------------------------------------------- 978----------------------------------------------------------------------------- */ 979void sys_close() 980{ 981 if (ip_sockfd != -1) { 982 close(ip_sockfd); 983 ip_sockfd = -1; 984 } 985 if (ppp_sockfd != -1) { 986 close(ppp_sockfd); 987 ppp_sockfd = -1; 988 } 989} 990 991/* ----------------------------------------------------------------------------- 992 Functions to read and set the flags value in the device driver 993----------------------------------------------------------------------------- */ 994static int get_flags (int fd) 995{ 996 int flags; 997 998 if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) { 999 if ( ok_error (errno) ) 1000 flags = 0; 1001 else 1002 fatal("ioctl(PPPIOCGFLAGS): %m"); 1003 } 1004 1005 SYSDEBUG ((LOG_DEBUG, "get flags = %x\n", flags)); 1006 return flags; 1007} 1008 1009/* ----------------------------------------------------------------------------- 1010----------------------------------------------------------------------------- */ 1011static void set_flags (int fd, int flags) 1012{ 1013 SYSDEBUG ((LOG_DEBUG, "set flags = %x\n", flags)); 1014 1015 if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0) { 1016 if (! ok_error (errno) ) 1017 fatal("ioctl(PPPIOCSFLAGS, %x): %m", flags, errno); 1018 } 1019} 1020 1021/* ----------------------------------------------------------------------------- 1022----------------------------------------------------------------------------- */ 1023void sys_notify(u_int32_t message, uintptr_t code1, uintptr_t code2) 1024{ 1025 struct ppp_msg_hdr *hdr; 1026 int servlen, totlen; 1027 u_char *p, *msg; 1028 1029 if (statusfd == -1) 1030 return; 1031 1032 servlen = strlen(serviceid); 1033 totlen = sizeof(struct ppp_msg_hdr) + servlen + 8; 1034 1035 msg = malloc(totlen); 1036 if (!msg) { 1037 warning("no memory to send event to PPPController"); 1038 return; 1039 } 1040 1041 p = msg; 1042 bzero(p, totlen); 1043 hdr = ALIGNED_CAST(struct ppp_msg_hdr *)p; 1044 hdr->m_type = message; 1045 hdr->m_len = 8; 1046 hdr->m_flags |= USE_SERVICEID; 1047 hdr->m_link = servlen; 1048 1049 p += sizeof(struct ppp_msg_hdr); 1050 bcopy(serviceid, p, servlen); 1051 p += servlen; 1052 bcopy((u_char*)&code1, p, 4); 1053 p += 4; 1054 bcopy((u_char*)&code2, p, 4); 1055 1056 if (write(statusfd, msg, totlen) != totlen) { 1057 warning("can't talk to PPPController : %m"); 1058 } 1059 free(msg); 1060} 1061 1062/* ----------------------------------------------------------------------------- 1063we installed the notifier with the event as the parameter 1064----------------------------------------------------------------------------- */ 1065void sys_eventnotify(void *param, uintptr_t code) 1066{ 1067 1068 if (param == (void*)PPP_EVT_CONN_FAILED) 1069 code = EXIT_CONNECT_FAILED; 1070 1071 sys_notify(PPPD_EVENT, (uintptr_t)param, code); 1072} 1073 1074/* ----------------------------------------------------------------------------- 1075send status notification to the controller 1076----------------------------------------------------------------------------- */ 1077void sys_statusnotify() 1078{ 1079 1080 sys_notify(PPPD_STATUS, status, devstatus); 1081} 1082 1083 1084/* ----------------------------------------------------------------------------- 1085check the options that the user specified 1086----------------------------------------------------------------------------- */ 1087int sys_check_options() 1088{ 1089#ifndef CDTRCTS 1090 if (crtscts == 2) { 1091 warning("DTR/CTS flow control is not supported on this system"); 1092 return 0; 1093 } 1094#endif 1095 return 1; 1096} 1097 1098/* ----------------------------------------------------------------------------- 1099check if the kernel supports PPP 1100----------------------------------------------------------------------------- */ 1101int ppp_available() 1102{ 1103 int s; 1104 extern char *no_ppp_msg; 1105 1106 no_ppp_msg = "\ 1107Mac OS X lacks kernel support for PPP. \n\ 1108To include PPP support in the kernel, please follow \n\ 1109the steps detailed in the README.MacOSX file.\n"; 1110 1111 // open to socket to the PF_PPP family 1112 // if that works, the kernel extension is loaded. 1113 if ((s = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL)) < 0) { 1114 1115#if !TARGET_OS_EMBEDDED 1116 if (!noload && !load_kext(PPP_NKE_PATH, 0)) 1117#else 1118 if (!noload && !load_kext(PPP_NKE_ID, 1)) 1119#endif 1120 s = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL); 1121 1122 if (s < 0) 1123 return 0; 1124 } 1125 1126 // could be smarter and get the version of the ppp family, 1127 // using get option or ioctl 1128 1129 close(s); 1130 1131 return 1; 1132} 1133 1134/* ----------------------------------------------------------------------------- 1135----------------------------------------------------------------------------- */ 1136static int still_ppp(void) 1137{ 1138 1139 return !hungup && ppp_fd >= 0; 1140} 1141 1142/* ----------------------------------------------------------------------------- 1143Define the debugging level for the kernel 1144----------------------------------------------------------------------------- */ 1145static int set_kdebugflag (int requested_level) 1146{ 1147 if (ifunit < 0) 1148 return 1; 1149 if (ioctl(ppp_sockfd, PPPIOCSDEBUG, &requested_level) < 0) { 1150 if ( ! ok_error (errno) ) 1151 error("ioctl(PPPIOCSDEBUG): %m"); 1152 return (0); 1153 } 1154 SYSDEBUG ((LOG_INFO, "set kernel debugging level to %d", 1155 requested_level)); 1156 return (1); 1157} 1158 1159/* ----------------------------------------------------------------------------- 1160make a new ppp unit for ppp_sockfd 1161----------------------------------------------------------------------------- */ 1162static int make_ppp_unit() 1163{ 1164 int x; 1165 char name[32]; 1166 1167 ifunit = req_unit; 1168 x = ioctl(ppp_sockfd, PPPIOCNEWUNIT, &ifunit); 1169 if (x < 0 && req_unit >= 0 && errno == EEXIST) { 1170 warning("Couldn't allocate PPP unit %d as it is already in use"); 1171 ifunit = -1; 1172 x = ioctl(ppp_sockfd, PPPIOCNEWUNIT, &ifunit); 1173 1174 1175 } 1176 if (x < 0) 1177 error("Couldn't create new ppp unit: %m"); 1178 else { 1179 slprintf(name, sizeof(name), "%s%d", PPP_DRV_NAME, ifunit); 1180 publish_dictstrentry(kSCEntNetPPP, kSCPropInterfaceName, name, kCFStringEncodingMacRoman); 1181 } 1182 1183 return x; 1184} 1185 1186/* ----------------------------------------------------------------------------- 1187coen a socket to the PF_PPP protocol 1188----------------------------------------------------------------------------- */ 1189int connect_pfppp() 1190{ 1191 int fd = -1; 1192 struct sockaddr_ppp pppaddr; 1193 1194 // open a PF_PPP socket 1195 fd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL); 1196 if (fd < 0) { 1197 error("Couldn't open PF_PPP: %m"); 1198 return -1; 1199 } 1200 // need to connect to the PPP protocol 1201 pppaddr.ppp_len = sizeof(struct sockaddr_ppp); 1202 pppaddr.ppp_family = AF_PPP; 1203 pppaddr.ppp_proto = PPPPROTO_CTL; 1204 pppaddr.ppp_cookie = 0; 1205 if (connect(fd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0) { 1206 error("Couldn't connect to PF_PPP: %m"); 1207 close(fd); 1208 return -1; 1209 } 1210 return fd; 1211} 1212 1213 1214/* ----------------------------------------------------------------------------- 1215Turn the serial port into a ppp interface 1216----------------------------------------------------------------------------- */ 1217int tty_establish_ppp (int tty_fd) 1218{ 1219 int new_fd; 1220 1221 // First, turn the device into ppp link 1222 1223 /* Ensure that the tty device is in exclusive mode. */ 1224 ioctl(tty_fd, TIOCEXCL, 0); 1225 1226 // Set the current tty to the PPP discpline 1227 pppdisc = sync_serial ? N_SYNC_PPP: PPPDISC; 1228 if (ioctl(tty_fd, TIOCSETD, &pppdisc) < 0) { 1229 if ( ! ok_error (errno) ) { 1230 error("Couldn't set tty to PPP discipline: %m"); 1231 return -1; 1232 } 1233 } 1234 1235 // Then, then do the generic link work, and get a generic fd back 1236 1237 new_fd = generic_establish_ppp(tty_fd, NULL); 1238 if (new_fd == -1) { 1239 // Restore the previous line discipline 1240 if (ioctl(tty_fd, TIOCSETD, &ttydisc) < 0) 1241 if ( ! ok_error (errno)) 1242 error("ioctl(TIOCSETD, TTYDISC): %m"); 1243 return -1; 1244 } 1245 1246 set_flags(new_fd, get_flags(ppp_fd) & ~(SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP)); 1247 1248 return new_fd; 1249} 1250 1251/* ----------------------------------------------------------------------------- 1252Restore the serial port to normal operation. 1253This shouldn't call die() because it's called from die() 1254----------------------------------------------------------------------------- */ 1255void tty_disestablish_ppp(int tty_fd) 1256{ 1257 1258 if (!hungup) { 1259 1260 // Flush the tty output buffer so that the TIOCSETD doesn't hang. 1261 //if (tcflush(tty_fd, TCIOFLUSH) < 0) 1262 // warning("tcflush failed: %m"); 1263 1264 // Restore the previous line discipline 1265 if (ioctl(tty_fd, TIOCSETD, &ttydisc) < 0) { 1266 if ( ! ok_error (errno)) 1267 error("ioctl(TIOCSETD, TTYDISC): %m"); 1268 } 1269 1270 if (ioctl(tty_fd, TIOCNXCL, 0) < 0) { 1271 if ( ! ok_error (errno)) 1272 warning("ioctl(TIOCNXCL): %m(%d)", errno); 1273 } 1274 1275 // Reset non-blocking mode on fd 1276 if (initfdflags != -1 && fcntl(tty_fd, F_SETFL, initfdflags) < 0) { 1277 if ( ! ok_error (errno)) 1278 warning("Couldn't restore device fd flags: %m"); 1279 } 1280 } 1281 1282 initfdflags = -1; 1283 1284 generic_disestablish_ppp(tty_fd); 1285} 1286 1287/* ----------------------------------------------------------------------------- 1288generic code to establish ppp interface 1289----------------------------------------------------------------------------- */ 1290int generic_establish_ppp (int fd, UInt8 *delegate) 1291{ 1292 int flags, s = -1, link = 0; 1293 1294 // Open another instance of the ppp socket and connect the link to it 1295 if (ioctl(fd, PPPIOCGCHAN, &link) == -1) { 1296 error("Couldn't get link number: %m"); 1297 goto err; 1298 } 1299 1300 dbglog("using link %d", link); 1301 1302 // open a socket to the PPP protocol 1303 s = connect_pfppp(); 1304 if (s < 0) { 1305 error("Couldn't reopen PF_PPP: %m"); 1306 goto err; 1307 } 1308 1309 if (ioctl(s, PPPIOCATTCHAN, &link) < 0) { 1310 error("Couldn't attach to the ppp link %d: %m", link); 1311 goto err_close; 1312 } 1313 1314 flags = fcntl(s, F_GETFL); 1315 if (flags == -1 || fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) 1316 warning("Couldn't set ppp socket link to nonblock: %m"); 1317 1318 /* set the ppp_fd socket now */ 1319 ppp_fd = s; 1320 1321 if (!looped) 1322 ifunit = -1; 1323 if (!looped && !multilink) { 1324 // Create a new PPP unit. 1325 if (make_ppp_unit() < 0) 1326 goto err_close; 1327 } 1328 1329 // set the delegate interface 1330 if (delegate) { 1331 if (ioctl(ppp_sockfd, PPPIOCSDELEGATE, delegate) < 0) { 1332 error("Couldn't set the delegate interface: %m"); 1333 goto err_close; 1334 } 1335 } 1336 1337 if (looped) { 1338 set_flags(ppp_sockfd, get_flags(ppp_sockfd) & ~SC_LOOP_TRAFFIC); 1339 looped = 0; 1340 } 1341 1342 if (!multilink) { 1343 add_fd(ppp_sockfd); 1344 if (ioctl(s, PPPIOCCONNECT, &ifunit) < 0) { 1345 error("Couldn't attach to PPP unit %d: %m", ifunit); 1346 goto err_close; 1347 } 1348 } 1349 1350 // Enable debug in the driver if requested. 1351 set_kdebugflag (kdebugflag); 1352 1353 return ppp_fd; 1354 1355 err_close: 1356 close(s); 1357 1358 err: 1359 return -1; 1360} 1361 1362/* ----------------------------------------------------------------------------- 1363Restore the serial port to normal operation. 1364This shouldn't call die() because it's called from die() 1365fd is the file descriptor of the device 1366----------------------------------------------------------------------------- */ 1367void generic_disestablish_ppp(int fd) 1368{ 1369 int x; 1370 1371 close(ppp_fd); 1372 ppp_fd = -1; 1373 if (demand) { 1374 looped = 1; 1375 set_flags(ppp_sockfd, get_flags(ppp_sockfd) | SC_LOOP_TRAFFIC); 1376 } 1377 else { 1378 unpublish_dictentry(kSCEntNetPPP, kSCPropInterfaceName); 1379 if (ifunit >= 0 && ioctl(ppp_sockfd, PPPIOCDETACH, &x) < 0) 1380 error("Couldn't release PPP unit ppp_sockfd %d: %m", ppp_sockfd); 1381 } 1382 if (!multilink) 1383 remove_fd(ppp_sockfd); 1384} 1385 1386/* ----------------------------------------------------------------------------- 1387Check whether the link seems not to be 8-bit clean 1388----------------------------------------------------------------------------- */ 1389void clean_check() 1390{ 1391 int x; 1392 char *s; 1393 1394 if (!still_ppp()) 1395 return; 1396 1397 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) { 1398 s = NULL; 1399 switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) { 1400 case SC_RCV_B7_0: 1401 s = "bit 7 set to 1"; 1402 break; 1403 case SC_RCV_B7_1: 1404 s = "bit 7 set to 0"; 1405 break; 1406 case SC_RCV_EVNP: 1407 s = "odd parity"; 1408 break; 1409 case SC_RCV_ODDP: 1410 s = "even parity"; 1411 break; 1412 } 1413 if (s != NULL) { 1414 warning("Serial link is not 8-bit clean:"); 1415 warning("All received characters had %s", s); 1416 } 1417 } 1418} 1419 1420/* ----------------------------------------------------------------------------- 1421Set up the serial port on `fd' for 8 bits, no parity, 1422 * at the requested speed, etc. If `local' is true, set CLOCAL 1423 * regardless of whether the modem option was specified. 1424 * 1425 * For *BSD, we assume that speed_t values numerically equal bits/second 1426----------------------------------------------------------------------------- */ 1427void set_up_tty(int fd, int local) 1428{ 1429 struct termios tios; 1430 1431 // set the file descriptor as the controlling terminal, in order to receive SIGHUP 1432 if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) 1433 error("set_up_tty, can't set controlling terminal: %m"); 1434 1435 if (tcgetattr(fd, &tios) < 0) { 1436 error("tcgetattr: %m"); 1437 return; 1438 } 1439 1440 if (!restore_term) { 1441 inittermios = tios; 1442 ioctl(fd, TIOCGWINSZ, &wsinfo); 1443 } 1444 1445 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); 1446 if (crtscts > 0 && !local) { 1447 if (crtscts == 2) { 1448#ifdef CDTRCTS 1449 tios.c_cflag |= CDTRCTS; 1450#endif 1451 } else 1452 tios.c_cflag |= CRTSCTS; 1453 } else if (crtscts < 0) { 1454 tios.c_cflag &= ~CRTSCTS; 1455#ifdef CDTRCTS 1456 tios.c_cflag &= ~CDTRCTS; 1457#endif 1458 } 1459 1460 tios.c_cflag |= CS8 | CREAD | HUPCL; 1461 if (local || !modem) 1462 tios.c_cflag |= CLOCAL; 1463 tios.c_iflag = IGNBRK | IGNPAR; 1464 tios.c_oflag = 0; 1465 tios.c_lflag = 0; 1466 tios.c_cc[VMIN] = 1; 1467 tios.c_cc[VTIME] = 0; 1468 1469 if (crtscts == -2) { 1470 tios.c_iflag |= IXON | IXOFF; 1471 tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ 1472 tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ 1473 } 1474 1475 if (inspeed) { 1476 cfsetospeed(&tios, inspeed); 1477 cfsetispeed(&tios, inspeed); 1478 } else { 1479 inspeed = cfgetospeed(&tios); 1480 /* 1481 * We can't proceed if the serial port speed is 0, 1482 * since that implies that the serial port is disabled. 1483 */ 1484 if (inspeed == 0) 1485 fatal("Baud rate for %s is 0; need explicit baud rate", devnam); 1486 } 1487 1488 baud_rate = inspeed; 1489 if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) 1490 fatal("tcsetattr: %m"); 1491 1492 restore_term = 1; 1493} 1494 1495 1496/* ----------------------------------------------------------------------------- 1497Set up the serial port 1498 * If `local' is true, set CLOCAL 1499 * regardless of whether the modem option was specified. 1500 * other parameter (speed, start/stop bits, parity) may have been changed by the CCL 1501----------------------------------------------------------------------------- */ 1502void set_up_tty_local(int fd, int local) 1503{ 1504 struct termios tios; 1505 1506 if (tcgetattr(fd, &tios) < 0) { 1507 error("tcgetattr: %m"); 1508 return; 1509 } 1510 1511 tios.c_cc[VMIN] = 1; 1512 tios.c_cc[VTIME] = 0; 1513 1514 tios.c_cflag &= ~CLOCAL; 1515 if (local || !modem) 1516 tios.c_cflag |= CLOCAL; 1517 1518 if (tcsetattr(fd, TCSANOW, &tios) < 0) 1519 fatal("tcsetattr: %m"); 1520} 1521 1522/* ----------------------------------------------------------------------------- 1523restore the terminal to the saved settings 1524----------------------------------------------------------------------------- */ 1525void restore_tty(int fd) 1526{ 1527 if (restore_term) { 1528 if (!default_device) { 1529 /* 1530 * Turn off echoing, because otherwise we can get into 1531 * a loop with the tty and the modem echoing to each other. 1532 * We presume we are the sole user of this tty device, so 1533 * when we close it, it will revert to its defaults anyway. 1534 */ 1535 inittermios.c_lflag &= ~(ECHO | ECHONL); 1536 } 1537 if (!hungup) { 1538 if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) 1539 if (errno != ENXIO) 1540 warning("tcsetattr: %m"); 1541 ioctl(fd, TIOCSWINSZ, &wsinfo); 1542 } 1543 restore_term = 0; 1544 } 1545} 1546 1547/* ----------------------------------------------------------------------------- 1548control the DTR line on the serial port. 1549 * This is called from die(), so it shouldn't call die() 1550----------------------------------------------------------------------------- */ 1551void setdtr(int fd, int on) 1552{ 1553 int modembits = TIOCM_DTR; 1554 1555 ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); 1556} 1557 1558/* ----------------------------------------------------------------------------- 1559get a pty master/slave pair and chown the slave side 1560 * to the uid given. Assumes slave_name points to >= 12 bytes of space 1561----------------------------------------------------------------------------- */ 1562int get_pty(int *master_fdp, int *slave_fdp, char *slave_name, int uid) 1563{ 1564 struct termios tios; 1565 1566 if (openpty(master_fdp, slave_fdp, slave_name, NULL, NULL) < 0) 1567 return 0; 1568 1569 fchown(*slave_fdp, uid, -1); 1570 fchmod(*slave_fdp, S_IRUSR | S_IWUSR); 1571 if (tcgetattr(*slave_fdp, &tios) == 0) { 1572 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB); 1573 tios.c_cflag |= CS8 | CREAD; 1574 tios.c_iflag = IGNPAR | CLOCAL; 1575 tios.c_oflag = 0; 1576 tios.c_lflag = 0; 1577 if (tcsetattr(*slave_fdp, TCSAFLUSH, &tios) < 0) 1578 warning("couldn't set attributes on pty: %m"); 1579 } else 1580 warning("couldn't get attributes on pty: %m"); 1581 1582 return 1; 1583} 1584 1585/* ----------------------------------------------------------------------------- 1586create the ppp interface and configure it in loopback mode. 1587----------------------------------------------------------------------------- */ 1588int open_ppp_loopback() 1589{ 1590 looped = 1; 1591 /* allocate ourselves a ppp unit */ 1592 if (make_ppp_unit() < 0) 1593 die(1); 1594 set_flags(ppp_sockfd, SC_LOOP_TRAFFIC); 1595 set_kdebugflag(kdebugflag); 1596 ppp_fd = -1; 1597 return ppp_sockfd; 1598} 1599 1600/* ----------------------------------------------------------------------------- 1601Output PPP packet 1602----------------------------------------------------------------------------- */ 1603void output(int unit, u_char *p, int len) 1604{ 1605 1606 dump_packet("sent", p, len); 1607 1608 // don't write FF03 1609 len -= 2; 1610 p += 2; 1611 1612 // link protocol are sent to the link 1613 // other protocols are send to the bundle 1614 /* test was changed because compiler strangeness for embedded os */ 1615// if (write((ntohs(*(u_short*)p) >= 0xC000) ? ppp_fd : ppp_sockfd, p, len) < 0) { 1616 if (write((p[0] >= 0xC0) ? ppp_fd : ppp_sockfd, p, len) < 0) { 1617 if (errno != EIO) 1618 error("write: %m"); 1619 } 1620} 1621 1622/* ----------------------------------------------------------------------------- 1623wait until there is data available, for the length of time specified by *timo 1624(indefinite if timo is NULL) 1625----------------------------------------------------------------------------- */ 1626void wait_input(struct timeval *timo) 1627{ 1628 int n; 1629 1630 ready_fds = in_fds; 1631 n = select(max_in_fd + 1, &ready_fds, NULL, NULL, timo); 1632 if (n < 0 && errno != EINTR) 1633 fatal("select: %m"); 1634 1635 if (n < 0) { 1636 FD_ZERO(&ready_fds); 1637 } 1638} 1639 1640/* ----------------------------------------------------------------------------- 1641wait on fd until there is data available, for the delay in milliseconds 1642return 0 if timeout expires, < 0 if error, otherwise > 0 1643----------------------------------------------------------------------------- */ 1644int wait_input_fd(int fd, int delay) 1645{ 1646 fd_set ready; 1647 int n; 1648 struct timeval t; 1649 1650 t.tv_sec = delay / 1000; 1651 t.tv_usec = delay % 1000; 1652 1653 FD_ZERO(&ready); 1654 FD_SET(fd, &ready); 1655 1656 do { 1657 n = select(fd + 1, &ready, NULL, &ready, &t); 1658 } while (n < 0 && errno == EINTR); 1659 1660 if (n > 0) 1661 if (ioctl(fd, FIONREAD, &n) == -1) 1662 n = -1; 1663 1664 return n; 1665} 1666 1667 1668/* ----------------------------------------------------------------------------- 1669add an fd to the set that wait_input waits for 1670----------------------------------------------------------------------------- */ 1671void add_fd(int fd) 1672{ 1673 FD_SET(fd, &in_fds); 1674 if (fd > max_in_fd) 1675 max_in_fd = fd; 1676} 1677 1678/* ----------------------------------------------------------------------------- 1679remove an fd from the set that wait_input waits for 1680----------------------------------------------------------------------------- */ 1681void remove_fd(int fd) 1682{ 1683 FD_CLR(fd, &in_fds); 1684} 1685 1686/* ----------------------------------------------------------------------------- 1687return 1 is fd is set (i.e. select returned with this file descriptor set) 1688----------------------------------------------------------------------------- */ 1689bool is_ready_fd(int fd) 1690{ 1691 return (FD_ISSET(fd, &ready_fds) != 0); 1692} 1693 1694/* ----------------------------------------------------------------------------- 1695get a PPP packet from the serial device 1696----------------------------------------------------------------------------- */ 1697int read_packet(u_char *buf) 1698{ 1699 int len = -1; 1700 1701 // FF03 are not read 1702 *buf++ = PPP_ALLSTATIONS; 1703 *buf++ = PPP_UI; 1704 1705 // read first the socket attached to the link 1706 if (ppp_fd >= 0) { 1707 if ((len = read(ppp_fd, buf, PPP_MRU + PPP_HDRLEN - 2)) < 0) { 1708 if (errno != EWOULDBLOCK && errno != EINTR) 1709 error("read from socket link: %m"); 1710 } 1711 } 1712 1713 // then, if nothing, link the socket attached to the bundle 1714 if (len < 0 && ifunit >= 0) { 1715 if ((len = read(ppp_sockfd, buf, PPP_MRU + PPP_HDRLEN - 2)) < 0) { 1716 if (errno != EWOULDBLOCK && errno != EINTR) 1717 error("read from socket bundle: %m"); 1718 } 1719 } 1720 return (len <= 0 ? len : len + 2); 1721} 1722 1723/* ----------------------------------------------------------------------------- 1724 read characters from the loopback, form them 1725 * into frames, and detect when we want to bring the real link up. 1726 * Return value is 1 if we need to bring up the link, 0 otherwise 1727----------------------------------------------------------------------------- */ 1728int get_loop_output() 1729{ 1730 int rv = 0; 1731 int n; 1732 1733 while ((n = read_packet(inpacket_buf)) > 0) 1734 if (loop_frame(inpacket_buf, n)) 1735 rv = 1; 1736 return rv; 1737} 1738 1739/* ----------------------------------------------------------------------------- 1740configure the transmit characteristics of the ppp interface 1741 ----------------------------------------------------------------------------- */ 1742void tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp) 1743{ 1744 u_int x; 1745 1746 if (!still_ppp()) 1747 return; 1748 1749 if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) 1750 fatal("ioctl(PPPIOCSASYNCMAP): %m"); 1751 1752 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) 1753 fatal("ioctl (PPPIOCGFLAGS): %m"); 1754 x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT; 1755 x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC; 1756 x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC; 1757 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 1758 fatal("ioctl(PPPIOCSFLAGS): %m"); 1759 1760 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPCompressionPField, pcomp); 1761 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPCompressionACField, accomp); 1762 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPTransmitACCM, asyncmap); 1763} 1764 1765/* ----------------------------------------------------------------------------- 1766configure the transmit characteristics of the ppp interface 1767function used for synchronous links, asyncmap is irrelevant 1768 ----------------------------------------------------------------------------- */ 1769void generic_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp) 1770{ 1771 u_int x; 1772 1773 if (!still_ppp()) 1774 return; 1775 1776 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) 1777 fatal("ioctl (PPPIOCGFLAGS): %m"); 1778 x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT; 1779 x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC; 1780 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 1781 fatal("ioctl(PPPIOCSFLAGS): %m"); 1782 1783 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPCompressionPField, pcomp); 1784 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPCompressionACField, accomp); 1785} 1786 1787/* ----------------------------------------------------------------------------- 1788set the MTU on the PPP network interface 1789----------------------------------------------------------------------------- */ 1790void netif_set_mtu(int unit, int mtu) 1791{ 1792 struct ifreq ifr; 1793 1794 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 1795 ifr.ifr_mtu = mtu; 1796 if (ioctl(ip_sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) 1797 error("ioctl (SIOCSIFMTU): %m"); 1798 1799 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPMTU, mtu); 1800} 1801 1802/* ----------------------------------------------------------------------------- 1803get the MTU on the PPP network interface 1804----------------------------------------------------------------------------- */ 1805int netif_get_mtu(int unit) 1806{ 1807 struct ifreq ifr; 1808 1809 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 1810 if (ioctl(ip_sockfd, SIOCGIFMTU, (caddr_t) &ifr) < 0) { 1811 error("ioctl (SIOCGIFMTU): %m"); 1812 return 0; 1813 } 1814 return ifr.ifr_mtu; 1815} 1816 1817 1818/* ----------------------------------------------------------------------------- 1819stop traffic on this link 1820 ----------------------------------------------------------------------------- */ 1821void ppp_hold(int unit) 1822{ 1823 u_int x; 1824 1825 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 1826 warning("ioctl (PPPIOCGFLAGS): %m"); 1827 return; 1828 } 1829 x |= SC_HOLD; 1830 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 1831 warning("ioctl(PPPIOCSFLAGS): %m"); 1832} 1833 1834/* ----------------------------------------------------------------------------- 1835resume traffic on this link 1836 ----------------------------------------------------------------------------- */ 1837void ppp_cont(int unit) 1838{ 1839 u_int x; 1840 1841 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 1842 warning("ioctl (PPPIOCGFLAGS): %m"); 1843 return; 1844 } 1845 x &= ~SC_HOLD; 1846 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 1847 warning("ioctl(PPPIOCSFLAGS): %m"); 1848} 1849 1850/* ----------------------------------------------------------------------------- 1851set the extended transmit ACCM for the interface 1852----------------------------------------------------------------------------- */ 1853void tty_set_xaccm(ext_accm accm) 1854{ 1855 if (!still_ppp()) 1856 return; 1857 if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) 1858 warning("ioctl(set extended ACCM): %m"); 1859} 1860 1861/* ----------------------------------------------------------------------------- 1862configure the receive-side characteristics of the ppp interface. 1863----------------------------------------------------------------------------- */ 1864void tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp) 1865{ 1866 int x; 1867 1868 if (!still_ppp()) 1869 return; 1870 1871 if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) 1872 fatal("ioctl(PPPIOCSMRU): %m"); 1873 if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) 1874 fatal("ioctl(PPPIOCSRASYNCMAP): %m"); 1875 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) 1876 fatal("ioctl (PPPIOCGFLAGS): %m"); 1877 x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC; 1878 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 1879 fatal("ioctl(PPPIOCSFLAGS): %m"); 1880 1881 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPMRU, mru); 1882 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPReceiveACCM, asyncmap); 1883} 1884 1885/* ----------------------------------------------------------------------------- 1886configure the receive-side characteristics of the ppp interface. 1887function used for synchronous links, asyncmap is irrelevant 1888----------------------------------------------------------------------------- */ 1889void generic_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp) 1890{ 1891 int x; 1892 1893 if (!still_ppp()) 1894 return; 1895 1896 if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) 1897 fatal("ioctl(PPPIOCSMRU): %m"); 1898 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) 1899 fatal("ioctl (PPPIOCGFLAGS): %m"); 1900 x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC; 1901 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 1902 fatal("ioctl(PPPIOCSFLAGS): %m"); 1903 1904 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPLCPMRU, mru); 1905} 1906 1907/* ----------------------------------------------------------------------------- 1908ask kernel whether a given compression method 1909 * is acceptable for use. Returns 1 if the method and parameters 1910 * are OK, 0 if the method is known but the parameters are not OK 1911 * (e.g. code size should be reduced), or -1 if the method is unknown 1912 ----------------------------------------------------------------------------- */ 1913int ccp_test(int unit, u_char * opt_ptr, int opt_len, int for_transmit) 1914{ 1915 struct ppp_option_data data; 1916 1917 data.ptr = opt_ptr; 1918 data.length = opt_len; 1919 data.transmit = for_transmit; 1920 if (ioctl(ppp_sockfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0) 1921 return 1; 1922 return (errno == ENOBUFS)? 0: -1; 1923} 1924 1925/* ----------------------------------------------------------------------------- 1926inform kernel about the current state of CCP 1927----------------------------------------------------------------------------- */ 1928void ccp_flags_set(int unit, int isopen, int isup) 1929{ 1930 int x; 1931 1932 if (!still_ppp()) 1933 return; 1934 1935 if (ioctl(ppp_sockfd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 1936 error("ioctl (PPPIOCGFLAGS): %m"); 1937 return; 1938 } 1939 1940 x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN; 1941 x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP; 1942 if (ioctl(ppp_sockfd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 1943 error("ioctl(PPPIOCSFLAGS): %m"); 1944} 1945 1946/* ----------------------------------------------------------------------------- 1947returns 1 if decompression was disabled as a 1948 * result of an error detected after decompression of a packet, 1949 * 0 otherwise. This is necessary because of patent nonsense 1950 ----------------------------------------------------------------------------- */ 1951int ccp_fatal_error(int unit) 1952{ 1953 int x; 1954 1955 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 1956 error("ioctl(PPPIOCGFLAGS): %m"); 1957 return 0; 1958 } 1959 return x & SC_DC_FERROR; 1960} 1961 1962/* ----------------------------------------------------------------------------- 1963return how long the link has been idle 1964----------------------------------------------------------------------------- */ 1965int get_idle_time(int u, struct ppp_idle *ip) 1966{ 1967 return ioctl(ppp_sockfd, PPPIOCGIDLE, ip) >= 0; 1968} 1969 1970/* ----------------------------------------------------------------------------- 1971return statistics for the link 1972----------------------------------------------------------------------------- */ 1973int get_ppp_stats(int u, struct pppd_stats *stats) 1974{ 1975 struct ifpppstatsreq req; 1976 1977 memset (&req, 0, sizeof (req)); 1978 strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)); 1979 if (ioctl(ip_sockfd, SIOCGPPPSTATS, &req) < 0) { 1980 error("Couldn't get PPP statistics: %m"); 1981 return 0; 1982 } 1983 stats->bytes_in = req.stats.p.ppp_ibytes; 1984 stats->bytes_out = req.stats.p.ppp_obytes; 1985 stats->pkts_in = req.stats.p.ppp_ipackets; 1986 stats->pkts_out = req.stats.p.ppp_opackets; 1987 return 1; 1988} 1989 1990 1991#ifdef PPP_FILTER 1992/* ----------------------------------------------------------------------------- 1993transfer the pass and active filters to the kernel 1994----------------------------------------------------------------------------- */ 1995int set_filters(struct bpf_program *pass, struct bpf_program *active) 1996{ 1997 int ret = 1; 1998 1999 if (pass->bf_len > 0) { 2000 if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) { 2001 error("Couldn't set pass-filter in kernel: %m"); 2002 ret = 0; 2003 } 2004 } 2005 if (active->bf_len > 0) { 2006 if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) { 2007 error("Couldn't set active-filter in kernel: %m"); 2008 ret = 0; 2009 } 2010 } 2011 return ret; 2012} 2013#endif 2014 2015/* ----------------------------------------------------------------------------- 2016config tcp header compression 2017----------------------------------------------------------------------------- */ 2018int sifvjcomp(int u, int vjcomp, int cidcomp, int maxcid) 2019{ 2020 u_int x; 2021 2022 if (ioctl(ppp_sockfd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 2023 error("ioctl (PPPIOCGFLAGS): %m"); 2024 return 0; 2025 } 2026 x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP; 2027 x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID; 2028 if (ioctl(ppp_sockfd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { 2029 error("ioctl(PPPIOCSFLAGS): %m"); 2030 return 0; 2031 } 2032 if (vjcomp && ioctl(ppp_sockfd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) { 2033 error("ioctl(PPPIOCSMAXCID): %m"); 2034 return 0; 2035 } 2036 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPIPCPCompressionVJ, vjcomp); 2037 return 1; 2038} 2039 2040/* ----------------------------------------------------------------------------- 2041Config the interface up and enable IP packets to pass 2042----------------------------------------------------------------------------- */ 2043int sifup(int u) 2044{ 2045 struct ifreq ifr; 2046 2047 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2048 if (ioctl(ip_sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { 2049 error("ioctl (SIOCGIFFLAGS): %m"); 2050 return 0; 2051 } 2052 ifr.ifr_flags |= IFF_UP; 2053 if (ioctl(ip_sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { 2054 error("ioctl(SIOCSIFFLAGS): %m"); 2055 return 0; 2056 } 2057 if_is_up = 1; 2058 return 1; 2059} 2060 2061/* ----------------------------------------------------------------------------- 2062Set the mode for handling packets for a given NP 2063----------------------------------------------------------------------------- */ 2064int sifnpmode(int u, int proto, enum NPmode mode) 2065{ 2066 struct npioctl npi; 2067 2068 npi.protocol = proto; 2069 npi.mode = mode; 2070 if (ioctl(ppp_sockfd, PPPIOCSNPMODE, &npi) < 0) { 2071 error("ioctl(set NP %d mode to %d): %m", proto, mode); 2072 return 0; 2073 } 2074 return 1; 2075} 2076 2077/* ----------------------------------------------------------------------------- 2078Set the mode for filtering protocol addresses 2079----------------------------------------------------------------------------- */ 2080int sifnpafmode(int u, int proto, enum NPAFmode mode) 2081{ 2082 struct npafioctl npi; 2083 2084 npi.protocol = proto; 2085 npi.mode = mode; 2086 if (ioctl(ppp_sockfd, PPPIOCSNPAFMODE, &npi) < 0) { 2087 error("ioctl(set NPAF %d mode to %d): %m", proto, mode); 2088 return 0; 2089 } 2090 return 1; 2091} 2092 2093/* ----------------------------------------------------------------------------- 2094Config the interface down 2095----------------------------------------------------------------------------- */ 2096int sifdown(int u) 2097{ 2098 struct ifreq ifr; 2099 int rv; 2100 struct npioctl npi; 2101 2102 npi.protocol = PPP_IP; 2103 if ((ioctl(ppp_sockfd, PPPIOCGNPMODE, (caddr_t) &npi) == 0) 2104 && (npi.mode != NPMODE_DROP)) { 2105 return 0; 2106 } 2107 2108 npi.protocol = PPP_IPV6; 2109 if ((ioctl(ppp_sockfd, PPPIOCGNPMODE, (caddr_t) &npi) == 0) 2110 && (npi.mode != NPMODE_DROP)) { 2111 return 0; 2112 } 2113 2114 /* ipv4 and ipv4 are both down. take the interface down now */ 2115 2116 rv = 1; 2117 2118 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2119 if (ioctl(ip_sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { 2120 error("ioctl (SIOCGIFFLAGS): %m"); 2121 rv = 0; 2122 } else { 2123 ifr.ifr_flags &= ~IFF_UP; 2124 if (ioctl(ip_sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { 2125 error("ioctl(SIOCSIFFLAGS): %m"); 2126 rv = 0; 2127 } else 2128 if_is_up = 0; 2129 } 2130 return rv; 2131} 2132 2133 2134/* ----------------------------------------------------------------------------- 2135set the route for the interface. 2136----------------------------------------------------------------------------- */ 2137int sifroute(int u, u_int32_t o, u_int32_t h, u_int32_t m) 2138{ 2139 if (addifroute && m != 0xFFFFFFFF) { 2140 ifroute_address.s_addr = o & m; 2141 ifroute_mask.s_addr = m; 2142 ifroute_installed = route_interface(RTM_ADD, ifroute_address, ifroute_mask, IFT_PPP, ifname, 0); 2143 } 2144 2145 return 1; 2146} 2147 2148/* ----------------------------------------------------------------------------- 2149clear the route for the interface. 2150----------------------------------------------------------------------------- */ 2151int cifroute() 2152{ 2153 if (addifroute && ifroute_installed) { 2154 route_interface(RTM_DELETE, ifroute_address, ifroute_mask, IFT_PPP, ifname, 0); 2155 ifroute_installed = 0; 2156 } 2157 2158 return 1; 2159} 2160 2161/* ----------------------------------------------------------------------------- 2162set the sa_family field of a struct sockaddr, if it exists. 2163----------------------------------------------------------------------------- */ 2164#define SET_SA_FAMILY(addr, family) \ 2165 BZERO((char *) &(addr), sizeof(addr)); \ 2166 addr.sa_family = (family); \ 2167 addr.sa_len = sizeof(addr); 2168 2169/* ----------------------------------------------------------------------------- 2170Config the interface IP addresses and netmask 2171----------------------------------------------------------------------------- */ 2172int sifaddr(int u, u_int32_t o, u_int32_t h, u_int32_t m) 2173{ 2174 struct ifaliasreq ifra __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 2175 struct ifreq ifr; 2176 2177// XXX from sys/sockio.h 2178#define SIOCPROTOATTACH _IOWR('i', 80, struct ifreq) /* attach proto to interface */ 2179#define SIOCPROTODETACH _IOWR('i', 81, struct ifreq) /* detach proto from interface */ 2180 2181 // first plumb ip over ppp 2182 if (ipv4_plumbed == 0) { 2183 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2184 if (ioctl(ip_sockfd, SIOCPROTOATTACH, (caddr_t) &ifr) < 0) { 2185 error("Couldn't plumb IP to the interface: %d %m", errno); 2186 //return 0; 2187 } 2188 ipv4_plumbed = 1; 2189 } 2190 2191 strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); 2192 SET_SA_FAMILY(ifra.ifra_addr, AF_INET); 2193 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; 2194 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); 2195 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; 2196 if (m != 0) { 2197 SET_SA_FAMILY(ifra.ifra_mask, AF_INET); 2198 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m; 2199 } else 2200 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); 2201 BZERO(&ifr, sizeof(ifr)); 2202 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 2203 if (ioctl(ip_sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { 2204 if (errno != EADDRNOTAVAIL) 2205 warning("Couldn't remove interface address: %m"); 2206 } 2207 if (ioctl(ip_sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) { 2208 if (errno != EEXIST) { 2209 error("Couldn't set interface address: %m"); 2210 return 0; 2211 } 2212 warning("Couldn't set interface address: Address %I already exists", o); 2213 } 2214 ifaddrs[0] = o; 2215 ifaddrs[1] = h; 2216 2217 if (looplocal) { 2218 struct in_addr o1; 2219 struct in_addr mask; 2220 2221 set_flags(ppp_sockfd, get_flags(ppp_sockfd) | SC_LOOP_LOCAL); 2222 // add a route for our local address via our interface 2223 o1.s_addr = o; 2224 mask.s_addr = 0; 2225 route_interface(RTM_ADD, o1, mask, IFT_PPP, ifname, 1); 2226 } 2227 2228 sifroute(u, o, h, m); 2229 2230 publish_stateaddr(o, h, m); 2231 2232 return 1; 2233} 2234 2235/* ----------------------------------------------------------------------------- 2236 Update the interface IP addresses and netmask 2237 ----------------------------------------------------------------------------- */ 2238int uifaddr(int u, u_int32_t o, u_int32_t h, u_int32_t m) 2239{ 2240 struct ifaliasreq ifra __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 2241 struct ifreq ifr; 2242 2243 cifroute(); 2244 2245 // XXX from sys/sockio.h 2246#define SIOCPROTOATTACH _IOWR('i', 80, struct ifreq) /* attach proto to interface */ 2247#define SIOCPROTODETACH _IOWR('i', 81, struct ifreq) /* detach proto from interface */ 2248 2249 // first plumb ip over ppp 2250 if (ipv4_plumbed == 0) { 2251 error("Interface should have been plumbed already"); 2252 return -1; 2253 } 2254 2255 strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); 2256 SET_SA_FAMILY(ifra.ifra_addr, AF_INET); 2257 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; 2258 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); 2259 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; 2260 if (m != 0) { 2261 SET_SA_FAMILY(ifra.ifra_mask, AF_INET); 2262 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m; 2263 } else 2264 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); 2265 BZERO(&ifr, sizeof(ifr)); 2266 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 2267 if (ioctl(ip_sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { 2268 if (errno != EADDRNOTAVAIL) 2269 warning("Couldn't remove interface address: %m"); 2270 } 2271 if (ioctl(ip_sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) { 2272 if (errno != EEXIST) { 2273 error("Couldn't set interface address: %m"); 2274 return 0; 2275 } 2276 warning("Couldn't set interface address: Address %I already exists", o); 2277 } 2278 ifaddrs[0] = o; 2279 ifaddrs[1] = h; 2280 2281 sifroute(u, o, h, m); 2282 2283 update_stateaddr(o, h, m); 2284 2285 return 1; 2286} 2287 2288/* ----------------------------------------------------------------------------- 2289Clear the interface IP addresses, and delete routes 2290 * through the interface if possible 2291 ----------------------------------------------------------------------------- */ 2292int cifaddr(int u, u_int32_t o, u_int32_t h) 2293{ 2294 //struct ifreq ifr; 2295 struct ifaliasreq ifra __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 2296 2297// XXX from sys/sockio.h 2298#define SIOCPROTOATTACH _IOWR('i', 80, struct ifreq) /* attach proto to interface */ 2299#define SIOCPROTODETACH _IOWR('i', 81, struct ifreq) /* detach proto from interface */ 2300 2301 cifroute(); 2302 2303 ifaddrs[0] = 0; 2304 strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); 2305 SET_SA_FAMILY(ifra.ifra_addr, AF_INET); 2306 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; 2307 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); 2308 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; 2309 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); 2310 if (ioctl(ip_sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) { 2311 if (errno != EADDRNOTAVAIL) 2312 warning("Couldn't delete interface address: %m"); 2313 return 0; 2314 } 2315 2316#if 0 2317 // unplumb ip from ppp 2318 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2319 if (ioctl(ip_sockfd, SIOCPROTODETACH, (caddr_t) &ifr) < 0) { 2320 error("Couldn't unplumb IP from the interface: %m"); 2321 return 0; 2322 } 2323#endif 2324 2325 unpublish_dict(kSCEntNetIPv4); 2326 2327 return 1; 2328} 2329 2330#ifdef INET6 2331/* ----------------------------------------------------------------------------- 2332Config the interface IPv6 addresses 2333----------------------------------------------------------------------------- */ 2334int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64) 2335{ 2336 int ifindex, s; 2337 struct in6_ifreq ifr6; 2338 struct in6_aliasreq addreq6 __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 2339 2340// XXX from sys/sockio.h 2341#define SIOCPROTOATTACH_IN6 _IOWR('i', 110, struct in6_aliasreq) /* attach proto to interface */ 2342#define SIOCPROTODETACH_IN6 _IOWR('i', 111, struct in6_ifreq) /* detach proto from interface */ 2343#define SIOCPROTOATTACH _IOWR('i', 80, struct ifreq) /* attach proto to interface */ 2344#define SIOCPROTODETACH _IOWR('i', 81, struct ifreq) /* detach proto from interface */ 2345#define SIOCLL_START _IOWR('i', 130, struct in6_aliasreq) /* start aquiring linklocal on interface */ 2346#define SIOCLL_STOP _IOWR('i', 131, struct in6_ifreq) /* deconfigure linklocal from interface */ 2347 2348 s = socket(AF_INET6, SOCK_DGRAM, 0); 2349 if (s < 0) { 2350 error("Can't create IPv6 socket: %m"); 2351 return 0; 2352 } 2353 2354 /* actually, this part is not kame local - RFC2553 conformant */ 2355 ifindex = if_nametoindex(ifname); 2356 if (ifindex == 0) { 2357 error("sifaddr6: no interface %s", ifname); 2358 close(s); 2359 return 0; 2360 } 2361 2362 strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); 2363 if (ioctl(s, SIOCPROTOATTACH_IN6, &ifr6) < 0) { 2364 error("sif6addr: can't attach IPv6 protocol: %m"); 2365 close(s); 2366 return 0; 2367 } 2368 2369 memset(&addreq6, 0, sizeof(addreq6)); 2370 strlcpy(addreq6.ifra_name, ifname, sizeof(addreq6.ifra_name)); 2371 2372 /* my addr */ 2373 addreq6.ifra_addr.sin6_family = AF_INET6; 2374 addreq6.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); 2375 addreq6.ifra_addr.sin6_addr.s6_addr[0] = 0xfe; 2376 addreq6.ifra_addr.sin6_addr.s6_addr[1] = 0x80; 2377 memcpy(&addreq6.ifra_addr.sin6_addr.s6_addr[8], &our_eui64, 2378 sizeof(our_eui64)); 2379 /* KAME ifindex hack */ 2380 *ALIGNED_CAST(u_int16_t *)&addreq6.ifra_addr.sin6_addr.s6_addr[2] = htons(ifindex); 2381 2382 /* his addr */ 2383 addreq6.ifra_dstaddr.sin6_family = AF_INET6; 2384 addreq6.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6); 2385 addreq6.ifra_dstaddr.sin6_addr.s6_addr[0] = 0xfe; 2386 addreq6.ifra_dstaddr.sin6_addr.s6_addr[1] = 0x80; 2387 memcpy(&addreq6.ifra_dstaddr.sin6_addr.s6_addr[8], &his_eui64, 2388 sizeof(our_eui64)); 2389 /* KAME ifindex hack */ 2390 *ALIGNED_CAST(u_int16_t *)&addreq6.ifra_dstaddr.sin6_addr.s6_addr[2] = htons(ifindex); 2391 2392 /* prefix mask: 128bit */ 2393 addreq6.ifra_prefixmask.sin6_family = AF_INET6; 2394 addreq6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 2395 memset(&addreq6.ifra_prefixmask.sin6_addr, 0xff, 2396 sizeof(addreq6.ifra_prefixmask.sin6_addr)); 2397 2398 /* address lifetime (infty) */ 2399 addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 2400 addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 2401 2402 if (ioctl(s, SIOCLL_START, &addreq6) < 0) { 2403 error("sif6addr: can't set LL address: %m"); 2404 close(s); 2405 return 0; 2406 } 2407 2408 close(s); 2409 2410 return 1; 2411} 2412 2413/* ----------------------------------------------------------------------------- 2414Clear the interface IPv6 addresses 2415 ----------------------------------------------------------------------------- */ 2416int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64) 2417{ 2418 int s; 2419 struct ifreq ifr; 2420 struct in6_ifreq ifr6; 2421 2422// XXX from sys/sockio.h 2423#define SIOCPROTOATTACH_IN6 _IOWR('i', 110, struct in6_aliasreq) /* attach proto to interface */ 2424#define SIOCPROTODETACH_IN6 _IOWR('i', 111, struct in6_ifreq) /* detach proto from interface */ 2425#define SIOCPROTOATTACH _IOWR('i', 80, struct ifreq) /* attach proto to interface */ 2426#define SIOCPROTODETACH _IOWR('i', 81, struct ifreq) /* detach proto from interface */ 2427#define SIOCLL_START _IOWR('i', 130, struct in6_aliasreq) /* start aquiring linklocal on interface */ 2428#define SIOCLL_STOP _IOWR('i', 131, struct in6_ifreq) /* deconfigure linklocal from interface */ 2429 2430 s = socket(AF_INET6, SOCK_DGRAM, 0); 2431 if (s < 0) { 2432 error("Can't create IPv6 socket: %m"); 2433 return 0; 2434 } 2435 2436 /* first try old ioctl */ 2437 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 2438 if (ioctl(s, SIOCPROTODETACH, &ifr) < 0) { 2439 /* then new ioctl */ 2440 strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); 2441 if (ioctl(s, SIOCLL_STOP, &ifr6) < 0) { 2442 warning("Can't stop LL address: %m"); 2443 } 2444 strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); 2445 if (ioctl(s, SIOCPROTODETACH_IN6, &ifr6) < 0) { 2446 warning("Can't detach IPv6 protocol: %m"); 2447 } 2448 2449 close(s); 2450 return 0; 2451 } 2452 2453 close(s); 2454 2455 return 1; 2456} 2457 2458/* ----------------------------------------------------------------------------- 2459Returns an iterator containing the primary (built-in) Ethernet interface. 2460The caller is responsible for releasing the iterator after the caller is done with it. 2461 ----------------------------------------------------------------------------- */ 2462static kern_return_t FindPrimaryEthernetInterfaces(io_iterator_t *matchingServices) 2463{ 2464 kern_return_t kernResult; 2465 CFMutableDictionaryRef matchingDict; 2466 CFMutableDictionaryRef propertyMatchDict; 2467 2468 // Ethernet interfaces are instances of class kIOEthernetInterfaceClass. 2469 // IOServiceMatching is a convenience function to create a dictionary with the key kIOProviderClassKey and 2470 // the specified value. 2471 matchingDict = IOServiceMatching(kIOEthernetInterfaceClass); 2472 if (matchingDict) { 2473 2474 // Each IONetworkInterface object has a Boolean property with the key kIOPrimaryInterface. Only the 2475 // primary (built-in) interface has this property set to TRUE. 2476 2477 // IOServiceGetMatchingServices uses the default matching criteria defined by IOService. This considers 2478 // only the following properties plus any family-specific matching in this order of precedence 2479 // (see IOService::passiveMatch): 2480 // 2481 // kIOProviderClassKey (IOServiceMatching) 2482 // kIONameMatchKey (IOServiceNameMatching) 2483 // kIOPropertyMatchKey 2484 // kIOPathMatchKey 2485 // kIOMatchedServiceCountKey 2486 // family-specific matching 2487 // kIOBSDNameKey (IOBSDNameMatching) 2488 // kIOLocationMatchKey 2489 2490 // The IONetworkingFamily does not define any family-specific matching. This means that in 2491 // order to have IOServiceGetMatchingServices consider the kIOPrimaryInterface property, we must 2492 // add that property to a separate dictionary and then add that to our matching dictionary 2493 // specifying kIOPropertyMatchKey. 2494 2495 propertyMatchDict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, 2496 &kCFTypeDictionaryKeyCallBacks, 2497 &kCFTypeDictionaryValueCallBacks); 2498 if (propertyMatchDict) { 2499 2500 // Set the value in the dictionary of the property with the given key, or add the key 2501 // to the dictionary if it doesn't exist. This call retains the value object passed in. 2502 CFDictionarySetValue(propertyMatchDict, CFSTR(kIOPrimaryInterface), kCFBooleanTrue); 2503 2504 // Now add the dictionary containing the matching value for kIOPrimaryInterface to our main 2505 // matching dictionary. This call will retain propertyMatchDict, so we can release our reference 2506 // on propertyMatchDict after adding it to matchingDict. 2507 CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); 2508 CFRelease(propertyMatchDict); 2509 } 2510 } 2511 2512 // IOServiceGetMatchingServices retains the returned iterator, so release the iterator when we're done with it. 2513 // IOServiceGetMatchingServices also consumes a reference on the matching dictionary so we don't need to release 2514 // the dictionary explicitly. 2515 kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, matchingServices); 2516 2517 return kernResult; 2518} 2519 2520/* ----------------------------------------------------------------------------- 2521Get the mac address of the primary interface 2522----------------------------------------------------------------------------- */ 2523static kern_return_t GetPrimaryMACAddress(UInt8 *MACAddress) 2524{ 2525 io_object_t intfService; 2526 io_object_t controllerService; 2527 kern_return_t kernResult = KERN_FAILURE; 2528 io_iterator_t intfIterator; 2529 2530 kernResult = FindPrimaryEthernetInterfaces(&intfIterator); 2531 if (kernResult != KERN_SUCCESS) 2532 return kernResult; 2533 2534 // Initialize the returned address 2535 bzero(MACAddress, kIOEthernetAddressSize); 2536 2537 // IOIteratorNext retains the returned object, so release it when we're done with it. 2538 while ((intfService = IOIteratorNext(intfIterator))) { 2539 2540 CFTypeRef MACAddressAsCFData; 2541 2542 // IONetworkControllers can't be found directly by the IOServiceGetMatchingServices call, 2543 // since they are hardware nubs and do not participate in driver matching. In other words, 2544 // registerService() is never called on them. So we've found the IONetworkInterface and will 2545 // get its parent controller by asking for it specifically. 2546 2547 // IORegistryEntryGetParentEntry retains the returned object, so release it when we're done with it. 2548 kernResult = IORegistryEntryGetParentEntry( intfService, 2549 kIOServicePlane, 2550 &controllerService ); 2551 2552 if (kernResult == KERN_SUCCESS) { 2553 2554 // Retrieve the MAC address property from the I/O Registry in the form of a CFData 2555 MACAddressAsCFData = IORegistryEntryCreateCFProperty( controllerService, 2556 CFSTR(kIOMACAddress), 2557 kCFAllocatorDefault, 0); 2558 if (MACAddressAsCFData) { 2559 // Get the raw bytes of the MAC address from the CFData 2560 CFDataGetBytes(MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress); 2561 CFRelease(MACAddressAsCFData); 2562 } 2563 2564 // Done with the parent Ethernet controller object so we release it. 2565 IOObjectRelease(controllerService); 2566 } 2567 2568 // Done with the Ethernet interface object so we release it. 2569 IOObjectRelease(intfService); 2570 } 2571 2572 IOObjectRelease(intfIterator); 2573 2574 return kernResult; 2575} 2576 2577/* ----------------------------------------------------------------------------- 2578Convert 48-bit Ethernet address into 64-bit EUI 2579 ----------------------------------------------------------------------------- */ 2580int 2581ether_to_eui64(eui64_t *p_eui64) 2582{ 2583 static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 2584 static u_int8_t allone[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 2585 kern_return_t err; 2586 UInt8 addr[kIOEthernetAddressSize]; 2587 2588 err = GetPrimaryMACAddress(addr); 2589 if (err != KERN_SUCCESS) { 2590 warning("Can't get hardware interface address for en0 (error = %d)\n", err); 2591 return 0; 2592 } 2593 2594 /* check for invalid MAC address */ 2595 if (bcmp(addr, allzero, ETHER_ADDR_LEN) == 0) 2596 return 0; 2597 if (bcmp(addr, allone, ETHER_ADDR_LEN) == 0) 2598 return 0; 2599 2600 /* And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1] */ 2601 p_eui64->e8[0] = addr[0] | 0x02; 2602 p_eui64->e8[1] = addr[1]; 2603 p_eui64->e8[2] = addr[2]; 2604 p_eui64->e8[3] = 0xFF; 2605 p_eui64->e8[4] = 0xFE; 2606 p_eui64->e8[5] = addr[3]; 2607 p_eui64->e8[6] = addr[4]; 2608 p_eui64->e8[7] = addr[5]; 2609 2610 return 1; 2611} 2612 2613#endif 2614 2615/* ---------------------------------------------------------------------------- 2616 Create a "NULL Service" primary IPv6 dictionary for the dynamic store. This 2617 prevents any other service from becoming primary on IPv6. 2618 ----------------------------------------------------------------------------- */ 2619#ifndef kIsNULL 2620#define kIsNULL CFSTR("IsNULL") /* CFBoolean */ 2621#endif 2622void ppp_create_ipv6_dummy_primary(Boolean uninstall) 2623{ 2624 CFMutableArrayRef array; 2625 CFMutableDictionaryRef ipv6_dict; 2626 int isprimary = 1; 2627 CFStringRef key; 2628 CFNumberRef num; 2629 CFStringRef str; 2630 2631 if (noipv6override || cfgCache == NULL || serviceidRef == NULL) 2632 return; 2633 2634 if ((key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceidRef, kSCEntNetIPv6))) { 2635 if (uninstall) { 2636 unpublish_dict(key); 2637 } else { 2638 /* create the IPv6 dictionnary */ 2639 if ((ipv6_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks))) { 2640 if ((array = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks))) { 2641 CFArrayAppendValue(array, CFSTR("::1")); 2642 CFDictionarySetValue(ipv6_dict, kSCPropNetIPv6Addresses, array); 2643 CFRelease(array); 2644 } 2645 2646 CFDictionarySetValue(ipv6_dict, kSCPropNetIPv6Router, CFSTR("::1")); 2647 2648 num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &isprimary); 2649 if (num) { 2650 CFDictionarySetValue(ipv6_dict, kSCPropNetOverridePrimary, num); 2651 CFRelease(num); 2652 } 2653 2654 CFDictionarySetValue(ipv6_dict, kIsNULL, kCFBooleanTrue); 2655 2656 if (ifname) { 2657 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), ifname))) { 2658 CFDictionarySetValue(ipv6_dict, kSCPropInterfaceName, str); 2659 CFRelease(str); 2660 } 2661 } 2662 2663 update_publish_dict(key, ipv6_dict); 2664 CFRelease(ipv6_dict); 2665 } 2666 } 2667 2668 CFRelease(key); 2669 } 2670 2671 return; 2672} 2673 2674/* ----------------------------------------------------------------------------- 2675assign a default route through the address given 2676----------------------------------------------------------------------------- */ 2677int sifdefaultroute(int u, u_int32_t l, u_int32_t g) 2678{ 2679 override_primary = 1; 2680 ppp_create_ipv6_dummy_primary(FALSE); 2681 return publish_dictnumentry(kSCEntNetIPv4, kSCPropNetOverridePrimary, 1); 2682} 2683 2684/* ----------------------------------------------------------------------------- 2685delete a default route through the address given 2686----------------------------------------------------------------------------- */ 2687int cifdefaultroute(int u, u_int32_t l, u_int32_t g) 2688{ 2689 override_primary = 0; 2690 ppp_create_ipv6_dummy_primary(TRUE); 2691 return unpublish_dictentry(kSCEntNetIPv4, kSCPropNetOverridePrimary); 2692} 2693 2694/* ---------------------------------------------------------------------------- 2695 update ip addresses using configd cache mechanism 2696 use new state information model 2697 ----------------------------------------------------------------------------- */ 2698static int update_stateaddr(u_int32_t o, u_int32_t h, u_int32_t m) 2699{ 2700 struct in_addr addr; 2701 CFMutableArrayRef array; 2702 CFMutableDictionaryRef ipv4_dict; 2703 CFStringRef str; 2704 CFStringRef key; 2705 2706 // ppp daemons without services are not published in the cache 2707 if (cfgCache == NULL) 2708 return 0; 2709 2710 /* update the store now */ 2711 if ((key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceidRef, kSCEntNetIPv4))) { 2712 CFPropertyListRef ref; 2713 if (publish_dict != NULL) { 2714 ref = CFDictionaryGetValue(publish_dict, key); 2715 if (ref) { 2716 CFRetain(ref); 2717 } 2718 } else { 2719 ref = SCDynamicStoreCopyValue(cfgCache, key); 2720 } 2721 2722 if (ref == NULL || 2723 CFGetTypeID(ref) != CFDictionaryGetTypeID()) { 2724 warning("SCDynamicStoreCopyValue IP %s failed: %s\n", ifname, SCErrorString(SCError())); 2725 if (ref) { 2726 CFRelease(ref); 2727 } 2728 CFRelease(key); 2729 return 0; 2730 } 2731 ipv4_dict = CFDictionaryCreateMutableCopy(NULL, 0, ref); 2732 CFRelease(ref); 2733 if (!ipv4_dict || CFGetTypeID(ipv4_dict) != CFDictionaryGetTypeID()) { 2734 warning("CFDictionaryCreateMutableCopy IP %s failed: %s\n", ifname, SCErrorString(SCError())); 2735 if (ipv4_dict) { 2736 CFRelease(ipv4_dict); 2737 } 2738 CFRelease(key); 2739 return 0; 2740 } 2741 } else { 2742 return 0; 2743 } 2744 2745 /* set the ip address src and dest arrays */ 2746 if ((array = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks))) { 2747 addr.s_addr = o; 2748 if ((str = CFStringCreateWithFormat(0, 0, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 2749 CFArrayAppendValue(array, str); 2750 CFRelease(str); 2751 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4Addresses, array); 2752 } 2753 CFRelease(array); 2754 } 2755 2756 if ((array = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks))) { 2757 addr.s_addr = h; 2758 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 2759 CFArrayAppendValue(array, str); 2760 CFRelease(str); 2761 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4DestAddresses, array); 2762 } 2763 CFRelease(array); 2764 } 2765 2766 /* set the router */ 2767 addr.s_addr = o; 2768 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 2769 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4Router, str); 2770 CFRelease(str); 2771 } 2772 2773 /* add the interface name */ 2774 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), ifname))) { 2775 CFDictionarySetValue(ipv4_dict, kSCPropInterfaceName, str); 2776 CFRelease(str); 2777 } 2778 2779 /* add the network signature */ 2780 if (network_signature) { 2781 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), network_signature))) { 2782 CFDictionarySetValue(ipv4_dict, CFSTR("NetworkSignature"), str); 2783 CFRelease(str); 2784 } 2785 } 2786 2787 /* add the remote server peer address */ 2788 if (server_peer) { 2789 CFDictionarySetValue(ipv4_dict, CFSTR("ServerAddress"), server_peer); 2790 } 2791 2792 2793 if (update_publish_dict(key, ipv4_dict) == 0) 2794 warning("SCDynamicStoreSetValue IP %s failed: %s\n", ifname, SCErrorString(SCError())); 2795 2796 CFRelease(ipv4_dict); 2797 CFRelease(key); 2798 return 1; 2799} 2800 2801/* ---------------------------------------------------------------------------- 2802publish ip addresses using configd cache mechanism 2803use new state information model 2804----------------------------------------------------------------------------- */ 2805int publish_stateaddr(u_int32_t o, u_int32_t h, u_int32_t m) 2806{ 2807 struct in_addr addr; 2808 CFMutableArrayRef array; 2809 CFMutableDictionaryRef ipv4_dict; 2810 CFStringRef str; 2811 2812 // ppp daemons without services are not published in the cache 2813 if (cfgCache == NULL) 2814 return 0; 2815 2816 /* create the IPV4 dictionnary */ 2817 if ((ipv4_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) 2818 return 0; 2819 2820 /* set the ip address src and dest arrays */ 2821 if ((array = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks))) { 2822 addr.s_addr = o; 2823 if ((str = CFStringCreateWithFormat(0, 0, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 2824 CFArrayAppendValue(array, str); 2825 CFRelease(str); 2826 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4Addresses, array); 2827 } 2828 CFRelease(array); 2829 } 2830 2831 if ((array = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks))) { 2832 addr.s_addr = h; 2833 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 2834 CFArrayAppendValue(array, str); 2835 CFRelease(str); 2836 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4DestAddresses, array); 2837 } 2838 CFRelease(array); 2839 } 2840 2841 /* set the router */ 2842 addr.s_addr = o; 2843 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 2844 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4Router, str); 2845 CFRelease(str); 2846 } 2847 2848 /* add the interface name */ 2849 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), ifname))) { 2850 CFDictionarySetValue(ipv4_dict, kSCPropInterfaceName, str); 2851 CFRelease(str); 2852 } 2853 2854 /* add the network signature */ 2855 if (network_signature) { 2856 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), network_signature))) { 2857 CFDictionarySetValue(ipv4_dict, CFSTR("NetworkSignature"), str); 2858 CFRelease(str); 2859 } 2860 } 2861 2862 /* add the remote server peer address */ 2863 if (server_peer) { 2864 CFDictionarySetValue(ipv4_dict, CFSTR("ServerAddress"), server_peer); 2865 } 2866 2867 /* update the store now */ 2868 if ((str = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceidRef, kSCEntNetIPv4))) { 2869 2870 if (update_publish_dict(str, ipv4_dict) == 0) 2871 warning("SCDynamicStoreSetValue IP %s failed: %s\n", ifname, SCErrorString(SCError())); 2872 2873 CFRelease(str); 2874 } 2875 2876 CFRelease(ipv4_dict); 2877 return 1; 2878} 2879 2880/* ----------------------------------------------------------------------------- 2881 add a search domain, using configd cache mechanism. 2882----------------------------------------------------------------------------- */ 2883int publish_dns_wins_entry(CFStringRef entity, CFStringRef property1, CFTypeRef ref1, CFTypeRef ref1a, 2884 CFStringRef property2, CFTypeRef ref2, 2885 CFStringRef property3, CFTypeRef ref3, int clean) 2886{ 2887 CFMutableArrayRef mutable_array; 2888 CFArrayRef array = NULL; 2889 CFMutableDictionaryRef dict = NULL; 2890 CFStringRef key = NULL; 2891 CFPropertyListRef ref; 2892 int ret = 0; 2893 2894 if (publish_dict == NULL && cfgCache == NULL) 2895 return 0; 2896 2897 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceidRef, entity); 2898 if (!key) 2899 goto end; 2900 2901 if (publish_dict) { 2902 if ((ref = CFDictionaryGetValue(publish_dict, key))) { 2903 dict = CFDictionaryCreateMutableCopy(0, 0, ref); 2904 } 2905 else 2906 dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2907 } 2908 else if ((ref = SCDynamicStoreCopyValue(cfgCache, key))) { 2909 dict = CFDictionaryCreateMutableCopy(0, 0, ref); 2910 CFRelease(ref); 2911 } else 2912 dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2913 2914 if (!dict || (CFGetTypeID(dict) != CFDictionaryGetTypeID())) 2915 goto end; 2916 2917 if (!clean) 2918 array = CFDictionaryGetValue(dict, property1); 2919 if (array && (CFGetTypeID(array) == CFArrayGetTypeID())) 2920 mutable_array = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(array) + 1, array); 2921 else 2922 mutable_array = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); 2923 2924 if (!mutable_array) 2925 goto end; 2926 2927 CFArrayAppendValue(mutable_array, ref1); 2928 if (ref1a) 2929 CFArrayAppendValue(mutable_array, ref1a); 2930 CFDictionarySetValue(dict, property1, mutable_array); 2931 CFRelease(mutable_array); 2932 2933 if (property2) { 2934 if (!clean) 2935 array = CFDictionaryGetValue(dict, property2); 2936 if (array && (CFGetTypeID(array) == CFArrayGetTypeID())) 2937 mutable_array = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(array) + 1, array); 2938 else 2939 mutable_array = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); 2940 2941 if (!mutable_array) 2942 goto end; 2943 2944 CFArrayAppendValue(mutable_array, ref2); 2945 CFDictionarySetValue(dict, property2, mutable_array); 2946 CFRelease(mutable_array); 2947 } 2948 2949 if (property3) { 2950 if (!clean) 2951 array = CFDictionaryGetValue(dict, property3); 2952 if (array && (CFGetTypeID(array) == CFArrayGetTypeID())) 2953 mutable_array = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(array) + 1, array); 2954 else 2955 mutable_array = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); 2956 2957 if (!mutable_array) 2958 goto end; 2959 2960 CFArrayAppendValue(mutable_array, ref3); 2961 CFDictionarySetValue(dict, property3, mutable_array); 2962 CFRelease(mutable_array); 2963 } 2964 2965 if (update_publish_dict(key,dict)) 2966 ret = 1; 2967 else 2968 warning("SCDynamicStoreSetValue DNS/WINS %s failed: %s\n", ifname, SCErrorString(SCError())); 2969 2970end: 2971 if (key) 2972 CFRelease(key); 2973 if (dict) 2974 CFRelease(dict); 2975 return ret; 2976} 2977 2978 2979/* ----------------------------------------------------------------------------- 2980set dns information 2981----------------------------------------------------------------------------- */ 2982int sifdns(u_int32_t dns1, u_int32_t dns2) 2983{ 2984 CFStringRef str1 = 0, str2 = 0, strname = 0; 2985 int result = 0, clean = 1; 2986 long order = 100000; 2987 CFNumberRef num = 0; 2988 2989 num = CFNumberCreate(NULL, kCFNumberLongType, &order); 2990 if (!num) 2991 goto done; 2992 2993 strname = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8); 2994 if (!strname) 2995 goto done; 2996 2997 /* warn lookupd of upcoming change */ 2998 notify_post("com.apple.system.dns.delay"); 2999 3000 if (dns1) 3001 str1 = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&dns1)); 3002 if (!str1) 3003 goto done; 3004 3005 if (dns2 && (dns2!=dns1)) 3006 str2 = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&dns2)); 3007 3008 result = publish_dns_wins_entry(kSCEntNetDNS, kSCPropNetDNSServerAddresses, str1, str2, kSCPropNetDNSSupplementalMatchDomains, strname, kSCPropNetDNSSupplementalMatchOrders, num, clean); 3009#ifndef kSCPropNetProxiesSupplementalMatchDomains 3010#define kSCPropNetProxiesSupplementalMatchDomains kSCPropNetDNSSupplementalMatchDomains 3011#define kSCPropNetProxiesSupplementalMatchOrders kSCPropNetDNSSupplementalMatchOrders 3012#endif 3013 if (result) publish_dns_wins_entry(kSCEntNetProxies, kSCPropNetProxiesSupplementalMatchDomains, strname, 0, kSCPropNetProxiesSupplementalMatchOrders, num, 0, 0, clean); 3014 3015done: 3016 if (num) 3017 CFRelease(num); 3018 if (str1) 3019 CFRelease(str1); 3020 if (str2) 3021 CFRelease(str2); 3022 if (strname) 3023 CFRelease(strname); 3024 3025 return result; 3026} 3027 3028/* ----------------------------------------------------------------------------- 3029set wins information 3030----------------------------------------------------------------------------- */ 3031int sifwins(u_int32_t wins1, u_int32_t wins2) 3032{ 3033#if !TARGET_OS_EMBEDDED 3034 CFStringRef str1 = 0, str2 = 0; 3035 int result = 0, clean = 1; 3036 3037 if (wins1) 3038 str1 = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&wins1)); 3039 if (!str1) 3040 goto done; 3041 3042 if (wins2) 3043 str2 = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&wins2)); 3044 3045 result = publish_dns_wins_entry(kSCEntNetSMB, kSCPropNetSMBWINSAddresses, str1, str2, 0, 0, 0, 0, clean); 3046 3047done: 3048 if (str1) 3049 CFRelease(str1); 3050 if (str2) 3051 CFRelease(str2); 3052 3053 return result; 3054#else 3055 return 0; 3056#endif 3057} 3058 3059static struct { 3060 struct rt_msghdr hdr; 3061 struct sockaddr_inarp dst; 3062 struct sockaddr_dl hwa; 3063 char extra[128]; 3064} arpmsg; 3065 3066static int arpmsg_valid; 3067 3068/* ----------------------------------------------------------------------------- 3069Make a proxy ARP entry for the peer 3070----------------------------------------------------------------------------- */ 3071int sifproxyarp(int unit, u_int32_t hisaddr) 3072{ 3073 int routes; 3074 3075 /* 3076 * Get the hardware address of an interface on the same subnet 3077 * as our local address. 3078 */ 3079 memset(&arpmsg, 0, sizeof(arpmsg)); 3080 if (!get_ether_addr(hisaddr, &arpmsg.hwa)) { 3081 error("Cannot determine ethernet address for proxy ARP"); 3082 return 0; 3083 } 3084 3085 if ((routes = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) { 3086 error("Couldn't add proxy arp entry: socket: %m"); 3087 return 0; 3088 } 3089 3090 arpmsg.hdr.rtm_type = RTM_ADD; 3091 arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC; 3092 arpmsg.hdr.rtm_version = RTM_VERSION; 3093 arpmsg.hdr.rtm_seq = ++rtm_seq; 3094 arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; 3095 arpmsg.hdr.rtm_inits = RTV_EXPIRE; 3096 arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp); 3097 arpmsg.dst.sin_family = AF_INET; 3098 arpmsg.dst.sin_addr.s_addr = hisaddr; 3099 arpmsg.dst.sin_other = SIN_PROXY; 3100 3101 arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg 3102 + arpmsg.hwa.sdl_len; 3103 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 3104 error("Couldn't add proxy arp entry: %m"); 3105 close(routes); 3106 return 0; 3107 } 3108 3109 close(routes); 3110 arpmsg_valid = 1; 3111 proxy_arp_addr = hisaddr; 3112 return 1; 3113} 3114 3115/* ----------------------------------------------------------------------------- 3116Delete the proxy ARP entry for the peer 3117----------------------------------------------------------------------------- */ 3118int cifproxyarp(int unit, u_int32_t hisaddr) 3119{ 3120 int routes; 3121 3122 if (!arpmsg_valid) 3123 return 0; 3124 arpmsg_valid = 0; 3125 3126 arpmsg.hdr.rtm_type = RTM_DELETE; 3127 arpmsg.hdr.rtm_seq = ++rtm_seq; 3128 3129 if ((routes = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) { 3130 error("Couldn't delete proxy arp entry: socket: %m"); 3131 return 0; 3132 } 3133 3134 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 3135 error("Couldn't delete proxy arp entry: %m"); 3136 close(routes); 3137 return 0; 3138 } 3139 3140 close(routes); 3141 proxy_arp_addr = 0; 3142 return 1; 3143} 3144 3145#define MAX_IFS 32 3146 3147/* ----------------------------------------------------------------------------- 3148get the hardware address of an interface on the 3149 * the same subnet as ipaddr. 3150----------------------------------------------------------------------------- */ 3151static int get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr) 3152{ 3153 struct ifreq *ifr, *ifend, *ifp; 3154 u_int32_t ina, mask; 3155 struct sockaddr_dl *dla; 3156 struct ifreq ifreq; 3157 struct ifconf ifc; 3158 struct ifreq ifs[MAX_IFS]; 3159 3160 ifc.ifc_len = sizeof(ifs); 3161 ifc.ifc_req = ifs; 3162 if (ioctl(ip_sockfd, SIOCGIFCONF, &ifc) < 0) { 3163 error("ioctl(SIOCGIFCONF): %m"); 3164 return 0; 3165 } 3166 3167 /* 3168 * Scan through looking for an interface with an Internet 3169 * address on the same subnet as `ipaddr'. 3170 */ 3171 ifend = ALIGNED_CAST(struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 3172 for (ifr = ifc.ifc_req; ifr < ifend; ifr = ALIGNED_CAST(struct ifreq *) 3173 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { 3174 if (ifr->ifr_addr.sa_family == AF_INET) { 3175 ina = (ALIGNED_CAST(struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; 3176 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 3177 /* 3178 * Check that the interface is up, and not point-to-point 3179 * or loopback. 3180 */ 3181 if (ioctl(ip_sockfd, SIOCGIFFLAGS, &ifreq) < 0) 3182 continue; 3183 if ((ifreq.ifr_flags & 3184 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) 3185 != (IFF_UP|IFF_BROADCAST)) 3186 continue; 3187 /* 3188 * Get its netmask and check that it's on the right subnet. 3189 */ 3190 if (ioctl(ip_sockfd, SIOCGIFNETMASK, &ifreq) < 0) 3191 continue; 3192 mask = (ALIGNED_CAST(struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; 3193 if ((ipaddr & mask) != (ina & mask)) 3194 continue; 3195 3196 break; 3197 } 3198 } 3199 3200 if (ifr >= ifend) 3201 return 0; 3202 info("found interface %s for proxy arp", ifr->ifr_name); 3203 3204 /* 3205 * Now scan through again looking for a link-level address 3206 * for this interface. 3207 */ 3208 ifp = ifr; 3209 for (ifr = ifc.ifc_req; ifr < ifend; ) { 3210 if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 3211 && ifr->ifr_addr.sa_family == AF_LINK) { 3212 /* 3213 * Found the link-level address - copy it out 3214 */ 3215 dla = ALIGNED_CAST(struct sockaddr_dl *) &ifr->ifr_addr; 3216 BCOPY(dla, hwaddr, dla->sdl_len); 3217 return 1; 3218 } 3219 ifr = ALIGNED_CAST(struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); 3220 } 3221 3222 return 0; 3223} 3224 3225/* ----------------------------------------------------------------------------- 3226 * Return user specified netmask, modified by any mask we might determine 3227 * for address `addr' (in network byte order). 3228 * Here we scan through the system's list of interfaces, looking for 3229 * any non-point-to-point interfaces which might appear to be on the same 3230 * network as `addr'. If we find any, we OR in their netmask to the 3231 * user-specified netmask. 3232----------------------------------------------------------------------------- */ 3233u_int32_t GetMask(u_int32_t addr) 3234{ 3235 u_int32_t mask, nmask, ina; 3236 struct ifreq *ifr, *ifend, ifreq; 3237 struct ifconf ifc; 3238 struct ifreq ifs[MAX_IFS]; 3239 3240 addr = ntohl(addr); 3241 if (IN_CLASSA(addr)) /* determine network mask for address class */ 3242 nmask = IN_CLASSA_NET; 3243 else if (IN_CLASSB(addr)) 3244 nmask = IN_CLASSB_NET; 3245 else 3246 nmask = IN_CLASSC_NET; 3247 /* class D nets are disallowed by bad_ip_adrs */ 3248 mask = netmask | htonl(nmask); 3249 3250 /* 3251 * Scan through the system's network interfaces. 3252 */ 3253 ifc.ifc_len = sizeof(ifs); 3254 ifc.ifc_req = ifs; 3255 if (ioctl(ip_sockfd, SIOCGIFCONF, &ifc) < 0) { 3256 warning("ioctl(SIOCGIFCONF): %m"); 3257 return mask; 3258 } 3259 ifend = ALIGNED_CAST(struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 3260 for (ifr = ifc.ifc_req; ifr < ifend; ifr = ALIGNED_CAST(struct ifreq *) 3261 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { 3262 /* 3263 * Check the interface's internet address. 3264 */ 3265 if (ifr->ifr_addr.sa_family != AF_INET) 3266 continue; 3267 ina = (ALIGNED_CAST(struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; 3268 if ((ntohl(ina) & nmask) != (addr & nmask)) 3269 continue; 3270 /* 3271 * Check that the interface is up, and not point-to-point or loopback. 3272 */ 3273 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 3274 if (ioctl(ip_sockfd, SIOCGIFFLAGS, &ifreq) < 0) 3275 continue; 3276 if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) 3277 != IFF_UP) 3278 continue; 3279 /* 3280 * Get its netmask and OR it into our mask. 3281 */ 3282 if (ioctl(ip_sockfd, SIOCGIFNETMASK, &ifreq) < 0) 3283 continue; 3284 mask |= (ALIGNED_CAST(struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr; 3285 } 3286 3287 return mask; 3288} 3289 3290/* ----------------------------------------------------------------------------- 3291determine if the system has any route to 3292 * a given IP address. 3293 * For demand mode to work properly, we have to ignore routes 3294 * through our own interface. 3295 ----------------------------------------------------------------------------- */ 3296int have_route_to(u_int32_t addr) 3297{ 3298 return -1; 3299} 3300 3301/* ----------------------------------------------------------------------------- 3302Use the hostid as part of the random number seed 3303----------------------------------------------------------------------------- */ 3304int get_host_seed() 3305{ 3306 return gethostid(); 3307} 3308 3309 3310#if 0 3311 3312#define LOCK_PREFIX "/var/spool/lock/LCK.." 3313 3314static char *lock_file; /* name of lock file created */ 3315 3316/* ----------------------------------------------------------------------------- 3317create a lock file for the named lock device 3318----------------------------------------------------------------------------- */ 3319int lock(char *dev) 3320{ 3321 char hdb_lock_buffer[12]; 3322 int fd, pid, n; 3323 char *p; 3324 size_t l; 3325 3326 if ((p = strrchr(dev, '/')) != NULL) 3327 dev = p + 1; 3328 l = strlen(LOCK_PREFIX) + strlen(dev) + 1; 3329 lock_file = malloc(l); 3330 if (lock_file == NULL) 3331 novm("lock file name"); 3332 slprintf(lock_file, l, "%s%s", LOCK_PREFIX, dev); 3333 3334 while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { 3335 if (errno == EEXIST 3336 && (fd = open(lock_file, O_RDONLY, 0)) >= 0) { 3337 /* Read the lock file to find out who has the device locked */ 3338 n = read(fd, hdb_lock_buffer, 11); 3339 if (n <= 0) { 3340 error("Can't read pid from lock file %s", lock_file); 3341 close(fd); 3342 } else { 3343 hdb_lock_buffer[n] = 0; 3344 pid = atoi(hdb_lock_buffer); 3345 if (kill(pid, 0) == -1 && errno == ESRCH) { 3346 /* pid no longer exists - remove the lock file */ 3347 if (unlink(lock_file) == 0) { 3348 close(fd); 3349 notice("Removed stale lock on %s (pid %d)", 3350 dev, pid); 3351 continue; 3352 } else 3353 warning("Couldn't remove stale lock on %s", 3354 dev); 3355 } else 3356 notice("Device %s is locked by pid %d", 3357 dev, pid); 3358 } 3359 close(fd); 3360 } else 3361 error("Can't create lock file %s: %m", lock_file); 3362 free(lock_file); 3363 lock_file = NULL; 3364 return -1; 3365 } 3366 3367 slprintf(hdb_lock_buffer, sizeof(hdb_lock_buffer), "%10d\n", getpid()); 3368 write(fd, hdb_lock_buffer, 11); 3369 3370 close(fd); 3371 return 0; 3372} 3373 3374/* ----------------------------------------------------------------------------- 3375remove our lockfile 3376----------------------------------------------------------------------------- */ 3377void unlock() 3378{ 3379 if (lock_file) { 3380 unlink(lock_file); 3381 free(lock_file); 3382 lock_file = NULL; 3383 } 3384} 3385#endif 3386 3387/* ----------------------------------------------------------------------------- 3388----------------------------------------------------------------------------- */ 3389int sys_loadplugin(char *arg) 3390{ 3391 char path[MAXPATHLEN]; 3392 int ret = -1; 3393 CFBundleRef bundle; 3394 CFURLRef url; 3395 int (*start)(CFBundleRef); 3396 3397 3398 if (arg[0] == '/') { 3399 strlcpy(path, arg, sizeof(path)); 3400 } 3401 else { 3402 strlcpy(path, "/System/Library/Extensions/", sizeof(path)); 3403 strlcat(path, arg, sizeof(path)); 3404 } 3405 3406 url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)path, strlen(path), TRUE); 3407 if (url) { 3408 bundle = CFBundleCreate(NULL, url); 3409 if (bundle) { 3410 3411 if (CFBundleLoadExecutable(bundle) 3412 && (start = CFBundleGetFunctionPointerForName(bundle, CFSTR("start")))) { 3413 3414 ret = (*start)(bundle); 3415 } 3416 3417 CFRelease(bundle); 3418 } 3419 CFRelease(url); 3420 } 3421 return ret; 3422} 3423 3424/* ----------------------------------------------------------------------------- 3425----------------------------------------------------------------------------- */ 3426int sys_eaploadplugin(char *arg, eap_ext *eap) 3427{ 3428 char path[MAXPATHLEN]; 3429 int ret = -1; 3430 CFBundleRef bundle; 3431 CFURLRef url; 3432 CFDictionaryRef dict; 3433 3434 if (arg[0] == '/') { 3435 strlcpy(path, arg, sizeof(path)); 3436 } 3437 else { 3438 strlcpy(path, "/System/Library/Extensions/", sizeof(path)); 3439 strlcat(path, arg, sizeof(path)); 3440 } 3441 3442 url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)path, strlen(path), TRUE); 3443 if (url) { 3444 3445 dict = CFBundleCopyInfoDictionaryForURL(url); 3446 if (dict) { 3447 CFNumberRef num; 3448 CFStringRef str; 3449 int i; 3450 3451 bzero(eap, sizeof(eap_ext)); 3452 num = CFDictionaryGetValue(dict, CFSTR("EAPType")); 3453 if (num && (CFGetTypeID(num) == CFNumberGetTypeID())) { 3454 CFNumberGetValue(num, kCFNumberSInt32Type, &i); 3455 eap->type = i; 3456 } 3457 3458 str = CFDictionaryGetValue(dict, CFSTR("EAPName")); 3459 if (str && (CFGetTypeID(str) == CFStringGetTypeID())) { 3460 eap->name = malloc(CFStringGetLength(str) + 1); 3461 if (eap->name) 3462 CFStringGetCString((CFStringRef)str, eap->name, CFStringGetLength(str) + 1, kCFStringEncodingUTF8); 3463 } 3464 CFRelease(dict); 3465 3466 bundle = CFBundleCreate(NULL, url); 3467 if (bundle) { 3468 3469 if (CFBundleLoadExecutable(bundle)) { 3470 3471 eap->init = CFBundleGetFunctionPointerForName(bundle, CFSTR("Init")); 3472 eap->dispose = CFBundleGetFunctionPointerForName(bundle, CFSTR("Dispose")); 3473 eap->process = CFBundleGetFunctionPointerForName(bundle, CFSTR("Process")); 3474 eap->free = CFBundleGetFunctionPointerForName(bundle, CFSTR("Free")); 3475 eap->attribute = CFBundleGetFunctionPointerForName(bundle, CFSTR("GetAttribute")); 3476 eap->interactive_ui = CFBundleGetFunctionPointerForName(bundle, CFSTR("InteractiveUI")); 3477 eap->print_packet = CFBundleGetFunctionPointerForName(bundle, CFSTR("PrintPacket")); 3478 eap->identity = CFBundleGetFunctionPointerForName(bundle, CFSTR("Identity")); 3479 3480 // keep a ref to release later 3481 eap->plugin = bundle; 3482 3483 ret = 0; 3484 } 3485 3486 if (ret) 3487 CFRelease(bundle); 3488 } 3489 } 3490 CFRelease(url); 3491 } 3492 return ret; 3493} 3494 3495/* ----------------------------------------------------------------------------- 3496publish a dictionnary entry in the cache, given a key 3497----------------------------------------------------------------------------- */ 3498int publish_keyentry(CFStringRef key, CFStringRef entry, CFTypeRef value) 3499{ 3500 CFMutableDictionaryRef dict; 3501 CFPropertyListRef ref; 3502 3503 // ppp daemons without services are not published in the cache 3504 if (cfgCache == NULL) 3505 return 0; 3506 3507 if (publish_dict && key && CFDictionaryContainsKey(publish_dict, key) && (ref = CFDictionaryGetValue(publish_dict, key))) { 3508 dict = CFDictionaryCreateMutableCopy(0, 0, ref); 3509 } else { 3510 dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3511 } 3512 3513 if (dict == 0) 3514 return 0; 3515 3516 CFDictionarySetValue(dict, entry, value); 3517 if (update_publish_dict(key,dict) == 0) 3518 warning("publish_entry SCDSet() failed: %s\n", SCErrorString(SCError())); 3519 CFRelease(dict); 3520 3521 return 1; 3522 } 3523 3524/* ----------------------------------------------------------------------------- 3525publish a numerical entry in the cache, given a dictionary 3526----------------------------------------------------------------------------- */ 3527int publish_dictnumentry(CFStringRef dict, CFStringRef entry, int val) 3528{ 3529 int ret = ENOMEM; 3530 CFNumberRef num; 3531 CFStringRef key; 3532 3533 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceidRef, dict); 3534 if (key) { 3535 num = CFNumberCreate(NULL, kCFNumberIntType, &val); 3536 if (num) { 3537 ret = publish_keyentry(key, entry, num); 3538 CFRelease(num); 3539 ret = 0; 3540 } 3541 CFRelease(key); 3542 } 3543 return ret; 3544} 3545 3546/* ----------------------------------------------------------------------------- 3547publish a string entry in the cache, given a dictionary 3548----------------------------------------------------------------------------- */ 3549int publish_dictstrentry(CFStringRef dict, CFStringRef entry, char *str, int encoding) 3550{ 3551 3552 int ret = ENOMEM; 3553 CFStringRef ref; 3554 CFStringRef key; 3555 3556 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceidRef, dict); 3557 if (key) { 3558 ref = CFStringCreateWithCString(NULL, str, encoding); 3559 if (ref) { 3560 ret = publish_keyentry(key, entry, ref); 3561 CFRelease(ref); 3562 ret = 0; 3563 } 3564 CFRelease(key); 3565 } 3566 return ret; 3567} 3568 3569/* ----------------------------------------------------------------------------- 3570 republish Dynamic store 3571 ----------------------------------------------------------------------------- */ 3572static void 3573republish_dict(SCDynamicStoreRef store __unused, void *info __unused) 3574{ 3575 int count; 3576 3577 dbglog("DynamicStore Server has reconnected, republish keys"); 3578 if (publish_dict == NULL) 3579 return; 3580 3581 count = CFDictionaryGetCount(publish_dict); 3582 if ( count ){ 3583 CFRelease(cfgCache); 3584 cfgCache = SCDynamicStoreCreate(0, CFSTR("pppd"), 0, 0); /* create new ref with server */ 3585 if (cfgCache == 0){ 3586 fatal("republish_dict SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); 3587 return; 3588 } 3589 3590 dbglog("republish_dict: processing %d keys", count); 3591 if (demand) { /* Republish directly for demand mode */ 3592 if (publish_dict) { 3593 SCDynamicStoreSetMultiple(cfgCache, publish_dict, NULL, NULL); 3594 } 3595 } else if (!commit_publish_dict()) { 3596 warning("republish_dict SCDynamicStoreSetMultiple failed key: %s\n", SCErrorString(SCError())); 3597 } 3598 } 3599} 3600 3601/* ----------------------------------------------------------------------------- 3602unpublish a dictionnary entry from the cache, given the dict key 3603----------------------------------------------------------------------------- */ 3604int unpublish_keyentry(CFStringRef key, CFStringRef entry) 3605{ 3606 CFMutableDictionaryRef dict; 3607 CFPropertyListRef ref; 3608 3609 // ppp daemons without services are not published in the cache 3610 if (cfgCache == NULL) 3611 return 0; 3612 3613 if (publish_dict && key && CFDictionaryContainsKey(publish_dict, key) && (ref = CFDictionaryGetValue(publish_dict, key))) { 3614 if ((dict = CFDictionaryCreateMutableCopy(0, 0, ref))) { 3615 CFDictionaryRemoveValue(dict, entry); 3616 if (update_publish_dict(key, dict) == 0) 3617 warning("unpublish_keyentry SCDSet() failed: %s\n", SCErrorString(SCError())); 3618 CFRelease(dict); 3619 } 3620 } 3621 3622 return 0; 3623} 3624 3625/* ----------------------------------------------------------------------------- 3626unpublish a complete dictionnary from the cache 3627----------------------------------------------------------------------------- */ 3628int unpublish_dict(CFStringRef dict) 3629{ 3630 int ret = ENOMEM; 3631 CFStringRef key; 3632 3633 if (cfgCache == NULL) 3634 return 0; 3635 3636 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceidRef, dict); 3637 if (key) { 3638 if (publish_dict){ 3639 CFDictionaryRemoveValue(publish_dict, key); 3640 } 3641 ret = !SCDynamicStoreRemoveValue(cfgCache, key); 3642 CFRelease(key); 3643 } 3644 return ret; 3645} 3646 3647/* ----------------------------------------------------------------------------- 3648unpublish a dictionnary entry from the cache, given the dict name 3649----------------------------------------------------------------------------- */ 3650int unpublish_dictentry(CFStringRef dict, CFStringRef entry) 3651{ 3652 int ret = ENOMEM; 3653 CFStringRef key; 3654 3655 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceidRef, dict); 3656 if (key) { 3657 ret = unpublish_keyentry(key, entry); 3658 CFRelease(key); 3659 ret = 0; 3660 } 3661 return ret; 3662} 3663 3664/* ----------------------------------------------------------------------------- 3665get mach asbolute time, for timeout purpose independent of date changes 3666----------------------------------------------------------------------------- */ 3667int getabsolutetime(struct timeval *timenow) 3668{ 3669 double now; 3670 3671 if (timeScaleSeconds == 0) 3672 return -1; 3673 3674 now = mach_absolute_time(); 3675 timenow->tv_sec = now * timeScaleSeconds; 3676 timenow->tv_usec = (now * timeScaleMicroSeconds) - ((double)timenow->tv_sec * 1000000); 3677 return 0; 3678} 3679 3680/* ----------------------------------------------------------------------------- 3681our new phase hook 3682----------------------------------------------------------------------------- */ 3683void sys_phasechange(void *arg, uintptr_t p) 3684{ 3685 3686 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPStatus, p); 3687 3688 switch (p) { 3689 3690 case PHASE_ESTABLISH: 3691 connecttime = mach_absolute_time() * timeScaleSeconds; 3692 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPConnectTime, connecttime); 3693 if (maxconnect) 3694 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPDisconnectTime, connecttime + maxconnect); 3695 break; 3696 3697 case PHASE_SERIALCONN: 3698 unpublish_dictentry(kSCEntNetPPP, kSCPropNetPPPRetryConnectTime); 3699 break; 3700 3701 case PHASE_WAITONBUSY: 3702 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPRetryConnectTime, redialtimer + (mach_absolute_time() * timeScaleSeconds)); 3703 break; 3704 3705 case PHASE_RUNNING: 3706 break; 3707 3708 case PHASE_DORMANT: 3709 case PHASE_HOLDOFF: 3710 case PHASE_DEAD: 3711 sys_eventnotify((void*)PPP_EVT_DISCONNECTED, status); 3712 break; 3713 3714 case PHASE_DISCONNECT: 3715 unpublish_dictentry(kSCEntNetPPP, CFSTR("AuthPeerName") /*kSCPropNetPPPAuthPeerName*/); 3716 unpublish_dictentry(kSCEntNetPPP, kSCPropNetPPPCommRemoteAddress); 3717 unpublish_dictentry(kSCEntNetPPP, kSCPropNetPPPConnectTime); 3718 unpublish_dictentry(kSCEntNetPPP, kSCPropNetPPPDisconnectTime); 3719 sys_eventnotify((void*)PPP_EVT_REQUEST_UNINSTALL, 0); 3720 break; 3721 } 3722 3723 /* send phase notification to the controller */ 3724 if (phase != PHASE_DEAD) 3725 sys_notify(PPPD_PHASE, phase, ifunit); 3726} 3727 3728 3729/* ----------------------------------------------------------------------------- 3730----------------------------------------------------------------------------- */ 3731void sys_authpeersuccessnotify(void *param, uintptr_t info) 3732{ 3733 struct auth_peer_success_info *peerinfo = (struct auth_peer_success_info *)info; 3734 3735 publish_dictstrentry(kSCEntNetPPP, CFSTR("AuthPeerName") /*kSCPropNetPPPAuthPeerName*/, peerinfo->name, kCFStringEncodingUTF8); 3736} 3737 3738/* ----------------------------------------------------------------------------- 3739----------------------------------------------------------------------------- */ 3740void sys_timeremaining(void *param, uintptr_t info) 3741{ 3742 struct lcp_timeremaining_info *timeinfo = (struct lcp_timeremaining_info *)info; 3743 u_int32_t val = 0, curtime = mach_absolute_time() * timeScaleSeconds; 3744 3745 if (timeinfo->time == 0xFFFFFFFF) { 3746 // infinite timer from the server, restore our maxconnect time if any 3747 if (maxconnect) 3748 val = connecttime + maxconnect; 3749 } 3750 else { 3751 // valid timer from the server, the disconnect time will be the min between 3752 // our setup and what says the server. 3753 if (maxconnect) 3754 val = MIN(curtime + timeinfo->time, connecttime + maxconnect); 3755 else 3756 val = curtime + timeinfo->time; 3757 } 3758 3759 if (val) 3760 publish_dictnumentry(kSCEntNetPPP, kSCPropNetPPPDisconnectTime, val); 3761 else 3762 unpublish_dictentry(kSCEntNetPPP, kSCPropNetPPPDisconnectTime); 3763 3764} 3765 3766/* ----------------------------------------------------------------------------- 3767----------------------------------------------------------------------------- */ 3768void sys_publish_remoteaddress(char *addr) 3769{ 3770 3771 if (addr) 3772 publish_dictstrentry(kSCEntNetPPP, kSCPropNetPPPCommRemoteAddress, addr, kCFStringEncodingUTF8); 3773} 3774 3775/* ----------------------------------------------------------------------------- 3776our pid has changed, reinit things 3777----------------------------------------------------------------------------- */ 3778void sys_reinit() 3779{ 3780 3781 cfgCache = SCDynamicStoreCreate(0, CFSTR("pppd"), 0, 0); 3782 if (cfgCache == 0) 3783 fatal("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); 3784 3785 publish_dictnumentry(kSCEntNetPPP, CFSTR("pid"), getpid()); 3786} 3787 3788/* ----------------------------------------------------------------------------- 3789we are exiting 3790----------------------------------------------------------------------------- */ 3791void sys_exitnotify(void *arg, uintptr_t exitcode) 3792{ 3793 3794 // unpublish the various info about the connection 3795 unpublish_dict(kSCEntNetPPP); 3796 unpublish_dict(kSCEntNetDNS); 3797 unpublish_dict(kSCEntNetProxies); 3798#if !TARGET_OS_EMBEDDED 3799 unpublish_dict(kSCEntNetSMB); 3800#endif 3801 unpublish_dict(kSCEntNetInterface); 3802 3803 sys_eventnotify((void*)PPP_EVT_DISCONNECTED, exitcode); 3804 3805 if (cfgCache) { 3806 CFRelease(cfgCache); 3807 cfgCache = 0; 3808 } 3809 3810 if (publish_dict){ 3811 CFRelease(publish_dict); 3812 publish_dict = NULL; 3813 } 3814} 3815 3816/* ----------------------------------------------------------------------------- 3817add/remove a route via an interface 3818----------------------------------------------------------------------------- */ 3819int 3820route_interface(int cmd, struct in_addr host, struct in_addr addr_mask, char iftype, char *ifname, int is_host) 3821{ 3822 int len, iflen; 3823 int rtm_seq = 0; 3824 struct { 3825 struct rt_msghdr hdr; 3826 struct sockaddr_in dst; 3827 struct sockaddr_dl iface; 3828 struct sockaddr_in mask; 3829 } rtmsg; 3830 3831 char host_str[INET_ADDRSTRLEN]; 3832 char mask_str[INET_ADDRSTRLEN]; 3833 int sockfd = -1; 3834 3835 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) { 3836 error("route_interface: open routing socket failed, %m. (address %s, mask %s, interface %s, host %d).", 3837 addr2ascii(AF_INET, &host, sizeof(host), host_str), 3838 addr2ascii(AF_INET, &addr_mask, sizeof(addr_mask), mask_str), 3839 ifname, 3840 is_host); 3841 return (0); 3842 } 3843 3844 memset(&rtmsg, 0, sizeof(rtmsg)); 3845 rtmsg.hdr.rtm_type = cmd; 3846 rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC; 3847 if (is_host) 3848 rtmsg.hdr.rtm_flags |= RTF_HOST; 3849 rtmsg.hdr.rtm_version = RTM_VERSION; 3850 rtmsg.hdr.rtm_seq = ++rtm_seq; 3851 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; 3852 rtmsg.dst.sin_len = sizeof(rtmsg.dst); 3853 rtmsg.dst.sin_family = AF_INET; 3854 rtmsg.dst.sin_addr = host; 3855 iflen = MIN(strlen(ifname), sizeof(rtmsg.iface.sdl_data)); 3856 rtmsg.iface.sdl_len = sizeof(rtmsg.iface); 3857 rtmsg.iface.sdl_family = AF_LINK; 3858 rtmsg.iface.sdl_type = iftype; 3859 rtmsg.iface.sdl_nlen = iflen; 3860 strncpy(rtmsg.iface.sdl_data, ifname, iflen); 3861 3862 // if addr_mask non-zero add it 3863 if (addr_mask.s_addr != 0) { 3864 rtmsg.hdr.rtm_addrs |= RTA_NETMASK; 3865 rtmsg.mask.sin_len = sizeof(rtmsg.mask); 3866 rtmsg.mask.sin_family = AF_INET; 3867 rtmsg.mask.sin_addr = addr_mask; 3868 } 3869 3870 len = sizeof(rtmsg); 3871 rtmsg.hdr.rtm_msglen = len; 3872 if (write(sockfd, &rtmsg, len) < 0) { 3873 sys_log((cmd == RTM_DELETE)? LOG_DEBUG : LOG_ERR, "route_interface: write routing socket failed, %s. (address %s, mask %s, interface %s, host %d).", 3874 strerror(errno), 3875 addr2ascii(AF_INET, &host, sizeof(host), host_str), 3876 addr2ascii(AF_INET, &addr_mask, sizeof(addr_mask), mask_str), 3877 ifname, 3878 is_host); 3879 close(sockfd); 3880 return (0); 3881 } 3882 3883 close(sockfd); 3884 return (1); 3885} 3886 3887/* ----------------------------------------------------------------------------- 3888 add/remove a route via a gateway 3889----------------------------------------------------------------------------- */ 3890int 3891route_gateway(int cmd, struct in_addr dest, struct in_addr mask, struct in_addr gateway, int use_gway_flag) 3892{ 3893 char dest_str[INET_ADDRSTRLEN]; 3894 char mask_str[INET_ADDRSTRLEN]; 3895 char gateway_str[INET_ADDRSTRLEN]; 3896 int len; 3897 int rtm_seq = 0; 3898 3899 struct { 3900 struct rt_msghdr hdr; 3901 struct sockaddr_in dst; 3902 struct sockaddr_in gway; 3903 struct sockaddr_in mask; 3904 } rtmsg; 3905 3906 int sockfd = -1; 3907 3908 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) { 3909 sys_log(LOG_INFO, "host_gateway: open routing socket failed, %s. (address %s, mask %s, gateway %s, use-gateway %d).", 3910 strerror(errno), 3911 addr2ascii(AF_INET, &dest, sizeof(dest), dest_str), 3912 addr2ascii(AF_INET, &mask, sizeof(mask), mask_str), 3913 addr2ascii(AF_INET, &gateway, sizeof(gateway), gateway_str), 3914 use_gway_flag); 3915 return (0); 3916 } 3917 3918 memset(&rtmsg, 0, sizeof(rtmsg)); 3919 rtmsg.hdr.rtm_type = cmd; 3920 rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC; 3921 if (use_gway_flag) 3922 rtmsg.hdr.rtm_flags |= RTF_GATEWAY; 3923 rtmsg.hdr.rtm_version = RTM_VERSION; 3924 rtmsg.hdr.rtm_seq = ++rtm_seq; 3925 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY; 3926 rtmsg.dst.sin_len = sizeof(rtmsg.dst); 3927 rtmsg.dst.sin_family = AF_INET; 3928 rtmsg.dst.sin_addr = dest; 3929 rtmsg.gway.sin_len = sizeof(rtmsg.gway); 3930 rtmsg.gway.sin_family = AF_INET; 3931 rtmsg.gway.sin_addr = gateway; 3932 rtmsg.mask.sin_len = sizeof(rtmsg.mask); 3933 rtmsg.mask.sin_family = AF_INET; 3934 rtmsg.mask.sin_addr = mask; 3935 3936 len = sizeof(rtmsg); 3937 rtmsg.hdr.rtm_msglen = len; 3938 if (write(sockfd, &rtmsg, len) < 0) { 3939 sys_log((cmd == RTM_DELETE)? LOG_DEBUG : LOG_ERR, "host_gateway: write routing socket failed, %s. (address %s, mask %s, gateway %s, use-gateway %d).", 3940 strerror(errno), 3941 addr2ascii(AF_INET, &dest, sizeof(dest), dest_str), 3942 addr2ascii(AF_INET, &mask, sizeof(mask), mask_str), 3943 addr2ascii(AF_INET, &gateway, sizeof(gateway), gateway_str), 3944 use_gway_flag); 3945 close(sockfd); 3946 return (0); 3947 } 3948 3949 close(sockfd); 3950 return (1); 3951} 3952 3953// Here stealing the in_cksum function which computes checksum from original ping. 3954static int 3955in_cksum(u_short *addr, int len) 3956{ 3957 register int nleft = len; 3958 register u_short *w = addr; 3959 register int sum = 0; 3960 u_short answer = 0; 3961 3962 // Our algorithm is simple, using a 32 bit accumulator (sum), we add 3963 // sequential 16 bit words to it, and at the end, fold back all the 3964 // carry bits from the top 16 bits into the lower 16 bits. 3965 3966 while (nleft > 1) { 3967 sum += *w++; 3968 nleft -= 2; 3969 } 3970 3971 /* mop up an odd byte, if necessary */ 3972 if (nleft == 1) { 3973 *(u_char *)(&answer) = *(u_char *)w; 3974 sum += answer; 3975 } 3976 3977 // Add back carry outs from top 16 bits to low 16 bits 3978 sum = (sum >> 16) + (sum & 0xffff); // Add hi 16 to low 16 3979 sum += (sum >> 16); // Add carry 3980 answer = ~sum; // Truncate to 16 bits 3981 3982 return answer; 3983} 3984 3985static int 3986ppp_scoped_ping (int s, 3987 unsigned int ifscope, 3988 struct sockaddr_in *dst, 3989 int ntransmit) 3990{ 3991 int i; 3992 int hold; 3993 struct icmp *icp; 3994 u_char *packet; 3995 u_char outpack[IP_MAXPACKET] __attribute__ ((aligned(4))); // Wcast-align fix - force alignment 3996 3997 if (s < 0) { 3998 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); 3999 if (s < 0) { 4000 return -1; 4001 } 4002 if (ifscope) { 4003 if (setsockopt(s, IPPROTO_IP, IP_BOUND_IF, (char *)&ifscope, sizeof(ifscope)) != 0) { 4004 close(s); 4005 return -1; 4006 } 4007 } 4008 4009 hold = IP_MAXPACKET + 128; 4010 (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold)); 4011 } 4012 4013 packet = outpack; 4014 icp = ALIGNED_CAST(struct icmp *)outpack; 4015 icp->icmp_type = ICMP_ECHO; 4016 icp->icmp_code = 0; 4017 icp->icmp_cksum = 0; 4018 icp->icmp_seq = htons(ntransmit); 4019 icp->icmp_id = getpid() & 0xFFFF; 4020 icp->icmp_cksum = in_cksum((u_short *)icp, ICMP_MINLEN); 4021 if ((i = sendto(s, (char *)packet, ICMP_MINLEN, 0, (struct sockaddr *)dst, sizeof(*dst))) != ICMP_MINLEN) { 4022 close(s); 4023 return -1; 4024 } 4025 return s; 4026} 4027 4028int 4029ppp_ip_probe_send (void *arg) 4030{ 4031 int scope; 4032 int i = 0; 4033 4034 dbglog("%s: starting", __FUNCTION__); 4035 4036 if (!session || !session->valid) { 4037 return -1; 4038 } 4039 4040 scope = if_nametoindex(session->interface_name); 4041 4042 session->probe_success = 0; 4043 4044 // first probe to goog-dns 4045 if ((session->probe_addrs[GOOG_DNS_PROBE].sin_family == AF_INET) && 4046 session->probe_addrs[GOOG_DNS_PROBE].sin_addr.s_addr) { 4047 dbglog("%s: found goog-dns address", __FUNCTION__); 4048 if ((session->probe_fds[GOOG_DNS_PROBE] = ppp_scoped_ping(session->probe_fds[GOOG_DNS_PROBE], 4049 scope, 4050 &session->probe_addrs[GOOG_DNS_PROBE], 4051 session->probe_ntransmit)) != -1) { 4052 add_fd(session->probe_fds[GOOG_DNS_PROBE]); 4053 dbglog("%s: sent to goog-dns over scope %d", __FUNCTION__, scope); 4054 i++; 4055 } 4056 } else { 4057 info("%s: no goog-dns address", __FUNCTION__); 4058 } 4059 // next probes to server and alternate server 4060 if ((session->probe_addrs[PEER_ADDR_PROBE].sin_family == AF_INET) && 4061 session->probe_addrs[PEER_ADDR_PROBE].sin_addr.s_addr) { 4062 dbglog("%s: found peer address", __FUNCTION__); 4063 // current vpn server 4064 if ((session->probe_fds[PEER_ADDR_PROBE] = ppp_scoped_ping(session->probe_fds[PEER_ADDR_PROBE], 4065 scope, 4066 &session->probe_addrs[PEER_ADDR_PROBE], 4067 session->probe_ntransmit)) != -1) { 4068 add_fd(session->probe_fds[PEER_ADDR_PROBE]); 4069 dbglog("%s: sent to peer over scope %d", __FUNCTION__, scope); 4070 i++; 4071 } 4072 4073 if ((session->probe_addrs[ALT_PEER_ADDR_PROBE].sin_family == AF_INET) && 4074 session->probe_addrs[ALT_PEER_ADDR_PROBE].sin_addr.s_addr) { 4075 dbglog("%s: found alternate peer address", __FUNCTION__); 4076 // alternate vpn server 4077 if ((session->probe_fds[ALT_PEER_ADDR_PROBE] = ppp_scoped_ping(session->probe_fds[ALT_PEER_ADDR_PROBE], 4078 scope, 4079 &session->probe_addrs[ALT_PEER_ADDR_PROBE], 4080 session->probe_ntransmit)) != -1) { 4081 add_fd(session->probe_fds[ALT_PEER_ADDR_PROBE]); 4082 info("%s: sent to alternate peer over scope %d", __FUNCTION__, scope); 4083 i++; 4084 } 4085 } else { 4086 dbglog("%s: no alternate peer address", __FUNCTION__); 4087 } 4088 } else { 4089 dbglog("%s: no peer address", __FUNCTION__); 4090 } 4091 if (i) { 4092 dbglog("%s: %d probes sent", __FUNCTION__, i); 4093 session->probe_tries++; 4094 if (!session->probe_timer_running) { 4095 session->probe_timer_running = 1; 4096 TIMEOUT(ppp_ip_probe_timeout, 0, 3); 4097 } 4098 return 0; 4099 } 4100 return -1; 4101} 4102 4103int 4104ppp_ip_probe_stop (void *arg) 4105{ 4106 int i; 4107 4108 if (!session || !session->valid) { 4109 return -1; 4110 } 4111 4112 if (session->probe_timer_running) { 4113 session->probe_timer_running = 0; 4114 UNTIMEOUT(ppp_ip_probe_timeout, 0); 4115 dbglog("ppp_auxiliary_probe stopped"); 4116 } 4117 4118 for (i = 0; i < MAX_PROBE_ADDRS; i++) { 4119 if (session->probe_fds[i] > 0) { 4120 remove_fd(session->probe_fds[i]); 4121 close(session->probe_fds[i]); 4122 session->probe_fds[i] = -1; 4123 } 4124 } 4125 session->probe_tries = 0; 4126 session->probe_success = 0; 4127 return 0; 4128} 4129 4130static void 4131ppp_ip_probe_timeout (void *arg) 4132{ 4133 if (!session || !session->valid) { 4134 return; 4135 } 4136 4137 if (session->probe_tries < 15) { 4138 if (!ppp_ip_probe_send(arg)) { 4139 return; 4140 } 4141 } 4142 error("ppp_auxiliary_probe timed out"); 4143} 4144 4145void ppp_session_clear (ppp_session_t *sess) 4146{ 4147 int i; 4148 4149 if (sess) { 4150 bzero(sess, sizeof(*sess)); 4151 for (i = 0; i < MAX_PROBE_ADDRS; i++) { 4152 sess->probe_fds[i] = -1; 4153 } 4154 } 4155} 4156 4157int 4158ppp_variable_echo_is_off (void) 4159{ 4160 if (!session || !session->valid) { 4161 return 1; 4162 } 4163 return(!wait_underlying_interface_up); 4164} 4165 4166void 4167ppp_variable_echo_start (void) 4168{ 4169 if (!session || !session->valid) { 4170 return; 4171 } 4172 if (wait_underlying_interface_up || wait_port_mapping_changed) { 4173 // speed up LCP echos 4174 if (!lcp_echos_hastened) { 4175 dbglog("ppp_variable_echo_start"); 4176 lcp_echo_interval_slow = lcp_echo_interval; 4177 lcp_echo_interval = 1; 4178 lcp_echo_fails_slow = lcp_echo_fails; 4179 if (lcp_echo_fails > 10) { 4180 lcp_echo_fails = 10; // max of 10 secs 4181 } 4182 lcp_echos_hastened = 1; 4183 lcp_echo_restart(0); 4184 } 4185 } 4186} 4187 4188void 4189ppp_variable_echo_stop (void) 4190{ 4191 if (!session || !session->valid) { 4192 return; 4193 } 4194 if (wait_underlying_interface_up || wait_port_mapping_changed) { 4195 dbglog("received echo-reply, ppp_variable_echo_stop!"); 4196 wait_underlying_interface_up = 0; 4197 wait_port_mapping_changed = 0; 4198 if (lcp_echos_hastened) { 4199 lcp_echo_interval = lcp_echo_interval_slow; 4200 lcp_echo_fails = lcp_echo_fails_slow; 4201 lcp_echos_hastened = 0; 4202 } 4203 } 4204} 4205 4206void ppp_auxiliary_probe_ip_up(void *arg, uintptr_t p) 4207{ 4208 ppp_auxiliary_probe_ip = 1; 4209} 4210 4211void ppp_auxiliary_probe_ip_down(void *arg, uintptr_t p) 4212{ 4213 ppp_auxiliary_probe_ip = 0; 4214} 4215 4216void 4217ppp_auxiliary_probe_init (void) 4218{ 4219 ppp_auxiliary_probe_echos_pending = 0; 4220 ppp_auxiliary_probe_success = 0; 4221 if (!ppp_auxiliary_probe_ip_notify_init) { 4222 add_notifier(&ip_up_notify, ppp_auxiliary_probe_ip_up, 0); 4223 add_notifier(&ip_down_notify, ppp_auxiliary_probe_ip_down, 0); 4224 ppp_auxiliary_probe_ip_notify_init= 1; 4225 } 4226} 4227 4228void 4229ppp_auxiliary_probe_stop (void) 4230{ 4231 ppp_ip_probe_stop(session); 4232 ppp_auxiliary_probe_echos_pending = 0; 4233 ppp_auxiliary_probe_success = 0; 4234} 4235 4236void 4237ppp_auxiliary_probe_check (int echos_pending, 4238 probe_disconnect_func disconnect_func, 4239 fsm *f) 4240{ 4241 if (ppp_auxiliary_probe_ip && 4242 !wait_underlying_interface_up && 4243 !wait_port_mapping_changed && 4244 echos_pending > 1){ 4245 // more than 2 echo responses pending: try probing the network 4246 if (!ppp_auxiliary_probe_echos_pending) { 4247 // probe hasn't been started 4248 error("no echo-reply, start ppp_auxiliary_probe!"); 4249 ppp_ip_probe_send(session); 4250 ppp_auxiliary_probe_echos_pending = 1; 4251 ppp_auxiliary_probe_success = 0; 4252 } else if (++ppp_auxiliary_probe_echos_pending > 1 && 4253 ppp_auxiliary_probe_success) { 4254 // we have more than 3 pending echo responses, while the network 4255 // probe succeeded... disconnect 4256 error("no echo-reply, despite successful ppp_auxiliary_probe!"); 4257 // network probe succeeded but no echo replies, disconnect 4258 if (disconnect_func) { 4259 disconnect_func(f); 4260 } 4261 } 4262 } 4263} 4264 4265void 4266ppp_process_auxiliary_probe_input (void) 4267{ 4268 int i, j, result; 4269 4270 if (!session || !session->valid) { 4271 return; 4272 } 4273 4274 for (i = 0, j = 0; i < MAX_PROBE_ADDRS; i++) { 4275 if (session->probe_fds[i] > 0 && is_ready_fd(session->probe_fds[i])) { 4276 result = 0; 4277 read(session->probe_fds[i], &result, 1); 4278 remove_fd(session->probe_fds[i]); 4279 if (result > 0) { 4280 // assume success for now. TODO: log and ignore alt-peer success 4281 session->probe_success++; 4282 j++; 4283 dbglog("ppp_auxiliary_probe[%d] response!", i); 4284 } 4285 close(session->probe_fds[i]); 4286 session->probe_fds[i] = -1; 4287 } 4288 } 4289 if (j) { 4290 if (session->probe_timer_running) { 4291 session->probe_timer_running = 0; 4292 UNTIMEOUT(ppp_ip_probe_timeout, 0); 4293 } 4294 if (ppp_auxiliary_probe_echos_pending) { 4295 ppp_auxiliary_probe_success++; 4296 } 4297 } 4298} 4299 4300#if !TARGET_OS_EMBEDDED 4301static void 4302ppp_clear_one_nat_port_mapping (mdns_nat_mapping_t *mapping) 4303{ 4304 if (mapping) { 4305 // what about mapping->mDNSRef_fd? 4306 if (mapping->mDNSRef != NULL) { 4307 if (mapping->mDNSRef_fd) 4308 remove_fd(mapping->mDNSRef_fd); 4309 DNSServiceRefDeallocate(mapping->mDNSRef); 4310 } 4311 bzero(mapping, sizeof(*mapping)); 4312 } 4313} 4314 4315static int 4316ppp_ignore_nat_port_mapping_update (DNSServiceRef sdRef, 4317 char *sd_name, 4318 char *if_name, 4319 uint32_t if_name_siz, 4320 uint32_t interfaceIndex, 4321 uint32_t publicAddress, 4322 DNSServiceProtocol protocol, 4323 uint16_t privatePort, 4324 uint16_t publicPort) 4325{ 4326 int i = 0, vpn = 0, found = 0; 4327 struct ifaddrs *ifap = NULL; 4328 char interfaceName[32]; 4329 4330 /* check if address still exist */ 4331 if (getifaddrs(&ifap) == 0) { 4332 struct ifaddrs *ifa; 4333 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 4334 if (ifa->ifa_name 4335 && ifa->ifa_addr 4336 && (!strncmp(ifa->ifa_name, "utun", 4) || !strncmp(ifa->ifa_name, "ppp", 3)) 4337 && ifa->ifa_addr->sa_family == AF_INET 4338 && ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == htonl(publicAddress)) { 4339 notice("%s port-mapping update for %s ignored: related to VPN interface. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d\n", 4340 sd_name, 4341 ifa->ifa_name, 4342 publicAddress, 4343 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4344 privatePort, 4345 publicPort); 4346 vpn = 1; 4347 } 4348 if (ifa->ifa_name 4349 && ifa->ifa_addr 4350 && !strncmp(ifa->ifa_name, if_name, if_name_siz) 4351 && ifa->ifa_addr->sa_family == AF_INET 4352 && ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == session->interface_address.s_addr) { 4353 found = 1; 4354 } 4355 } 4356 freeifaddrs(ifap); 4357 } else { 4358 error("%s port-mapping update for %s ignored: failed to get interface list", 4359 sd_name, 4360 if_name); 4361 return 1; 4362 } 4363 4364 if (vpn) { 4365 return 1; 4366 } 4367 bzero(interfaceName, sizeof(interfaceName)); 4368 if_indextoname(interfaceIndex, (char *)interfaceName); 4369 if (!strncmp(interfaceName, if_name, if_name_siz)) { 4370 if (strstr(if_name, "ppp") || strstr(if_name, "utun")) { 4371 // change on PPP interface... we don't care 4372 notice("%s port-mapping update for %s ignored: underlying interface is PPP/VPN. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d\n", 4373 sd_name, 4374 if_name, 4375 publicAddress, 4376 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4377 privatePort, 4378 publicPort); 4379 return 1; 4380 } else { 4381 /* check if address still exist */ 4382 if (found) { 4383 return 0; 4384 } else { 4385 if (!publicAddress || (!publicPort && privatePort)) { 4386 notice("%s port-mapping update for %s ignored: underlying interface down. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d\n", 4387 sd_name, 4388 if_name, 4389 publicAddress, 4390 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4391 privatePort, 4392 publicPort); 4393 for (i = 0; i < session->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 4394 if (session->nat_mapping[i].mDNSRef_tmp == sdRef) { 4395 session->nat_mapping[i].up = 0; 4396 notice("%s port-mapping for %s flagged down because of no connectivity\n", sd_name, if_name); 4397 } 4398 } 4399 return 1; 4400 } 4401 notice("%s port-mapping update for %s ignored: underlying interface's address changed. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d\n", 4402 sd_name, 4403 if_name, 4404 publicAddress, 4405 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4406 privatePort, 4407 publicPort); 4408 return 1; 4409 } 4410 } 4411 } else if (publicAddress && !publicPort && !privatePort && !protocol) { 4412 // an update on the NAT's public IP 4413 return 0; 4414 } else { 4415 // public interface disappeared? 4416 if (!publicAddress && !publicPort && !privatePort && !protocol) { 4417 return 0; 4418 } 4419 /* check if address still exist */ 4420 if (session->interface_address.s_addr == htonl(publicAddress) && found) { 4421 return 0; 4422 } 4423 // change due to another interface, ignore for now 4424 notice("%s port-mapping update for %s ignored: not for interface %s. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d\n", 4425 sd_name, 4426 interfaceName, 4427 if_name, 4428 publicAddress, 4429 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4430 privatePort, 4431 publicPort); 4432 return 1; 4433 } 4434} 4435#endif 4436 4437static void 4438ppp_public_nat_port_mapping_timeout (void *arg) 4439{ 4440 if (!session || !session->valid) { 4441 return; 4442 } 4443 4444 if (session->nat_mapping_timer_running) { 4445 session->nat_mapping_timer_running = 0; 4446 sys_log(LOG_ERR, "NAT's public interface down for more than %d secs... starting faster probe.\n", 4447 PUBLIC_NAT_PORT_MAPPING_TIMEOUT); 4448 // our public interface didn't come back... start faster probe 4449 if (session->failure_func) { 4450 wait_port_mapping_changed = 1; 4451 session->failure_func(); 4452 } 4453 } 4454} 4455 4456void 4457ppp_start_public_nat_port_mapping_timer (void) 4458{ 4459 if (!session || !session->valid) { 4460 return; 4461 } 4462 4463 if (session->nat_mapping_timer_blocked) { 4464 return; 4465 } 4466 4467 if (session->nat_mapping_timer_running) { 4468 return; 4469 } 4470 4471 notice("starting wait-port-mapping timer for %s: %d secs", session->sd_name, PUBLIC_NAT_PORT_MAPPING_TIMEOUT); 4472 TIMEOUT (ppp_public_nat_port_mapping_timeout, 0, PUBLIC_NAT_PORT_MAPPING_TIMEOUT); 4473 session->nat_mapping_timer_running = 1; 4474} 4475 4476void 4477ppp_stop_public_nat_port_mapping_timer (void) 4478{ 4479 if (!session || !session->valid) { 4480 return; 4481 } 4482 4483 if (session->nat_mapping_timer_running) { 4484 UNTIMEOUT (ppp_public_nat_port_mapping_timeout, 0); 4485 session->nat_mapping_timer_running = 0; 4486 } 4487} 4488 4489void 4490ppp_block_public_nat_port_mapping_timer (void) 4491{ 4492 if (!session || !session->valid) { 4493 return; 4494 } 4495 4496 ppp_stop_public_nat_port_mapping_timer(); 4497 session->nat_mapping_timer_blocked = 1; 4498} 4499 4500void 4501ppp_unblock_public_nat_port_mapping_timer (void) 4502{ 4503 if (!session || !session->valid) { 4504 return; 4505 } 4506 4507 session->nat_mapping_timer_blocked = 0; 4508} 4509 4510#if !TARGET_OS_EMBEDDED 4511 4512static void ppp_clear_nat_port_mapping(void); 4513 4514static void 4515ppp_set_nat_port_mapping_callback (DNSServiceRef sdRef, 4516 DNSServiceFlags flags, 4517 uint32_t interfaceIndex, 4518 DNSServiceErrorType errorCode, 4519 uint32_t nPublicAddress, /* four byte IPv4 address in network byte order */ 4520 DNSServiceProtocol protocol, 4521 uint16_t nPrivatePort, 4522 uint16_t nPublicPort, /* may be different than the requested port */ 4523 uint32_t ttl, /* may be different than the requested ttl */ 4524 void *context) 4525{ 4526 uint32_t publicAddress = ntohl(nPublicAddress); 4527 uint16_t privatePort = ntohs(nPrivatePort); 4528 uint16_t publicPort = ntohs(nPublicPort); 4529 int i; 4530 char *sd_name = session->sd_name; 4531 int is_connected = session->valid; 4532 char *if_name = session->interface_name; 4533 uint32_t if_name_siz = session->interface_name_siz; 4534 4535 if (!session || !session->valid) { 4536 return; 4537 } 4538 4539 if (override_primary) { 4540 info("%s port-mapping update for %s ignored: VPN is the Primary interface. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d\n", 4541 sd_name, 4542 if_name, 4543 publicAddress, 4544 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4545 privatePort, 4546 publicPort); 4547 ppp_clear_nat_port_mapping(); 4548 return; 4549 } 4550 4551 if (errorCode != kDNSServiceErr_NoError && errorCode != kDNSServiceErr_DoubleNAT) { 4552 error("%s failed to set port-mapping for %s, errorCode: %d\n", sd_name, if_name, errorCode); 4553 if (errorCode == kDNSServiceErr_NATPortMappingUnsupported || errorCode == kDNSServiceErr_NATPortMappingDisabled) { 4554 for (i = 0; i < session->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 4555 if (session->nat_mapping[i].mDNSRef_tmp == sdRef) { 4556 error("%s port-mapping for %s became invalid. is Connected: %d, Protocol: %s, Private Port: %d, Previous publicAddress: (%x), Previous publicPort: (%d)\n", 4557 sd_name, 4558 if_name, 4559 is_connected, 4560 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4561 privatePort, 4562 session->nat_mapping[i].reflexive.addr, 4563 session->nat_mapping[i].reflexive.port); 4564 if (session->nat_mapping[i].up && is_connected && session->failure_func) { 4565 notice("%s public port-mapping for %s changed... starting faster probe.\n", sd_name, if_name); 4566 wait_port_mapping_changed = 1; 4567 session->failure_func(); 4568 } else { 4569 ppp_clear_nat_port_mapping(); 4570 } 4571 return; 4572 } 4573 } 4574 } else if (errorCode == kDNSServiceErr_ServiceNotRunning) { 4575 ppp_clear_nat_port_mapping(); 4576 } 4577 return; 4578 } 4579 4580 if (ppp_ignore_nat_port_mapping_update(sdRef, sd_name, if_name, if_name_siz, interfaceIndex, publicAddress, protocol, privatePort, publicPort)) { 4581 return; 4582 } 4583 4584 info("%s port-mapping for %s, interfaceIndex: %d, Protocol: %s, Private Port: %d, Public Address: %x, Public Port: %d, TTL: %d%s\n", 4585 sd_name, 4586 if_name, 4587 interfaceIndex, 4588 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4589 privatePort, 4590 publicAddress, 4591 publicPort, 4592 ttl, 4593 (errorCode == kDNSServiceErr_DoubleNAT)? " (Double NAT)" : "."); 4594 4595 // generate a disconnect if we were already connected and we just detected a change in publicAddress or publicPort 4596 for (i = 0; i < session->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 4597 if (session->nat_mapping[i].mDNSRef_tmp == sdRef) { 4598 if (session->nat_mapping[i].up && !publicAddress && !publicPort) { 4599 notice("%s port-mapping for %s indicates public interface down. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d\n", 4600 sd_name, 4601 if_name, 4602 publicAddress, 4603 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4604 privatePort, 4605 publicPort); 4606 // start timer 4607 ppp_start_public_nat_port_mapping_timer(); 4608 return; 4609 } else if (session->nat_mapping[i].up) { 4610 ppp_stop_public_nat_port_mapping_timer(); 4611 } 4612 4613 if (session->interface_address.s_addr == htonl(publicAddress) && privatePort == publicPort) { 4614 notice("%s port-mapping update for %s indicates no NAT. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d\n", 4615 sd_name, 4616 if_name, 4617 publicAddress, 4618 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 4619 privatePort, 4620 publicPort); 4621 } 4622 4623 if (session->nat_mapping[i].interfaceIndex == interfaceIndex && 4624 session->nat_mapping[i].protocol == protocol && 4625 session->nat_mapping[i].privatePort == privatePort) { 4626 info("%s port-mapping for %s consistent. is Connected: %d, interface: %d, protocol: %d, privatePort: %d\n", 4627 sd_name, if_name, is_connected, interfaceIndex, protocol, privatePort); 4628 } else { 4629 // inconsistency (mostly because of mdns api only works for the primary interface): TODO revise 4630 if (session->nat_mapping[i].interfaceIndex != interfaceIndex) { 4631 info("%s port-mapping for %s inconsistent. is Connected: %d, Previous interface: %d, Current interface %d\n", 4632 sd_name, if_name, is_connected, session->nat_mapping[i].interfaceIndex, interfaceIndex); 4633 session->nat_mapping[i].interfaceIndex = interfaceIndex; 4634 } 4635 if (session->nat_mapping[i].protocol != protocol) { 4636 info("%s port-mapping for %s inconsistent. is Connected: %d, Previous protocol: %x, Current protocol %x\n", 4637 sd_name, if_name, is_connected, session->nat_mapping[i].protocol, protocol); 4638 session->nat_mapping[i].protocol = protocol; 4639 } 4640 if (session->nat_mapping[i].privatePort != privatePort) { 4641 info("%s port-mapping for %s inconsistent. is Connected: %d, Previous privatePort: %d, Current privatePort %d\n", 4642 sd_name, if_name, session->nat_mapping[i].privatePort, privatePort); 4643 session->nat_mapping[i].privatePort = privatePort; 4644 } 4645 } 4646 // is mapping up? 4647 if (!session->nat_mapping[i].up) { 4648 if (session->nat_mapping[i].reflexive.addr != publicAddress) { 4649 info("%s port-mapping for %s initialized. is Connected: %d, Previous publicAddress: (%d), Current publicAddress %x\n", 4650 sd_name, if_name, is_connected, session->nat_mapping[i].reflexive.addr, publicAddress); 4651 session->nat_mapping[i].reflexive.addr = publicAddress; 4652 } 4653 if (session->nat_mapping[i].reflexive.port != publicPort) { 4654 info("%s port-mapping for %s initialized. is Connected: %d, Previous publicPort: (%d), Current publicPort %d\n", 4655 sd_name, if_name, is_connected, session->nat_mapping[i].reflexive.port, publicPort); 4656 session->nat_mapping[i].reflexive.port = publicPort; 4657 } 4658 if (session->nat_mapping[i].reflexive.addr && 4659 ((!privatePort && !session->nat_mapping[i].reflexive.port) || (session->nat_mapping[i].reflexive.port))) { 4660 // flag up mapping 4661 session->nat_mapping[i].up = 1; 4662 info("%s port-mapping for %s fully initialized. Flagging up\n", sd_name, if_name); 4663 } 4664 return; 4665 } 4666 4667 if (session->nat_mapping[i].reflexive.addr != publicAddress) { 4668 error("%s port-mapping for %s changed. is Connected: %d, Previous publicAddress: (%x), Current publicAddress %x\n", 4669 sd_name, if_name, is_connected, session->nat_mapping[i].reflexive.addr, publicAddress); 4670 if (is_connected) { 4671 if (!privatePort || publicAddress) { 4672 sys_log(LOG_ERR, "NAT's public address down or changed... starting faster probe.\n"); 4673 if (session->failure_func) { 4674 wait_port_mapping_changed = 1; 4675 session->failure_func(); 4676 } 4677 return; 4678 } 4679 // let function that handles (KEV_INET_NEW_ADDR || KEV_INET_CHANGED_ADDR || KEV_INET_ADDR_DELETED) deal with the connection 4680 return; 4681 } 4682 session->nat_mapping[i].reflexive.addr = publicAddress; 4683 return; 4684 } 4685 if (session->nat_mapping[i].reflexive.port != publicPort) { 4686 error("%s port-mapping for %s changed. is Connected: %d, Previous publicPort: (%d), Current publicPort %d\n", 4687 sd_name, if_name, is_connected, session->nat_mapping[i].reflexive.port, publicPort); 4688 if (is_connected) { 4689 if (!privatePort || publicPort) { 4690 sys_log(LOG_ERR, "NAT's public port down or changed... starting faster probe.\n"); 4691 if (session->failure_func) { 4692 wait_port_mapping_changed = 1; 4693 session->failure_func(); 4694 } 4695 return; 4696 } 4697 // let function that handles (KEV_INET_NEW_ADDR || KEV_INET_CHANGED_ADDR || KEV_INET_ADDR_DELETED) deal with the connection 4698 return; 4699 } 4700 session->nat_mapping[i].reflexive.port = publicPort; 4701 return; 4702 } 4703 if (errorCode == kDNSServiceErr_DoubleNAT) { 4704 error("%s port-mapping for %s hasn't changed, however there's a Double NAT. is Connected: %d\n", 4705 sd_name, if_name, is_connected); 4706 } 4707 return; 4708 } 4709 } 4710 return; 4711} 4712 4713static void 4714ppp_clear_nat_port_mapping (void) 4715{ 4716 int i; 4717 4718 if (!session || !session->valid) 4719 return; 4720 4721 info("%s clearing port-mapping for %s\n", session->sd_name, session->interface_name); 4722 4723 ppp_stop_public_nat_port_mapping_timer(); 4724 4725 for (i = 0; i < session->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 4726 ppp_clear_one_nat_port_mapping(&session->nat_mapping[i]); 4727 } 4728 session->nat_mapping_cnt = 0; 4729} 4730 4731static int 4732ppp_set_nat_port_mapping (mdns_nat_mapping_t *mapping, 4733 DNSServiceProtocol protocol, 4734 uint16_t privatePort, 4735 int probe_only) 4736{ 4737 DNSServiceErrorType err = kDNSServiceErr_NoError; 4738 uint16_t publicPort; 4739 uint32_t ttl; 4740 char *sd_name = session->sd_name; 4741 char *if_name = session->interface_name; 4742 uint32_t interfaceIndex = if_nametoindex(session->interface_name); 4743 4744 if (!probe_only) { 4745 publicPort = 0; 4746 ttl = 2 * 3600; // 2 hours 4747 } else { 4748 publicPort = 0; 4749 ttl = 0; 4750 protocol = 0; 4751 privatePort = 0; 4752 } 4753 4754 if (mapping == NULL) { 4755 error("%s invalid mapping pointer for %s\n", sd_name, if_name); 4756 return -1; 4757 } 4758 4759 if (mapping->mDNSRef == NULL) { 4760 err = DNSServiceCreateConnection(&mapping->mDNSRef); 4761 if (err != kDNSServiceErr_NoError || mapping->mDNSRef == NULL) { 4762 error("%s Error calling DNSServiceCreateConnection for %s, error: %d\n", sd_name, if_name, err); 4763 ppp_clear_one_nat_port_mapping(mapping); 4764 return -1; 4765 } 4766 mapping->mDNSRef_fd = DNSServiceRefSockFD(mapping->mDNSRef); 4767 add_fd(mapping->mDNSRef_fd); 4768 } 4769 mapping->mDNSRef_tmp = mapping->mDNSRef; 4770 err = DNSServiceNATPortMappingCreate(&mapping->mDNSRef_tmp, kDNSServiceFlagsShareConnection, interfaceIndex, protocol, htons(privatePort), publicPort, ttl, ppp_set_nat_port_mapping_callback, session); 4771 if (err != kDNSServiceErr_NoError) { 4772 error("%s Error calling DNSServiceNATPortMappingCreate for %s, error: %d\n", sd_name, if_name, err); 4773 ppp_clear_one_nat_port_mapping(mapping); 4774 return -1; 4775 } 4776 mapping->interfaceIndex = interfaceIndex; 4777 mapping->protocol = protocol; 4778 mapping->privatePort = privatePort; 4779 bzero(&mapping->reflexive, sizeof(mapping->reflexive)); 4780 4781 info("%s set port-mapping for %s, interface: %d, protocol: %d, privatePort: %d\n", sd_name, if_name, interfaceIndex, protocol, privatePort); 4782 return 0; 4783} 4784 4785static void 4786l2tp_ipsec_set_nat_port_mapping (void) 4787{ 4788 if (ppp_set_nat_port_mapping(&session->nat_mapping[0], 0, 0, 1) == 0) { 4789 session->nat_mapping_cnt++; 4790 } 4791#if 0 // <rdar://problem/8001582> 4792 if (ppp_set_nat_port_mapping(&session->nat_mapping[1], kDNSServiceProtocol_UDP, (u_int16_t)500, 0) == 0) { 4793 session->nat_mapping_cnt++; 4794 } 4795 if (ppp_set_nat_port_mapping(&session->nat_mapping[2], kDNSServiceProtocol_UDP, (u_int16_t)4500, 0) == 0) { 4796 session->nat_mapping_cnt++; 4797 } 4798#endif 4799} 4800#endif 4801 4802void 4803l2tp_set_nat_port_mapping (void) 4804{ 4805#if !TARGET_OS_EMBEDDED 4806 if (!session || !session->valid) { 4807 return; 4808 } 4809 4810 if (override_primary) { 4811 info("%s port-mapping API for %s ignored: VPN is the Primary interface.\n", 4812 session->sd_name, 4813 session->interface_name); 4814 return; 4815 } 4816 4817 // exit early if interface is PPP/VPN 4818 if (strstr(session->interface_name, "ppp") || strstr(session->interface_name, "utun")) { 4819 return; 4820 } 4821 4822 if (!session->opt_noipsec) { 4823 // we always tranport l2tp over ipsec 4824 l2tp_ipsec_set_nat_port_mapping(); 4825 } else { 4826 if (ppp_set_nat_port_mapping(&session->nat_mapping[0], 0, 0, 1) == 0) { 4827 session->nat_mapping_cnt++; 4828 } 4829#if 0 // <rdar://problem/8001582> 4830 if (ppp_set_nat_port_mapping(&session->nat_mapping[1], kDNSServiceProtocol_UDP, (u_int16_t)1701, 0) == 0) { 4831 session->nat_mapping_cnt++; 4832 } 4833#endif 4834 } 4835#endif // TARGET_OS_EMBEDDED 4836} 4837 4838void 4839l2tp_clear_nat_port_mapping (void) 4840{ 4841#if !TARGET_OS_EMBEDDED 4842 ppp_clear_nat_port_mapping(); 4843#endif // TARGET_OS_EMBEDDED 4844} 4845 4846void 4847pptp_set_nat_port_mapping (void) 4848{ 4849#if !TARGET_OS_EMBEDDED 4850 if (!session || !session->valid) { 4851 return; 4852 } 4853 4854 if (override_primary) { 4855 info("%s port-mapping API for %s ignored: VPN is the Primary interface.\n", 4856 session->sd_name, 4857 session->interface_name); 4858 return; 4859 } 4860 4861 // exit early if interface is PPP/VPN 4862 if (strstr(session->interface_name, "ppp") || strstr(session->interface_name, "utun")) { 4863 return; 4864 } 4865 4866 if (ppp_set_nat_port_mapping(&session->nat_mapping[0], 0, 0, 1) == 0) { 4867 session->nat_mapping_cnt++; 4868 } 4869#if 0 // <rdar://problem/8001582> 4870 if (ppp_set_nat_port_mapping(&session->nat_mapping[1], kDNSServiceProtocol_TCP, (u_int16_t)1723, 0) == 0) { 4871 session->nat_mapping_cnt++; 4872 } 4873#endif 4874#endif // TARGET_OS_EMBEDDED 4875} 4876 4877void 4878pptp_clear_nat_port_mapping (void) 4879{ 4880#if !TARGET_OS_EMBEDDED 4881 ppp_clear_nat_port_mapping(); 4882#endif // TARGET_OS_EMBEDDED 4883} 4884 4885void 4886ppp_process_nat_port_mapping_events (void) 4887{ 4888#if !TARGET_OS_EMBEDDED 4889 int i = 0; 4890 DNSServiceErrorType ret; 4891 4892 for (i = 0; session && session->valid && i < session->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 4893 if (session->nat_mapping[i].mDNSRef && is_ready_fd(session->nat_mapping[i].mDNSRef_fd)) { 4894 ret = DNSServiceProcessResult(session->nat_mapping[i].mDNSRef); 4895 if (ret != kDNSServiceErr_NoError && ret != kDNSServiceErr_Transient) { 4896 error("Error calling DNSServiceProcessResult, error: %d\n", ret); 4897 if (ret == kDNSServiceErr_ServiceNotRunning) { 4898 ppp_clear_nat_port_mapping(); 4899 } 4900 } 4901 // the connection may have been disconnected... hence session may be invalidated after DNSServiceProcessResult. 4902 } 4903 } 4904#endif // TARGET_OS_EMBEDDED 4905} 4906 4907int 4908sys_setup_security_session(void) 4909{ 4910 if (ne_is_controller()) { 4911 return (!ne_setup_security_session()); 4912 } else { 4913 return setup_security_context(); 4914 } 4915} 4916 4917void 4918sys_log(int priority, const char *message, ...) 4919{ 4920 if (ne_is_controller()) { 4921 if (nelog_is_logging_at_level(priority)) { 4922 va_list args; 4923 4924 va_start(args, message); 4925 nelogv(priority, message, args); 4926 va_end(args); 4927 } 4928 } else { 4929 va_list args; 4930 va_start(args, message); 4931 vsyslog(priority, message, args); 4932 va_end(args); 4933 } 4934} 4935