1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25/* ----------------------------------------------------------------------------- 26includes 27----------------------------------------------------------------------------- */ 28#include <mach/mach.h> 29#include <string.h> 30#include <stdio.h> 31#include <termios.h> 32#include <unistd.h> 33#include <sys/errno.h> 34#include <sys/signal.h> 35#include <sys/param.h> 36#include <sys/socket.h> 37#include <net/if.h> 38#include <CoreFoundation/CoreFoundation.h> 39#include <netinet/in.h> 40#include <arpa/inet.h> 41#include <SystemConfiguration/SystemConfiguration.h> 42#include <SystemConfiguration/SCPrivate.h> // for SCLog() 43#include <SystemConfiguration/SCValidation.h> 44#include <sys/ioctl.h> 45#include <net/if_dl.h> 46#include <net/if_utun.h> 47#include <notify.h> 48#include <sys/kern_control.h> 49#include <sys/sys_domain.h> 50#include <servers/bootstrap.h> 51#include <mach/task_special_ports.h> 52#include "pppcontroller_types.h" 53#include "pppcontroller.h" 54#include <bsm/libbsm.h> 55#include <sys/kern_event.h> 56#include <netinet/in_var.h> 57#include <netinet6/in6_var.h> 58#include <netinet6/nd6.h> 59#include <network_information.h> 60 61#include "ppp_msg.h" 62#include "../Family/if_ppplink.h" 63#include "scnc_main.h" 64#include "scnc_client.h" 65#include "scnc_utils.h" 66#include "ppp_option.h" 67#include "PPPControllerPriv.h" 68#include "../Family/ppp_domain.h" 69#include "../Helpers/pppd/pppd.h" 70#include "../Drivers/PPTP/PPTP-plugin/pptp.h" 71#include "../Drivers/L2TP/L2TP-plugin/l2tp.h" 72#include "../Drivers/PPPoE/PPPoE-extension/PPPoE.h" 73#include "ne_sm_bridge_private.h" 74 75/* ----------------------------------------------------------------------------- 76definitions 77----------------------------------------------------------------------------- */ 78#undef CONSTSTR 79#define CONSTSTR(str) (const char *)str 80 81/* ----------------------------------------------------------------------------- 82Forward Declarations 83----------------------------------------------------------------------------- */ 84 85 86/* ----------------------------------------------------------------------------- 87globals 88----------------------------------------------------------------------------- */ 89const char *scnc_ctrl_stopped = "Controller Stopped"; 90const char *scnc_sys_sleep = "System will sleep"; 91const char *scnc_usr_logout = "User Logged out"; 92const char *scnc_usr_switch = "User Switched"; 93const char *scnc_sock_disco = "Socket disconnect"; 94const char *scnc_plugin_chg = "Plugin Change"; 95const char *scnc_app_rem = "App removed"; 96const char *scnc_usr_req = "User Requested"; 97const char *scnc_term_all = "Terminated All"; 98const char *scnc_serv_disp = "Service Disposed"; 99const char *ppp_fatal = "Fatal Error"; 100const char *ppp_option = "Option Error"; 101const char *ppp_not_root = "Not Root"; 102const char *ppp_no_kern = "No Kernel Support"; 103const char *ppp_user_req = "User requested"; 104const char *ppp_lock_fail = "Lock Failed"; 105const char *ppp_open_fail = "Open Failed"; 106const char *ppp_conn_fail = "Connect Failed"; 107const char *ppp_pty_fail = "Pty command Failed"; 108const char *ppp_nego_fail = "Negotiation Failed"; 109const char *ppp_peer_auth_fail = "Peer Authentication Failed"; 110const char *ppp_idle_tmo = "Idle Timeout"; 111const char *ppp_sess_tmo = "Session Timeout"; 112const char *ppp_callback = "Callback"; 113const char *ppp_peer_dead = "Peer Dead"; 114const char *ppp_disco_by_dev = "Disconnect by Device"; 115const char *ppp_loopback = "Loopback Error"; 116const char *ppp_init_fail = "Init Failed"; 117const char *ppp_auth_fail = "Authentication to Peer Failed"; 118const char *ppp_term_fail = "Terminal Failed"; 119const char *ppp_dev_err = "Device Error"; 120const char *ppp_peer_unauth = "Peer Not Authorized"; 121const char *ppp_cnid_auth_fail = "CNID Authentication Failed"; 122const char *ppp_peer_unreach = "Peer Unreachable"; 123const char *ppp_dev_no_srvr = "No Server"; 124const char *ppp_dev_no_ans = "No Answer"; 125const char *ppp_dev_prot_err = "Protocol Error"; 126const char *ppp_dev_net_chg = "Network Changed"; 127const char *ppp_dev_psk = "Shared Secret"; 128const char *ppp_dev_cert = "No Certificate"; 129const char *ppp_dev_no_car = "No Carrier"; 130const char *ppp_dev_no_num = "No Number"; 131const char *ppp_dev_bad_script = "Bad Script"; 132const char *ppp_dev_busy = "Busy"; 133const char *ppp_dev_no_dial = "No Dial Tone"; 134const char *ppp_dev_modem_err = "Modem Error"; 135const char *ppp_dev_hang = "Hang-up"; 136const char *ppp_dev_no_srvc = "No Service"; 137const char *ppp_dev_no_ac = "No AC"; 138const char *ppp_dev_no_ac_srvc = "No AC Service"; 139const char *ppp_dev_conn_refuse = "Connection Refused"; 140const char *ipsec_gen_err = "Generic Error"; 141const char *ipsec_no_srvr_addr = "No Server Address"; 142const char *ipsec_no_psk = "No Shared Secret"; 143const char *ipsec_no_cert = "No Certificate"; 144const char *ipsec_dns_err = "Resolve Address Error"; 145const char *ipsec_no_local = "No Local Network"; 146const char *ipsec_cfg_err = "Configuration Error"; 147const char *ipsec_ctrl_err = "Racoon Control Error"; 148const char *ipsec_conn_err = "Connection Error"; 149const char *ipsec_nego_err = "Negotiation Error"; 150const char *ipsec_psk_err = "Shared Secret Error"; 151const char *ipsec_srvr_cert_err = "Server Certificate Error"; 152const char *ipsec_cli_cert_err = "Client Certificate Error"; 153const char *ipsec_xauth_err = "Xauth Error"; 154const char *ipsec_net_chg = "Network Change"; 155const char *ipsec_peer_disco = "Peer Disconnect"; 156const char *ipsec_peer_dead = "Peer Dead"; 157const char *ipsec_edge_err = "Edge Activation Error"; 158const char *ipsec_idle_tmo = "Idle Timeout"; 159const char *ipsec_cli_cert_pre = "Client Certificate premature"; 160const char *ipsec_cli_cert_exp = "Client Certificate expired"; 161const char *ipsec_srvr_cert_pre = "Server Certificate premature"; 162const char *ipsec_srvr_cert_exp = "Server Certificate expired"; 163const char *ipsec_srvr_cert_id = "Server Certificate identity incorrect"; 164const char *vpn_gen_err = "Generic Error"; 165const char *vpn_no_srvr_addr = "No Server Address"; 166const char *vpn_no_cert = "No Certificate"; 167const char *vpn_dns_err = "Resolve Address Error"; 168const char *vpn_no_local = "No Local Network"; 169const char *vpn_cfg_err = "Configuration Error"; 170const char *vpn_ctrl_err = "Control Error"; 171const char *vpn_conn_err = "Connection Error"; 172const char *vpn_net_chg = "Network Change"; 173const char *vpn_peer_disco = "Peer Disconnect"; 174const char *vpn_peer_dead = "Peer Dead"; 175const char *vpn_peer_unresp = "Peer not responding"; 176const char *vpn_nego_err = "Negotiation Error"; 177const char *vpn_xauth_err = "Xauth Error"; 178const char *vpn_edge_err = "Edge Activation Error"; 179const char *vpn_idle_tmo = "Idle Timeout"; 180const char *vpn_addr_invalid = "Address invalid"; 181const char *vpn_ap_req = "AP required"; 182const char *vpn_cli_cert_pre = "Client Certificate premature"; 183const char *vpn_cli_cert_exp = "Client Certificate expired"; 184const char *vpn_srvr_cert_pre = "Server Certificate premature"; 185const char *vpn_srvr_cert_exp = "Server Certificate expired"; 186const char *vpn_srvr_cert_id = "Server Certificate identity incorrect"; 187const char *vpn_plugin_upd = "Plugin update required"; 188const char *vpn_plugin_dis = "Plugin disabled"; 189 190 191 192/* ----------------------------------------------------------------------------- 193 Given a string 'key' and a string prefix 'prefix', 194 return the next component in the slash '/' separated 195 key. If no slash follows the prefix, return NULL. 196 197 Examples: 198 1. key = "a/b/c" prefix = "a/" returns "b" 199 2. key = "a/b/c" prefix = "a/b/" returns NULL 200----------------------------------------------------------------------------- */ 201CFStringRef parse_component(CFStringRef key, CFStringRef prefix) 202{ 203 CFMutableStringRef comp; 204 CFRange range; 205 206 if (!CFStringHasPrefix(key, prefix)) 207 return NULL; 208 209 comp = CFStringCreateMutableCopy(NULL, 0, key); 210 CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix))); 211 range = CFStringFind(comp, CFSTR("/"), 0); 212 if (range.location == kCFNotFound) { 213 CFRelease(comp); 214 return NULL; 215 } 216 range.length = CFStringGetLength(comp) - range.location; 217 CFStringDelete(comp, range); 218 return comp; 219} 220 221/* ----------------------------------------------------------------------------- 222----------------------------------------------------------------------------- */ 223CFDictionaryRef copyService(SCDynamicStoreRef store, CFStringRef domain, CFStringRef serviceID) 224{ 225 CFTypeRef data = NULL; 226 CFMutableDictionaryRef service = NULL; 227 CFStringRef key = NULL; 228 int i; 229 CFStringRef copy[] = { 230 kSCEntNetPPP, 231 kSCEntNetModem, 232 kSCEntNetInterface, 233 kSCEntNetIPv4, 234 kSCEntNetIPv6, 235#if !TARGET_OS_EMBEDDED 236 kSCEntNetSMB, 237#endif 238 kSCEntNetDNS, 239 kSCEntNetL2TP, 240 kSCEntNetPPTP, 241 kSCEntNetIPSec, 242 NULL, 243 }; 244 245 key = SCDynamicStoreKeyCreate(0, CFSTR("%@/%@/%@/%@"), domain, kSCCompNetwork, kSCCompService, serviceID); 246 if (key == 0) 247 goto fail; 248 249 data = SCDynamicStoreCopyValue(store, key); 250 if (data == 0) { 251 data = CFDictionaryCreate(NULL, 0, 0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 252 if (data == 0) 253 goto fail; 254 } 255 256 CFRelease(key); 257 key = NULL; 258 259 service = CFDictionaryCreateMutableCopy(NULL, 0, data); 260 if (service == 0) 261 goto fail; 262 263 CFRelease(data); 264 265 for (i = 0; copy[i]; i++) { 266 data = copyEntity(store, domain, serviceID, copy[i]); 267 if (data) { 268 269 CFDictionaryAddValue(service, copy[i], data); 270 CFRelease(data); 271 } 272 } 273 274 return service; 275 276fail: 277 if (key) 278 CFRelease(key); 279 if (data) 280 CFRelease(data); 281 if (service) 282 CFRelease(service); 283 return 0; 284} 285 286/* ----------------------------------------------------------------------------- 287----------------------------------------------------------------------------- */ 288CFDictionaryRef copyEntity(SCDynamicStoreRef store, CFStringRef domain, CFStringRef serviceID, CFStringRef entity) 289{ 290 CFTypeRef data = NULL; 291 CFStringRef key; 292 293 if (serviceID) 294 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, domain, serviceID, entity); 295 else 296 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(0, domain, entity); 297 298 if (key) { 299 data = SCDynamicStoreCopyValue(store, key); 300 CFRelease(key); 301 } 302 return data; 303} 304 305/* ----------------------------------------------------------------------------- 306----------------------------------------------------------------------------- */ 307int existEntity(SCDynamicStoreRef store, CFStringRef domain, CFStringRef serviceID, CFStringRef entity) 308{ 309 CFTypeRef data; 310 311 data = copyEntity(store, domain, serviceID, entity); 312 if (data) { 313 CFRelease(data); 314 return 1; 315 } 316 317 return 0; 318} 319 320/* ----------------------------------------------------------------------------- 321get a string from the dictionnary, in service/property 322----------------------------------------------------------------------------- */ 323int getString(CFDictionaryRef service, CFStringRef property, u_char *str, u_int16_t maxlen) 324{ 325 CFStringRef string; 326 CFDataRef ref; 327 const UInt8 *dataptr; 328 int len; 329 330 str[0] = 0; 331 ref = CFDictionaryGetValue(service, property); 332 if (ref) { 333 if (CFGetTypeID(ref) == CFStringGetTypeID()) { 334 CFStringGetCString((CFStringRef)ref, (char*)str, maxlen, kCFStringEncodingUTF8); 335 return 1; 336 } 337 else if (CFGetTypeID(ref) == CFDataGetTypeID()) { 338 CFStringEncoding encoding; 339 340 if ((len = CFDataGetLength(ref)) && (dataptr = CFDataGetBytePtr(ref))){ 341#if __BIG_ENDIAN__ 342 encoding = (*(dataptr + 1) == 0x00) ? kCFStringEncodingUTF16LE : kCFStringEncodingUTF16BE; 343#else // __LITTLE_ENDIAN__ 344 encoding = (*dataptr == 0x00) ? kCFStringEncodingUTF16BE : kCFStringEncodingUTF16LE; 345#endif 346 string = CFStringCreateWithBytes(NULL, (const UInt8 *)dataptr, len, encoding, FALSE); 347 if (string) { 348 CFStringGetCString((CFStringRef)string, (char*)str, maxlen, kCFStringEncodingUTF8); 349 CFRelease(string); 350 return 1; 351 } 352 } 353 } 354 } 355 return 0; 356} 357 358/* ----------------------------------------------------------------------------- 359get a number from the dictionnary, in service/property 360----------------------------------------------------------------------------- */ 361int getNumber(CFDictionaryRef dict, CFStringRef property, u_int32_t *outval) 362{ 363 CFNumberRef ref; 364 365 ref = CFDictionaryGetValue(dict, property); 366 if (ref && (CFGetTypeID(ref) == CFNumberGetTypeID())) { 367 CFNumberGetValue(ref, kCFNumberSInt32Type, outval); 368 return 1; 369 } 370 return 0; 371} 372 373/* ----------------------------------------------------------------------------- 374----------------------------------------------------------------------------- */ 375int getNumberFromEntity(SCDynamicStoreRef store, CFStringRef domain, CFStringRef serviceID, 376 CFStringRef entity, CFStringRef property, u_int32_t *outval) 377{ 378 CFTypeRef data; 379 int ok = 0; 380 381 if ((data = copyEntity(store, domain, serviceID, entity))) { 382 ok = getNumber(data, property, outval); 383 CFRelease(data); 384 } 385 return ok; 386} 387 388/* ----------------------------------------------------------------------------- 389----------------------------------------------------------------------------- */ 390int getStringFromEntity(SCDynamicStoreRef store, CFStringRef domain, CFStringRef serviceID, 391 CFStringRef entity, CFStringRef property, u_char *str, u_int16_t maxlen) 392{ 393 CFTypeRef data; 394 int ok = 0; 395 396 data = copyEntity(store, domain, serviceID, entity); 397 if (data) { 398 ok = getString(data, property, str, maxlen); 399 CFRelease(data); 400 } 401 return ok; 402} 403 404/* ----------------------------------------------------------------------------- 405----------------------------------------------------------------------------- */ 406CFStringRef copyCFStringFromEntity(SCDynamicStoreRef store, CFStringRef domain, CFStringRef serviceID, 407 CFStringRef entity, CFStringRef property) 408{ 409 CFTypeRef data; 410 CFStringRef string, ret = 0; 411 412 data = copyEntity(store, domain, serviceID, entity); 413 if (data) { 414 string = CFDictionaryGetValue(data, property); 415 if (string && (CFGetTypeID(string) == CFStringGetTypeID())) { 416 CFRetain(string); 417 ret = string; 418 } 419 420 CFRelease(data); 421 } 422 return ret; 423} 424 425/* ----------------------------------------------------------------------------- 426----------------------------------------------------------------------------- */ 427u_int32_t CFStringAddrToLong(CFStringRef string) 428{ 429 char str[100]; 430 u_int32_t ret = 0; 431 432 if (string) { 433 str[0] = 0; 434 CFStringGetCString(string, str, sizeof(str), kCFStringEncodingMacRoman); 435 ret = ntohl(inet_addr(str)); 436 } 437 return ret; 438} 439 440/* ----------------------------------------------------------------------------- 441----------------------------------------------------------------------------- */ 442int getAddressFromEntity(SCDynamicStoreRef store, CFStringRef domain, CFStringRef serviceID, 443 CFStringRef entity, CFStringRef property, u_int32_t *outval) 444{ 445 CFTypeRef data; 446 int ok = 0; 447 CFArrayRef array; 448 449 data = copyEntity(store, domain, serviceID, entity); 450 if (data) { 451 array = CFDictionaryGetValue(data, property); 452 if (array && CFArrayGetCount(array)) { 453 *outval = CFStringAddrToLong(CFArrayGetValueAtIndex(array, 0)); 454 ok = 1; 455 } 456 CFRelease(data); 457 } 458 return ok; 459} 460 461/* ----------------------------------------------------------------------------- 462----------------------------------------------------------------------------- */ 463Boolean my_CFEqual(CFTypeRef obj1, CFTypeRef obj2) 464{ 465 if (obj1 == NULL && obj2 == NULL) 466 return true; 467 else if (obj1 == NULL || obj2 == NULL) 468 return false; 469 470 return CFEqual(obj1, obj2); 471} 472 473/* ----------------------------------------------------------------------------- 474----------------------------------------------------------------------------- */ 475void my_CFRelease(void *t) 476{ 477 void * * obj = (void * *)t; 478 if (obj && *obj) { 479 CFRelease(*obj); 480 *obj = NULL; 481 } 482 return; 483} 484 485/* ----------------------------------------------------------------------------- 486----------------------------------------------------------------------------- */ 487void my_close(int fd) 488{ 489 if (fd != -1) 490 close(fd); 491} 492 493/* ----------------------------------------------------------------------------- 494----------------------------------------------------------------------------- */ 495CFTypeRef my_CFRetain(CFTypeRef obj) 496{ 497 if (obj) 498 CFRetain(obj); 499 return obj; 500} 501 502/* ----------------------------------------------------------------------------- 503----------------------------------------------------------------------------- */ 504Boolean isDictionary (CFTypeRef obj) 505{ 506 return (obj && CFGetTypeID(obj) == CFDictionaryGetTypeID()); 507} 508 509/* ----------------------------------------------------------------------------- 510----------------------------------------------------------------------------- */ 511Boolean isArray (CFTypeRef obj) 512{ 513 return (obj && CFGetTypeID(obj) == CFArrayGetTypeID()); 514} 515 516/* ----------------------------------------------------------------------------- 517----------------------------------------------------------------------------- */ 518Boolean isString (CFTypeRef obj) 519{ 520 return (obj && CFGetTypeID(obj) == CFStringGetTypeID()); 521} 522 523/* ----------------------------------------------------------------------------- 524----------------------------------------------------------------------------- */ 525Boolean isNumber (CFTypeRef obj) 526{ 527 return (obj && CFGetTypeID(obj) == CFNumberGetTypeID()); 528} 529 530/* ----------------------------------------------------------------------------- 531----------------------------------------------------------------------------- */ 532Boolean isData (CFTypeRef obj) 533{ 534 return (obj && CFGetTypeID(obj) == CFDataGetTypeID()); 535} 536 537 538/* ----------------------------------------------------------------------------- 539----------------------------------------------------------------------------- */ 540void AddNumber(CFMutableDictionaryRef dict, CFStringRef property, u_int32_t number) 541{ 542 CFNumberRef num; 543 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &number); 544 if (num) { 545 CFDictionaryAddValue(dict, property, num); 546 CFRelease(num); 547 } 548} 549 550/* ----------------------------------------------------------------------------- 551----------------------------------------------------------------------------- */ 552void AddNumber64(CFMutableDictionaryRef dict, CFStringRef property, u_int64_t number) 553{ 554 CFNumberRef num; 555 num = CFNumberCreate(NULL, kCFNumberSInt64Type, &number); 556 if (num) { 557 CFDictionaryAddValue(dict, property, num); 558 CFRelease(num); 559 } 560} 561 562/* ----------------------------------------------------------------------------- 563----------------------------------------------------------------------------- */ 564void AddString(CFMutableDictionaryRef dict, CFStringRef property, char *string) 565{ 566 CFStringRef str; 567 str = CFStringCreateWithCString(NULL, string, kCFStringEncodingUTF8); 568 if (str) { 569 CFDictionaryAddValue(dict, property, str); 570 CFRelease(str); 571 } 572} 573 574/* ----------------------------------------------------------------------------- 575----------------------------------------------------------------------------- */ 576void AddNumberFromState(SCDynamicStoreRef store, CFStringRef serviceID, CFStringRef entity, CFStringRef property, CFMutableDictionaryRef dict) 577{ 578 u_int32_t lval; 579 580 if (getNumberFromEntity(store, kSCDynamicStoreDomainState, serviceID, entity, property, &lval)) 581 AddNumber(dict, property, lval); 582} 583 584/* ----------------------------------------------------------------------------- 585----------------------------------------------------------------------------- */ 586void AddStringFromState(SCDynamicStoreRef store, CFStringRef serviceID, CFStringRef entity, CFStringRef property, CFMutableDictionaryRef dict) 587{ 588 CFStringRef string; 589 590 if ((string = copyCFStringFromEntity(store, kSCDynamicStoreDomainState, serviceID, entity, property))) { 591 CFDictionaryAddValue(dict, property, string); 592 CFRelease(string); 593 } 594} 595 596/* ------------------------------------------------------------------------------------------- 597------------------------------------------------------------------------------------------- */ 598CFDataRef Serialize(CFPropertyListRef obj, void **data, u_int32_t *dataLen) 599{ 600 CFDataRef xml; 601 602 xml = CFPropertyListCreateXMLData(NULL, obj); 603 if (xml) { 604 *data = (void*)CFDataGetBytePtr(xml); 605 *dataLen = CFDataGetLength(xml); 606 } 607 return xml; 608} 609 610/* ------------------------------------------------------------------------------------------- 611------------------------------------------------------------------------------------------- */ 612CFPropertyListRef Unserialize(void *data, u_int32_t dataLen) 613{ 614 CFDataRef xml; 615 CFPropertyListRef ref = 0; 616 617 xml = CFDataCreate(NULL, data, dataLen); 618 if (xml) { 619 ref = CFPropertyListCreateFromXMLData(NULL, 620 xml, kCFPropertyListImmutable, NULL); 621 CFRelease(xml); 622 } 623 624 return ref; 625} 626 627/* ----------------------------------------------------------------------------- 628----------------------------------------------------------------------------- */ 629void *my_Allocate(int size) 630{ 631 void *addr; 632 kern_return_t status; 633 634 status = vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, TRUE); 635 if (status != KERN_SUCCESS) { 636 return 0; 637 } 638 639 return addr; 640} 641 642/* ----------------------------------------------------------------------------- 643----------------------------------------------------------------------------- */ 644void my_Deallocate(void * addr, int size) 645{ 646 kern_return_t status; 647 648 if (addr == 0) 649 return; 650 651 status = vm_deallocate(mach_task_self(), (vm_address_t)addr, size); 652 if (status != KERN_SUCCESS) { 653 } 654 655 return; 656} 657 658// ---------------------------------------------------------------------------- 659// GetIntFromDict 660// ---------------------------------------------------------------------------- 661Boolean GetIntFromDict (CFDictionaryRef dict, CFStringRef property, u_int32_t *outval, u_int32_t defaultval) 662{ 663 CFNumberRef ref; 664 665 ref = CFDictionaryGetValue(dict, property); 666 if (isNumber(ref) 667 && CFNumberGetValue(ref, kCFNumberSInt32Type, outval)) 668 return TRUE; 669 670 *outval = defaultval; 671 return FALSE; 672} 673 674// ---------------------------------------------------------------------------- 675// GetStrFromDict 676// ---------------------------------------------------------------------------- 677int GetStrFromDict (CFDictionaryRef dict, CFStringRef property, char *outstr, int maxlen, char *defaultval) 678{ 679 CFStringRef ref; 680 681 ref = CFDictionaryGetValue(dict, property); 682 if (!isString(ref) 683 || !CFStringGetCString(ref, outstr, maxlen, kCFStringEncodingUTF8)) 684 strncpy(outstr, defaultval, maxlen); 685 686 return strlen(outstr); 687} 688 689// ---------------------------------------------------------------------------- 690// GetStrAddrFromDict 691// ---------------------------------------------------------------------------- 692Boolean GetStrAddrFromDict (CFDictionaryRef dict, CFStringRef property, char *outstr, int maxlen) 693{ 694 CFStringRef ref; 695 in_addr_t addr; 696 697 ref = CFDictionaryGetValue(dict, property); 698 if (isString(ref) 699 && CFStringGetCString(ref, outstr, maxlen, kCFStringEncodingUTF8)) { 700 addr = inet_addr(outstr); 701 return addr != INADDR_NONE; 702 } 703 704 return FALSE; 705} 706 707// ---------------------------------------------------------------------------- 708// GetStrNetFromDict 709// ---------------------------------------------------------------------------- 710Boolean GetStrNetFromDict (CFDictionaryRef dict, CFStringRef property, char *outstr, int maxlen) 711{ 712 CFStringRef ref; 713 in_addr_t net; 714 715 ref = CFDictionaryGetValue(dict, property); 716 if (isString(ref) 717 && CFStringGetCString(ref, outstr, maxlen, kCFStringEncodingUTF8)) { 718 net = inet_network(outstr); 719 return net != INADDR_NONE;// && net != 0; 720 } 721 722 return FALSE; 723} 724 725 726 727/* ----------------------------------------------------------------------------- 728publish a dictionnary entry in the cache, given a key 729----------------------------------------------------------------------------- */ 730int publish_keyentry(SCDynamicStoreRef store, CFStringRef key, CFStringRef entry, CFTypeRef value) 731{ 732 CFMutableDictionaryRef dict; 733 CFPropertyListRef ref; 734 735 if ((ref = SCDynamicStoreCopyValue(store, key))) { 736 dict = CFDictionaryCreateMutableCopy(0, 0, ref); 737 CFRelease(ref); 738 } 739 else 740 dict = CFDictionaryCreateMutable(0, 0, 741 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 742 743 if (dict == 0) 744 return 0; 745 746 CFDictionarySetValue(dict, entry, value); 747 SCDynamicStoreSetValue(store, key, dict); 748 CFRelease(dict); 749 750 return 1; 751 } 752/* ----------------------------------------------------------------------------- 753unpublish a dictionnary entry from the cache, given the dict key 754----------------------------------------------------------------------------- */ 755int unpublish_keyentry(SCDynamicStoreRef store, CFStringRef key, CFStringRef entry) 756{ 757 CFMutableDictionaryRef dict; 758 CFPropertyListRef ref; 759 760 if ((ref = SCDynamicStoreCopyValue(store, key))) { 761 if ((dict = CFDictionaryCreateMutableCopy(0, 0, ref))) { 762 CFDictionaryRemoveValue(dict, entry); 763 SCDynamicStoreSetValue(store, key, dict); 764 CFRelease(dict); 765 } 766 CFRelease(ref); 767 } 768 return 0; 769} 770 771 772/* ----------------------------------------------------------------------------- 773publish a numerical entry in the cache, given a dictionary 774----------------------------------------------------------------------------- */ 775int publish_dictnumentry(SCDynamicStoreRef store, CFStringRef serviceID, CFStringRef dict, CFStringRef entry, int val) 776{ 777 int ret = ENOMEM; 778 CFNumberRef num; 779 CFStringRef key; 780 781 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceID, dict); 782 if (key) { 783 num = CFNumberCreate(NULL, kCFNumberIntType, &val); 784 if (num) { 785 ret = publish_keyentry(store, key, entry, num); 786 CFRelease(num); 787 ret = 0; 788 } 789 CFRelease(key); 790 } 791 return ret; 792} 793 794 795/* ----------------------------------------------------------------------------- 796 unpublish a dictionnary entry from the cache, given the dict name 797 ----------------------------------------------------------------------------- */ 798int unpublish_dictentry(SCDynamicStoreRef store, CFStringRef serviceID, CFStringRef dict, CFStringRef entry) 799{ 800 int ret = ENOMEM; 801 CFStringRef key; 802 803 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceID, dict); 804 if (key) { 805 ret = unpublish_keyentry(store, key, entry); 806 CFRelease(key); 807 ret = 0; 808 } 809 return ret; 810} 811 812/* ----------------------------------------------------------------------------- 813 publishes multiple dictionaries to the cache, given the dict names and the dicts. Indices must match up exactly 814 ----------------------------------------------------------------------------- */ 815int publish_multiple_dicts(SCDynamicStoreRef store, CFStringRef serviceID, CFArrayRef dictNames, CFArrayRef dicts) 816{ 817 CFDictionaryRef dict = NULL; 818 CFStringRef dictName = NULL; 819 int i; 820 CFStringRef key; 821 CFMutableDictionaryRef keys_to_add; 822 int numDicts; 823 int ret = ENOMEM; 824 825 if (!store) 826 return -1; 827 828 /* Check arrays */ 829 if (!dictNames || !dicts) 830 return -1; 831 832 /* Verify sizes */ 833 numDicts = CFArrayGetCount(dictNames); 834 if (numDicts != CFArrayGetCount(dicts)) 835 return -1; 836 837 keys_to_add = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 838 839 for (i = 0; i < numDicts; i++) { 840 dictName = CFArrayGetValueAtIndex(dictNames, i); 841 dict = CFArrayGetValueAtIndex(dicts, i); 842 if (isA_CFString(dictName) && isA_CFDictionary(dict)) { 843 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceID, dictName); 844 if (key) { 845 CFDictionaryAddValue(keys_to_add, key, dict); 846 CFRelease(key); 847 } 848 } 849 } 850 851 SCDynamicStoreSetMultiple(store, keys_to_add, NULL, NULL); 852 853 my_CFRelease(&keys_to_add); 854 855 return ret; 856} 857 858/* ----------------------------------------------------------------------------- 859 unpublish a dictionnary entry from the cache, given the dict name 860 ----------------------------------------------------------------------------- */ 861int unpublish_dict(SCDynamicStoreRef store, CFStringRef serviceID, CFStringRef dict) 862{ 863 int ret = ENOMEM; 864 CFStringRef key; 865 866 if (!store) 867 return -1; 868 869 if (dict) 870 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceID, dict); 871 else 872 key = SCDynamicStoreKeyCreate(0, CFSTR("%@/%@/%@/%@"), kSCDynamicStoreDomainState, kSCCompNetwork, kSCCompService, serviceID); 873 if (key) { 874 SCDynamicStoreRemoveValue(store, key); 875 CFRelease(key); 876 ret = 0; 877 } 878 879 return ret; 880} 881 882/* ----------------------------------------------------------------------------- 883 unpublish multiple dictionary entries from the cache, given an array of dict names 884 ----------------------------------------------------------------------------- */ 885int unpublish_multiple_dicts(SCDynamicStoreRef store, CFStringRef serviceID, CFArrayRef dictNames, Boolean removeService) 886{ 887 CFStringRef dictName = NULL; 888 int i; 889 CFStringRef key; 890 CFMutableArrayRef keys_to_remove; 891 int numDictNames; 892 int ret = ENOMEM; 893 894 if (!store) 895 return -1; 896 897 keys_to_remove = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 898 899 if (dictNames) { 900 numDictNames = CFArrayGetCount(dictNames); 901 for (i = 0; i < numDictNames; i++) { 902 dictName = CFArrayGetValueAtIndex(dictNames, i); 903 if (isA_CFString(dictName)) { 904 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceID, dictName); 905 if (key) { 906 CFArrayAppendValue(keys_to_remove, key); 907 CFRelease(key); 908 } 909 } 910 } 911 } 912 913 if (removeService) { 914 key = SCDynamicStoreKeyCreate(0, CFSTR("%@/%@/%@/%@"), kSCDynamicStoreDomainState, kSCCompNetwork, kSCCompService, serviceID); 915 if (key) { 916 CFArrayAppendValue(keys_to_remove, key); 917 CFRelease(key); 918 } 919 } 920 921 SCDynamicStoreSetMultiple(store, NULL, keys_to_remove, NULL); 922 923 my_CFRelease(&keys_to_remove); 924 925 return ret; 926} 927 928/* ----------------------------------------------------------------------------- 929publish a string entry in the cache, given a dictionary 930----------------------------------------------------------------------------- */ 931int publish_dictstrentry(SCDynamicStoreRef store, CFStringRef serviceID, CFStringRef dict, CFStringRef entry, char *str, int encoding) 932{ 933 934 int ret = ENOMEM; 935 CFStringRef ref; 936 CFStringRef key; 937 938 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceID, dict); 939 if (key) { 940 ref = CFStringCreateWithCString(NULL, str, encoding); 941 if (ref) { 942 ret = publish_keyentry(store, key, entry, ref); 943 CFRelease(ref); 944 ret = 0; 945 } 946 CFRelease(key); 947 } 948 return ret; 949} 950 951/* ----------------------------------------------------------------------------- 952 return f s CFString contains an IP address 953 ----------------------------------------------------------------------------- */ 954int 955cfstring_is_ip(CFStringRef str) 956{ 957 char *buf; 958 struct in_addr ip = { 0 }; 959 CFIndex l; 960 int n, result; 961 CFRange range; 962 963 if (!isString(str) || (l = CFStringGetLength(str)) == 0) 964 return 0; 965 966 buf = malloc(l+1); 967 if (buf == NULL) { 968 SCLog(TRUE, LOG_ERR, CFSTR("Failed to allocate memory")); 969 return 0; 970 } 971 972 range = CFRangeMake(0, l); 973 n = CFStringGetBytes(str, range, kCFStringEncodingMacRoman, 974 0, FALSE, (UInt8 *)buf, l, &l); 975 buf[l] = '\0'; 976 977 result = inet_aton(buf, &ip); 978 free(buf); 979 return result; 980} 981 982/* ----------------------------------------------------------------------------- 983 ----------------------------------------------------------------------------- */ 984CFStringRef 985copyPrimaryService (SCDynamicStoreRef store) 986{ 987 CFDictionaryRef dict; 988 CFStringRef key; 989 CFStringRef primary = NULL; 990 991 if ((key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, 992 kSCDynamicStoreDomainState, 993 kSCEntNetIPv4)) == NULL) { 994 return NULL; 995 } 996 997 dict = SCDynamicStoreCopyValue(store, key); 998 CFRelease(key); 999 if (isA_CFDictionary(dict)) { 1000 primary = CFDictionaryGetValue(dict, 1001 kSCDynamicStorePropNetPrimaryService); 1002 1003 primary = isA_CFString(primary); 1004 if (primary) 1005 CFRetain(primary); 1006 } 1007 if (dict != NULL) { 1008 CFRelease(dict); 1009 } 1010 return primary; 1011} 1012 1013/* ----------------------------------------------------------------------------- 1014 ----------------------------------------------------------------------------- */ 1015Boolean UpdatePasswordPrefs(CFStringRef serviceID, CFStringRef interfaceType, SCNetworkInterfacePasswordType passwordType, 1016 CFStringRef passwordEncryptionKey, CFStringRef passwordEncryptionValue, CFStringRef logTitle) 1017{ 1018 SCPreferencesRef prefs = NULL; 1019 SCNetworkServiceRef service = NULL; 1020 SCNetworkInterfaceRef interface = NULL; 1021 CFMutableDictionaryRef newConfig = NULL; 1022 CFDictionaryRef config; 1023 Boolean ok, locked = FALSE, success = FALSE; 1024 1025 prefs = SCPreferencesCreate(NULL, CFSTR("UpdatePassword"), NULL); 1026 if (prefs == NULL) { 1027 SCLog(TRUE, LOG_ERR, CFSTR("%@: SCPreferencesCreate fails"), logTitle); 1028 goto done; 1029 } 1030 // lock the prefs 1031 ok = SCPreferencesLock(prefs, TRUE); 1032 if (!ok) { 1033 SCLog(TRUE, LOG_ERR, CFSTR("%@: SCPreferencesLock fails"), logTitle); 1034 goto done; 1035 } 1036 1037 locked = TRUE; 1038 1039 // get the service 1040 service = SCNetworkServiceCopy(prefs, serviceID); 1041 if (service == NULL) { 1042 SCLog(TRUE, LOG_ERR, CFSTR("%@: SCNetworkServiceCopy fails"), logTitle); 1043 goto done; 1044 } 1045 // get the interface associated with the service 1046 interface = SCNetworkServiceGetInterface(service); 1047 if ((interface == NULL) || !CFEqual(SCNetworkInterfaceGetInterfaceType(interface), interfaceType)) { 1048 SCLog(TRUE, LOG_ERR, CFSTR("%@: interface not %@"), logTitle, interfaceType); 1049 goto done; 1050 } 1051 1052 // remove any current password (from the system keychain) 1053 if (SCNetworkInterfaceCheckPassword(interface, passwordType)) { 1054 // if password current associated with this interface 1055 ok = SCNetworkInterfaceRemovePassword(interface, passwordType); 1056 if (!ok) { 1057 SCLog(TRUE, LOG_ERR, CFSTR("%@: SCNetworkInterfaceRemovePassword fails"), logTitle); 1058 } 1059 } 1060 1061 // update passworEncryptionKey 1062 config = SCNetworkInterfaceGetConfiguration(interface); 1063 1064 if (config != NULL) { 1065 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 1066 } 1067 else { 1068 newConfig = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1069 } 1070 1071 if (newConfig == NULL) { 1072 SCLog(TRUE, LOG_ERR, CFSTR("%@: cannot allocate new interface configuration"), logTitle); 1073 goto done; 1074 } 1075 1076 if (passwordEncryptionValue) { 1077 CFDictionarySetValue(newConfig, passwordEncryptionKey, passwordEncryptionValue); 1078 } else { 1079 CFDictionaryRemoveValue( newConfig, passwordEncryptionKey); 1080 } 1081 1082 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig); 1083 if ( !ok ) { 1084 SCLog(TRUE, LOG_ERR, CFSTR("%@: SCNetworkInterfaceSetConfiguration fails"), logTitle); 1085 goto done; 1086 } 1087 1088 // commit & apply the changes 1089 ok = SCPreferencesCommitChanges(prefs); 1090 if (!ok) { 1091 SCLog(TRUE, LOG_ERR, CFSTR("%@: SCPreferencesCommitChanges fails"), logTitle); 1092 goto done; 1093 } 1094 ok = SCPreferencesApplyChanges(prefs); 1095 if (!ok) { 1096 SCLog(TRUE, LOG_ERR, CFSTR("%@: SCPreferencesApplyChanges fails"), logTitle); 1097 goto done; 1098 } 1099 1100 success = TRUE; 1101 1102 done : 1103 if (newConfig!= NULL) { 1104 CFRelease(newConfig); 1105 } 1106 if (service != NULL) { 1107 CFRelease(service); 1108 } 1109 if (locked) { 1110 SCPreferencesUnlock(prefs); 1111 } 1112 if (prefs != NULL) { 1113 CFRelease(prefs); 1114 } 1115 return success; 1116} 1117 1118 1119/* ----------------------------------------------------------------------------- 1120set the sa_family field of a struct sockaddr, if it exists. 1121----------------------------------------------------------------------------- */ 1122#define SET_SA_FAMILY(addr, family) \ 1123 bzero((char *) &(addr), sizeof(addr)); \ 1124 addr.sa_family = (family); \ 1125 addr.sa_len = sizeof(addr); 1126 1127/* ----------------------------------------------------------------------------- 1128Config the interface MTU 1129----------------------------------------------------------------------------- */ 1130int set_ifmtu(char *ifname, int mtu) 1131{ 1132 struct ifreq ifr; 1133 int ip_sockfd; 1134 1135 ip_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 1136 if (ip_sockfd < 0) { 1137 syslog(LOG_INFO, "sifmtu: cannot create ip socket, %s", 1138 strerror(errno)); 1139 return 0; 1140 } 1141 1142 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 1143 ifr.ifr_mtu = mtu; 1144 ioctl(ip_sockfd, SIOCSIFMTU, (caddr_t) &ifr); 1145 1146 close(ip_sockfd); 1147 return 1; 1148} 1149 1150/* ----------------------------------------------------------------------------- 1151Config the interface IP addresses and netmask 1152----------------------------------------------------------------------------- */ 1153int set_ifaddr(char *ifname, u_int32_t o, u_int32_t h, u_int32_t m) 1154{ 1155 struct ifaliasreq ifra __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 1156 int ip_sockfd; 1157 1158 ip_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 1159 if (ip_sockfd < 0) { 1160 syslog(LOG_INFO, "sifaddr: cannot create ip socket, %s", 1161 strerror(errno)); 1162 return 0; 1163 } 1164 1165 strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); 1166 1167 SET_SA_FAMILY(ifra.ifra_addr, AF_INET); 1168 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; 1169 1170 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); 1171 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; 1172 1173 if (m != 0) { 1174 SET_SA_FAMILY(ifra.ifra_mask, AF_INET); 1175 (ALIGNED_CAST(struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m; 1176 } 1177 else 1178 bzero(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); 1179 1180 if (ioctl(ip_sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) { 1181 if (errno != EEXIST) { 1182 //error("Couldn't set interface address: %m"); 1183 close(ip_sockfd); 1184 return 0; 1185 } 1186 //warning("Couldn't set interface address: Address %I already exists", o); 1187 } 1188 1189 close(ip_sockfd); 1190 return 1; 1191} 1192 1193/* ----------------------------------------------------------------------------- 1194Clear the interface IP addresses, and delete routes 1195 * through the interface if possible 1196 ----------------------------------------------------------------------------- */ 1197int clear_ifaddr(char *ifname, u_int32_t o, u_int32_t h) 1198{ 1199 struct ifreq ifr __attribute__ ((aligned (4))); // Wcast-align fix - force alignment 1200 int ip_sockfd; 1201 1202 ip_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 1203 if (ip_sockfd < 0) { 1204 syslog(LOG_INFO, "cifaddr: cannot create ip socket, %s", 1205 strerror(errno)); 1206 return 0; 1207 } 1208 1209 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1210 SET_SA_FAMILY(ifr.ifr_ifru.ifru_addr, AF_INET); 1211 (ALIGNED_CAST(struct sockaddr_in *) &ifr.ifr_ifru.ifru_addr)->sin_addr.s_addr = o; 1212 if (ioctl(ip_sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { 1213 close(ip_sockfd); 1214 return 0; 1215 } 1216 1217 close(ip_sockfd); 1218 return 1; 1219} 1220 1221/* ----------------------------------------------------------------------------- 1222----------------------------------------------------------------------------- */ 1223void 1224in6_len2mask(struct in6_addr *mask, int len) 1225{ 1226 int i; 1227 1228 bzero(mask, sizeof(*mask)); 1229 for (i = 0; i < len / 8; i++) 1230 mask->s6_addr[i] = 0xff; 1231 if (len % 8) 1232 mask->s6_addr[i] = (0xff00 >> (len % 8)) & 0xff; 1233} 1234 1235/* ----------------------------------------------------------------------------- 1236mask address according to the mask 1237----------------------------------------------------------------------------- */ 1238void 1239in6_maskaddr(struct in6_addr *addr, struct in6_addr *mask) 1240{ 1241 int i; 1242 1243 for (i = 0; i < sizeof(struct in6_addr); i++) 1244 addr->s6_addr[i] &= mask->s6_addr[i]; 1245} 1246 1247/* ----------------------------------------------------------------------------- 1248----------------------------------------------------------------------------- */ 1249void 1250in6_addr2net(struct in6_addr *addr, int prefix, struct in6_addr *net) { 1251 1252 struct in6_addr mask; 1253 int i; 1254 1255 in6_len2mask(&mask, prefix); 1256 1257 for (i = 0; i < sizeof(mask.s6_addr); i++) 1258 (*net).s6_addr[i] = (*addr).s6_addr[i] & (mask).s6_addr[i]; 1259 1260} 1261 1262/* ----------------------------------------------------------------------------- 1263Config the interface IPv6 addresses 1264ll_addr must be a 64 bits address. 1265----------------------------------------------------------------------------- */ 1266int set_ifaddr6 (char *ifname, struct in6_addr *addr, int prefix) 1267{ 1268 int s; 1269 struct in6_aliasreq addreq6; 1270 struct in6_addr mask; 1271 1272 s = socket(AF_INET6, SOCK_DGRAM, 0); 1273 if (s < 0) { 1274 syslog(LOG_ERR, "set_ifaddr6: can't create IPv6 socket, %s", 1275 strerror(errno)); 1276 return 0; 1277 } 1278 1279 memset(&addreq6, 0, sizeof(addreq6)); 1280 strlcpy(addreq6.ifra_name, ifname, sizeof(addreq6.ifra_name)); 1281 1282 /* my addr */ 1283 addreq6.ifra_addr.sin6_family = AF_INET6; 1284 addreq6.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); 1285 memcpy(&addreq6.ifra_addr.sin6_addr, addr, sizeof(struct in6_addr)); 1286 1287 /* prefix mask: 128bit */ 1288 addreq6.ifra_prefixmask.sin6_family = AF_INET6; 1289 addreq6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 1290 in6_len2mask(&mask, prefix); 1291 memcpy(&addreq6.ifra_prefixmask.sin6_addr, &mask, sizeof(struct in6_addr)); 1292 1293 /* address lifetime (infty) */ 1294 addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 1295 addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 1296 1297 if (IN6_IS_ADDR_LINKLOCAL(addr)) { 1298 if (ioctl(s, SIOCLL_START, &addreq6) < 0) { 1299 syslog(LOG_ERR, "set_ifaddr6: can't set link-local IPv6 address, %s", 1300 strerror(errno)); 1301 close(s); 1302 return 0; 1303 } 1304 } else { 1305 if (ioctl(s, SIOCAIFADDR_IN6, &addreq6) < 0) { 1306 syslog(LOG_ERR, "set_ifaddr6: can't set IPv6 address, %s", 1307 strerror(errno)); 1308 close(s); 1309 return 0; 1310 } 1311 } 1312 1313 close(s); 1314 return 1; 1315} 1316 1317/* ----------------------------------------------------------------------------- 1318Clear the interface IPv6 addresses 1319 ----------------------------------------------------------------------------- */ 1320int clear_ifaddr6 (char *ifname, struct in6_addr *addr) 1321{ 1322 int s; 1323 struct in6_ifreq ifreq6; 1324 1325 s = socket(AF_INET6, SOCK_DGRAM, 0); 1326 if (s < 0) { 1327 syslog(LOG_ERR, "set_ifaddr6: can't create IPv6 socket, %s", 1328 strerror(errno)); 1329 return 0; 1330 } 1331 1332 memset(&ifreq6, 0, sizeof(ifreq6)); 1333 strlcpy(ifreq6.ifr_name, ifname, sizeof(ifreq6.ifr_name)); 1334 1335 /* my addr */ 1336 ifreq6.ifr_ifru.ifru_addr.sin6_family = AF_INET6; 1337 ifreq6.ifr_ifru.ifru_addr.sin6_len = sizeof(struct sockaddr_in6); 1338 memcpy(&ifreq6.ifr_ifru.ifru_addr.sin6_addr, addr, sizeof(struct in6_addr)); 1339 1340 if (ioctl(s, SIOCDIFADDR_IN6, &ifreq6) < 0) { 1341 syslog(LOG_ERR, "set_ifaddr6: can't set IPv6 address, %s", 1342 strerror(errno)); 1343 close(s); 1344 return 0; 1345 } 1346 1347 close(s); 1348 return 1; 1349} 1350 1351 1352/* ---------------------------------------------------------------------------- 1353----------------------------------------------------------------------------- */ 1354const char *inet_sockaddr_to_p(struct sockaddr *addr, char *buf, int buflen) 1355{ 1356 void *p; 1357 1358 // Wcast-align fixes (void*) OK - inet_ntop has no alignment requirement 1359 switch (addr->sa_family) { 1360 case AF_INET: 1361 p = &((struct sockaddr_in *)(void*)addr)->sin_addr; 1362 break; 1363 case AF_INET6: 1364 p = &((struct sockaddr_in6 *)(void*)addr)->sin6_addr; 1365 break; 1366 default: 1367 return NULL; 1368 } 1369 1370 return inet_ntop(addr->sa_family, p, buf, buflen); 1371} 1372 1373/* ---------------------------------------------------------------------------- 1374----------------------------------------------------------------------------- */ 1375int inet_p_to_sockaddr(char *buf, struct sockaddr *addr, int addrlen) 1376{ 1377 bzero(addr, addrlen); 1378 1379 // Wcast-align fixes (void*) OK - inet_pton has no alignment requirement 1380 if (addrlen >= sizeof(struct sockaddr_in) 1381 && inet_pton(AF_INET, buf, &((struct sockaddr_in *)(void*)addr)->sin_addr)) { 1382 addr->sa_len = sizeof(struct sockaddr_in); 1383 addr->sa_family = AF_INET; 1384 return 1; 1385 } 1386 1387 if (addrlen >= sizeof(struct sockaddr_in6) 1388 && inet_pton(AF_INET6, buf, &((struct sockaddr_in6 *)(void*)addr)->sin6_addr)) { 1389 addr->sa_len = sizeof(struct sockaddr_in6); 1390 addr->sa_family = AF_INET6; 1391 return 1; 1392 } 1393 1394 return 0; 1395} 1396 1397 1398/* ---------------------------------------------------------------------------- 1399return the default interface name and gateway for a given protocol 1400----------------------------------------------------------------------------- */ 1401Boolean copyGateway(SCDynamicStoreRef store, u_int8_t family, char *ifname, int ifnamesize, struct sockaddr *gateway, int gatewaysize) 1402{ 1403 CFDictionaryRef dict; 1404 CFStringRef key, string; 1405 Boolean found_interface = FALSE; 1406 Boolean found_router = FALSE; 1407 1408 if (ifname) 1409 ifname[0] = 0; 1410 if (gateway) 1411 bzero(gateway, gatewaysize); 1412 1413 if (family != AF_INET && family != AF_INET6) 1414 return FALSE; 1415 1416 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, 1417 (family == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6); 1418 if (key) { 1419 dict = SCDynamicStoreCopyValue(store, key); 1420 CFRelease(key); 1421 if (dict) { 1422 1423 if ((string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface))) { 1424 found_interface = TRUE; 1425 if (ifname) 1426 CFStringGetCString(string, ifname, ifnamesize, kCFStringEncodingUTF8); 1427 } 1428 if ((string = CFDictionaryGetValue(dict, (family == AF_INET) ? kSCPropNetIPv4Router : kSCPropNetIPv6Router))) { 1429 char routeraddress[256]; 1430 routeraddress[0] = 0; 1431 CFStringGetCString(string, (char*)routeraddress, sizeof(routeraddress), kCFStringEncodingUTF8); 1432 if (routeraddress[0]) { 1433 struct sockaddr_storage addr; 1434 if (inet_p_to_sockaddr(routeraddress, (struct sockaddr *)&addr, sizeof(addr))) { 1435 found_router = TRUE; 1436 if (gateway && gatewaysize >= addr.ss_len) 1437 bcopy(&addr, gateway, addr.ss_len); 1438 } 1439 } 1440 } 1441 CFRelease(dict); 1442 } 1443 } 1444 return (found_interface && found_router); 1445} 1446 1447/* ---------------------------------------------------------------------------- 1448return TRUE if there is a default interface and gateway for a given protocol 1449----------------------------------------------------------------------------- */ 1450Boolean hasGateway(SCDynamicStoreRef store, u_int8_t family) 1451{ 1452 return copyGateway(store, family, 0, 0, 0, 0); 1453 1454} 1455 1456/* ---------------------------------------------------------------------------- 1457 Create a "NULL Service" primary IPv6 dictionary for the dynamic store. This 1458 prevents any other service from becoming primary on IPv6. 1459 ----------------------------------------------------------------------------- */ 1460#ifndef kIsNULL 1461#define kIsNULL CFSTR("IsNULL") /* CFBoolean */ 1462#endif 1463CFDictionaryRef create_ipv6_dummy_primary(char *if_name) 1464{ 1465 CFMutableArrayRef array; 1466 CFMutableDictionaryRef ipv6_dict; 1467 int isprimary = 1; 1468 CFNumberRef num; 1469 CFStringRef str; 1470 1471 /* create the IPv6 dictionnary */ 1472 if ((ipv6_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) 1473 return NULL; 1474 1475 if ((array = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks))) { 1476 CFArrayAppendValue(array, CFSTR("::1")); 1477 CFDictionarySetValue(ipv6_dict, kSCPropNetIPv6Addresses, array); 1478 CFRelease(array); 1479 } 1480 1481 CFDictionarySetValue(ipv6_dict, kSCPropNetIPv6Router, CFSTR("::1")); 1482 1483 num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &isprimary); 1484 if (num) { 1485 CFDictionarySetValue(ipv6_dict, kSCPropNetOverridePrimary, num); 1486 CFRelease(num); 1487 } 1488 1489 CFDictionarySetValue(ipv6_dict, kIsNULL, kCFBooleanTrue); 1490 1491 if (if_name) { 1492 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), if_name))) { 1493 CFDictionarySetValue(ipv6_dict, kSCPropInterfaceName, str); 1494 CFRelease(str); 1495 } 1496 } 1497 1498 return ipv6_dict; 1499} 1500 1501/* ---------------------------------------------------------------------------- 1502get dictionary for ip addresses to publish later to configd 1503use new state information model 1504----------------------------------------------------------------------------- */ 1505CFDictionaryRef create_stateaddr(SCDynamicStoreRef store, CFStringRef serviceID, char *if_name, u_int32_t server, u_int32_t o, 1506 u_int32_t h, u_int32_t m, int isprimary, CFArrayRef includedRoutes, CFArrayRef excludedRoutes) 1507{ 1508 struct in_addr addr; 1509 CFMutableArrayRef array; 1510 CFMutableDictionaryRef ipv4_dict; 1511 CFStringRef str; 1512 CFNumberRef num; 1513 SCNetworkServiceRef netservRef; 1514 1515 /* create the IPV4 dictionnary */ 1516 if ((ipv4_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) 1517 return NULL; 1518 1519 /* set the ip address src and dest arrays */ 1520 if ((array = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks))) { 1521 addr.s_addr = o; 1522 if ((str = CFStringCreateWithFormat(0, 0, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 1523 CFArrayAppendValue(array, str); 1524 CFRelease(str); 1525 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4Addresses, array); 1526 } 1527 CFRelease(array); 1528 } 1529 1530 /* set the router */ 1531 addr.s_addr = h; 1532 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 1533 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4Router, str); 1534 CFRelease(str); 1535 } 1536 1537 num = CFNumberCreate(NULL, kCFNumberIntType, &isprimary); 1538 if (num) { 1539 CFDictionarySetValue(ipv4_dict, kSCPropNetOverridePrimary, num); 1540 CFRelease(num); 1541 } 1542 1543 if (if_name) { 1544 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), if_name))) { 1545 CFDictionarySetValue(ipv4_dict, kSCPropInterfaceName, str); 1546 CFRelease(str); 1547 } 1548 } 1549 1550 /* set the server */ 1551 addr.s_addr = server; 1552 if ((str = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(&addr.s_addr)))) { 1553 CFDictionarySetValue(ipv4_dict, CFSTR("ServerAddress"), str); 1554 CFRelease(str); 1555 } 1556 1557#if 0 1558 /* add the network signature */ 1559 if (network_signature) { 1560 if (str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), network_signature)) { 1561 CFDictionarySetValue(ipv4_dict, CFSTR("NetworkSignature"), str); 1562 CFRelease(str); 1563 } 1564 } 1565#endif 1566 1567 1568 /* rank service, to prevent it from becoming primary */ 1569 if (!isprimary) { 1570 netservRef = _SCNetworkServiceCopyActive(store, serviceID); 1571 if (netservRef) { 1572 SCNetworkServiceSetPrimaryRank(netservRef, kSCNetworkServicePrimaryRankLast); 1573 CFRelease(netservRef); 1574 } 1575 } 1576 1577 if (includedRoutes) { 1578 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4AdditionalRoutes, includedRoutes); 1579 } 1580 1581 if (excludedRoutes) { 1582 CFDictionarySetValue(ipv4_dict, kSCPropNetIPv4ExcludedRoutes, excludedRoutes); 1583 } 1584 1585 return ipv4_dict; 1586} 1587 1588/* ----------------------------------------------------------------------------- 1589 get dns information 1590 ----------------------------------------------------------------------------- */ 1591CFDictionaryRef create_dns(SCDynamicStoreRef store, CFStringRef serviceID, CFArrayRef dns, CFStringRef domain, CFArrayRef supp_domains, Boolean neverSearchDomains) 1592{ 1593 CFMutableDictionaryRef dict = NULL; 1594 CFStringRef key = NULL; 1595 CFPropertyListRef ref; 1596 1597 if (store == NULL) 1598 return NULL; 1599 1600 key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainState, serviceID, kSCEntNetDNS); 1601 if (!key) 1602 goto end; 1603 1604 if ((ref = SCDynamicStoreCopyValue(store, key))) { 1605 dict = CFDictionaryCreateMutableCopy(0, 0, ref); 1606 CFRelease(ref); 1607 } else 1608 dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1609 1610 if (!dict || (CFGetTypeID(dict) != CFDictionaryGetTypeID())) 1611 goto end; 1612 1613 CFDictionarySetValue(dict, kSCPropNetDNSServerAddresses, dns); 1614 1615 if (domain) 1616 CFDictionarySetValue(dict, kSCPropNetDNSDomainName, domain); 1617 1618 if (supp_domains) 1619 CFDictionarySetValue(dict, kSCPropNetDNSSupplementalMatchDomains, supp_domains); 1620 1621#ifndef kSCPropNetDNSSupplementalMatchDomainsNoSearch 1622#define kSCPropNetDNSSupplementalMatchDomainsNoSearch CFSTR("SupplementalMatchDomainsNoSearch") 1623#endif 1624 1625 if (neverSearchDomains) { 1626 AddNumber(dict, kSCPropNetDNSSupplementalMatchDomainsNoSearch, 1); 1627 } 1628 1629 /* warn lookupd of upcoming change */ 1630 notify_post("com.apple.system.dns.delay"); 1631 1632end: 1633 my_CFRelease(&key); 1634 return dict; 1635 1636} 1637 1638/* ----------------------------------------------------------------------------- 1639 ----------------------------------------------------------------------------- */ 1640Boolean equal_address(struct sockaddr *addr1, struct sockaddr *addr2) 1641{ 1642 1643 if (addr1->sa_family != addr2->sa_family) 1644 return FALSE; 1645 1646 /* Wcast-align fixes - don't use assignement or standard compare for ptrs of unknown alignment */ 1647 if (addr1->sa_family == AF_INET) { 1648 return (!bcmp(&((struct sockaddr_in *)(void*)addr1)->sin_addr.s_addr, 1649 &((struct sockaddr_in *)(void*)addr2)->sin_addr.s_addr, 1650 sizeof(struct in_addr))); 1651 } 1652 1653 if (addr1->sa_family == AF_INET6) { 1654 return (!bcmp(&((struct sockaddr_in6 *)(void*)addr1)->sin6_addr, 1655 &((struct sockaddr_in6 *)(void*)addr2)->sin6_addr, 1656 sizeof(struct in6_addr))); 1657 } 1658 1659 return FALSE; 1660} 1661 1662/* ----------------------------------------------------------------------------- 1663 add/remove a route via a gateway 1664----------------------------------------------------------------------------- */ 1665int 1666route_gateway(int cmd, struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *gateway, int use_gway_flag, int use_blackhole_flag) 1667{ 1668 int len; 1669 int rtm_seq = 0; 1670 1671 struct rtmsg_in4 { 1672 struct rt_msghdr hdr; 1673 struct sockaddr_in dst; 1674 struct sockaddr_in gway; 1675 struct sockaddr_in mask; 1676 }; 1677 struct rtmsg_in6 { 1678 struct rt_msghdr hdr; 1679 struct sockaddr_in6 dst; 1680 struct sockaddr_in6 gway; 1681 struct sockaddr_in6 mask; 1682 }; 1683 1684 int sockfd = -1; 1685 struct rtmsg_in6 rtmsg; // use rtmsg_in6 since it is the bigger one; 1686 1687 if (dest == NULL || (dest->sa_family != AF_INET 1688 && dest->sa_family != AF_INET6)) 1689 return -1; 1690 1691 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) { 1692 syslog(LOG_INFO, "route_gateway: open routing socket failed, %s", 1693 strerror(errno)); 1694 return (-1); 1695 } 1696 1697 memset(&rtmsg, 0, sizeof(rtmsg)); 1698 1699 // fill in header, which is common to IPv4 and IPv6 1700 rtmsg.hdr.rtm_type = cmd; 1701 rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC; 1702 if (use_gway_flag) 1703 rtmsg.hdr.rtm_flags |= RTF_GATEWAY; 1704 if (use_blackhole_flag) 1705 rtmsg.hdr.rtm_flags |= RTF_BLACKHOLE; 1706 rtmsg.hdr.rtm_version = RTM_VERSION; 1707 rtmsg.hdr.rtm_seq = ++rtm_seq; 1708 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY; 1709 1710 // then fill in address specific portion 1711 if (dest->sa_family == AF_INET) { 1712 struct rtmsg_in4 *rtmsg4 = (struct rtmsg_in4 *)&rtmsg; 1713 1714 bcopy(dest, &rtmsg4->dst, sizeof(rtmsg4->dst)); 1715 if (gateway) 1716 bcopy(gateway, &rtmsg4->gway, sizeof(rtmsg4->gway)); 1717 if (mask) 1718 bcopy(mask, &rtmsg4->mask, sizeof(rtmsg4->mask)); 1719 1720 len = sizeof(struct rtmsg_in4); 1721 } 1722 else { 1723 struct rtmsg_in6 *rtmsg6 = (struct rtmsg_in6 *)&rtmsg; 1724 1725 bcopy(dest, &rtmsg6->dst, sizeof(rtmsg6->dst)); 1726 if (gateway) 1727 bcopy(gateway, &rtmsg6->gway, sizeof(rtmsg6->gway)); 1728 if (mask) 1729 bcopy(mask, &rtmsg6->mask, sizeof(rtmsg6->mask)); 1730 1731 len = sizeof(struct rtmsg_in6); 1732 } 1733 1734 rtmsg.hdr.rtm_msglen = len; 1735 if (write(sockfd, &rtmsg, len) < 0) { 1736 syslog((cmd == RTM_DELETE)? LOG_DEBUG : LOG_ERR, "route_gateway: write routing socket failed, %s", strerror(errno)); 1737 1738#if 0 1739 /* print routing message for debugging */ 1740 char buf[256]; 1741 syslog(LOG_ERR, "-------"); 1742 struct rtmsg_in4 *rtmsg4 = (struct rtmsg_in4 *)&rtmsg; 1743 inet_sockaddr_to_p(dest->sa_family == AF_INET ? (struct sockaddr *)&rtmsg4->dst : (struct sockaddr *)&rtmsg.dst, buf, sizeof(buf)); 1744 syslog(LOG_ERR, "route_gateway: rtmsg.dst = %s", buf); 1745 inet_sockaddr_to_p(dest->sa_family == AF_INET ? (struct sockaddr *)&rtmsg4->gway : (struct sockaddr *)&rtmsg.gway, buf, sizeof(buf)); 1746 syslog(LOG_ERR, "route_gateway: rtmsg.gway = %s", buf); 1747 inet_sockaddr_to_p(dest->sa_family == AF_INET ? (struct sockaddr *)&rtmsg4->mask : (struct sockaddr *)&rtmsg.mask, buf, sizeof(buf)); 1748 syslog(LOG_ERR, "route_gateway: rtmsg.mask = %s", buf); 1749 syslog(LOG_ERR, "-------"); 1750#endif 1751 1752 close(sockfd); 1753 return (-1); 1754 } 1755 1756 close(sockfd); 1757 return (0); 1758} 1759 1760/* ----------------------------------------------------------------------------- 1761add/remove a host route 1762----------------------------------------------------------------------------- */ 1763boolean_t 1764set_host_gateway(int cmd, struct sockaddr *host, struct sockaddr *gateway, char *ifname, int isnet) 1765{ 1766 int len; 1767 int rtm_seq = 0; 1768 struct rtmsg_in4 { 1769 struct rt_msghdr hdr; 1770 struct sockaddr_in dst; 1771 struct sockaddr_in gway; 1772 struct sockaddr_in mask; 1773 struct sockaddr_dl link; 1774 }; 1775 struct rtmsg_in6 { 1776 struct rt_msghdr hdr; 1777 struct sockaddr_in6 dst; 1778 struct sockaddr_in6 gway; 1779 struct sockaddr_in6 mask; 1780 struct sockaddr_dl link; 1781 }; 1782 1783 int sockfd = -1; 1784 struct rtmsg_in6 rtmsg; // use rtmsg_in6 since it is the bigger one; 1785 struct sockaddr_dl *link; 1786 struct in6_addr ip6_zeros; 1787 struct in_addr ip4_zeros; 1788 1789 if (host == NULL || (host->sa_family != AF_INET 1790 && host->sa_family != AF_INET6)) 1791 return FALSE; 1792 1793 if ((sockfd = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) { 1794 syslog(LOG_INFO, "host_gateway: open routing socket failed, %s", 1795 strerror(errno)); 1796 return (FALSE); 1797 } 1798 1799 memset(&rtmsg, 0, sizeof(rtmsg)); 1800 rtmsg.hdr.rtm_type = cmd; 1801 rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC; 1802 if (isnet) 1803 rtmsg.hdr.rtm_flags |= RTF_CLONING; 1804 else 1805 rtmsg.hdr.rtm_flags |= RTF_HOST; 1806 bzero(&ip6_zeros, sizeof(ip6_zeros)); 1807 bzero(&ip4_zeros, sizeof(ip4_zeros)); 1808 // Wcast-align fix - use memcmp for unaligned comparison 1809 if (gateway && (((gateway->sa_family == AF_INET && memcmp(&((struct sockaddr_in *)(void*)gateway)->sin_addr.s_addr, &ip4_zeros, sizeof(struct in_addr)))) || 1810 (gateway->sa_family == AF_INET6 && memcmp(&((struct sockaddr_in6 *)(void*)gateway)->sin6_addr, &ip6_zeros, sizeof(struct in6_addr))))) { 1811 rtmsg.hdr.rtm_flags |= RTF_GATEWAY; 1812 } 1813 1814 rtmsg.hdr.rtm_version = RTM_VERSION; 1815 rtmsg.hdr.rtm_seq = ++rtm_seq; 1816 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY; 1817 1818 if (host->sa_family == AF_INET) { 1819 struct rtmsg_in4 *rtmsg4 = (struct rtmsg_in4 *)&rtmsg; 1820 1821 bcopy(host, &rtmsg4->dst, sizeof(rtmsg4->dst)); 1822 1823 if (gateway) 1824 bcopy(gateway, &rtmsg4->gway, sizeof(rtmsg4->gway)); 1825 1826 rtmsg4->mask.sin_len = sizeof(rtmsg4->mask); 1827 rtmsg4->mask.sin_family = AF_INET; 1828 rtmsg4->mask.sin_addr.s_addr = 0xFFFFFFFF; 1829 1830 len = sizeof(struct rtmsg_in4); 1831 link = &rtmsg4->link; 1832 } 1833 else { 1834 struct rtmsg_in6 *rtmsg6 = (struct rtmsg_in6 *)&rtmsg; 1835 1836 bcopy(host, &rtmsg6->dst, sizeof(rtmsg6->dst)); 1837 1838 if (gateway) 1839 bcopy(gateway, &rtmsg6->gway, sizeof(rtmsg6->gway)); 1840 1841 rtmsg6->mask.sin6_len = sizeof(rtmsg6->mask); 1842 rtmsg6->mask.sin6_family = AF_INET6; 1843 rtmsg6->mask.sin6_addr.__u6_addr.__u6_addr32[0] = 0xFFFFFFFF; 1844 rtmsg6->mask.sin6_addr.__u6_addr.__u6_addr32[1] = 0xFFFFFFFF; 1845 rtmsg6->mask.sin6_addr.__u6_addr.__u6_addr32[2] = 0xFFFFFFFF; 1846 rtmsg6->mask.sin6_addr.__u6_addr.__u6_addr32[3] = 0xFFFFFFFF; 1847 1848 len = sizeof(struct rtmsg_in6); 1849 link = &rtmsg6->link; 1850 } 1851 1852 if (ifname) { 1853 link->sdl_len = sizeof(rtmsg.link); 1854 link->sdl_family = AF_LINK; 1855 link->sdl_nlen = MIN(strlen(ifname), sizeof(link->sdl_data)); 1856 rtmsg.hdr.rtm_addrs |= RTA_IFP; 1857 bcopy(ifname, link->sdl_data, link->sdl_nlen); 1858 } 1859 else { 1860 /* no link information */ 1861 len -= sizeof(rtmsg.link); 1862 } 1863 1864 rtmsg.hdr.rtm_msglen = len; 1865 if (write(sockfd, &rtmsg, len) < 0) { 1866 syslog((cmd == RTM_DELETE)? LOG_DEBUG : LOG_ERR, "host_gateway: write routing socket failed, command %d, %s", cmd, strerror(errno)); 1867 1868#if 0 1869 /* print routing message for debugging */ 1870 char buf[256]; 1871 syslog(LOG_ERR, "********"); 1872 struct rtmsg_in4 *rtmsg4 = (struct rtmsg_in4 *)&rtmsg; 1873 syslog(LOG_ERR, "host_gateway: dest->sa_family = %d rtmsg.hdr.rtm_msglen = %d", host->sa_family, rtmsg.hdr.rtm_msglen); 1874 inet_sockaddr_to_p(host->sa_family == AF_INET ? (struct sockaddr *)&rtmsg4->dst : (struct sockaddr *)&rtmsg.dst, buf, sizeof(buf)); 1875 syslog(LOG_ERR, "host_gateway: rtmsg.dst = %s", buf); 1876 inet_sockaddr_to_p(host->sa_family == AF_INET ? (struct sockaddr *)&rtmsg4->gway : (struct sockaddr *)&rtmsg.gway, buf, sizeof(buf)); 1877 syslog(LOG_ERR, "host_gateway: rtmsg.gway = %s", buf); 1878 inet_sockaddr_to_p(host->sa_family == AF_INET ? (struct sockaddr *)&rtmsg4->mask : (struct sockaddr *)&rtmsg.mask, buf, sizeof(buf)); 1879 syslog(LOG_ERR, "host_gateway: rtmsg.mask = %s", buf); 1880 syslog(LOG_ERR, "********"); 1881#endif 1882 close(sockfd); 1883 return (FALSE); 1884 } 1885 1886 close(sockfd); 1887 return (TRUE); 1888} 1889 1890/* ---------------------------------------------------------------------------- 1891 get proxies using to publish to configd 1892 ----------------------------------------------------------------------------- */ 1893CFDictionaryRef create_proxies(SCDynamicStoreRef store, CFStringRef serviceID, int autodetect, CFStringRef server, int port, int bypasslocal, 1894 CFStringRef exceptionlist, CFArrayRef supp_domains) 1895{ 1896 int val, ret = -1; 1897 CFStringRef cfstr = NULL; 1898 CFArrayRef cfarray; 1899 CFNumberRef cfnum, cfone = NULL; 1900 CFMutableDictionaryRef proxies_dict = NULL; 1901 1902 if ((proxies_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) 1903 goto fail; 1904 1905 val = 1; 1906 cfone = CFNumberCreate(NULL, kCFNumberIntType, &val); 1907 if (cfone == NULL) 1908 goto fail; 1909 1910 if (autodetect) { 1911 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesProxyAutoDiscoveryEnable, cfone); 1912 } 1913 else if (server) { 1914 1915 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesFTPEnable, cfone); 1916 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesHTTPEnable, cfone); 1917 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesHTTPSEnable, cfone); 1918 1919 cfnum = CFNumberCreate(NULL, kCFNumberIntType, &port); 1920 if (cfnum == NULL) 1921 goto fail; 1922 1923 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesFTPPort, cfnum); 1924 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesHTTPPort, cfnum); 1925 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesHTTPSPort, cfnum); 1926 CFRelease(cfnum); 1927 1928 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesFTPProxy, server); 1929 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesHTTPProxy, server); 1930 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesHTTPSProxy, server); 1931 1932 cfnum = CFNumberCreate(NULL, kCFNumberIntType, &bypasslocal); 1933 if (cfnum == NULL) 1934 goto fail; 1935 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesExcludeSimpleHostnames, cfnum); 1936 CFRelease(cfnum); 1937 1938 if (exceptionlist) { 1939 cfarray = CFStringCreateArrayBySeparatingStrings(NULL, exceptionlist, CFSTR(";")); 1940 if (cfarray) { 1941 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesExceptionsList, cfarray); 1942 CFRelease(cfarray); 1943 } 1944 } 1945 } 1946 1947#ifndef kSCPropNetProxiesSupplementalMatchDomains 1948#define kSCPropNetProxiesSupplementalMatchDomains kSCPropNetDNSSupplementalMatchDomains 1949#endif 1950 1951 if (supp_domains) 1952 CFDictionarySetValue(proxies_dict, kSCPropNetProxiesSupplementalMatchDomains, supp_domains); 1953 1954 ret = 0; 1955 1956fail: 1957 1958 my_CFRelease(&cfone); 1959 my_CFRelease(&cfstr); 1960 return proxies_dict; 1961} 1962 1963/* ----------------------------------------------------------------------------- 1964 Create the new tun interface, and return the socket 1965 ----------------------------------------------------------------------------- */ 1966int create_tun_interface(char *name, int name_max_len, int *index, int flags, int ext_stats) 1967{ 1968 1969 struct ctl_info kernctl_info; 1970 struct sockaddr_ctl kernctl_addr; 1971 u_int32_t optlen; 1972 int tunsock = -1; 1973 1974 tunsock = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); 1975 if (tunsock == -1) { 1976 SCLog(TRUE, LOG_ERR, CFSTR("create_tun_interface: cannot create kernel control socket (errno = %d)"), errno); 1977 goto fail; 1978 } 1979 1980 bzero(&kernctl_info, sizeof(kernctl_info)); 1981 strlcpy(kernctl_info.ctl_name, UTUN_CONTROL_NAME, sizeof(kernctl_info.ctl_name)); 1982 if (ioctl(tunsock, CTLIOCGINFO, &kernctl_info)) { 1983 SCLog(TRUE, LOG_ERR, CFSTR("create_tun_interface: ioctl failed on kernel control socket (errno = %d)"), errno); 1984 goto fail; 1985 } 1986 1987 bzero(&kernctl_addr, sizeof(kernctl_addr)); // sets the sc_unit field to 0 1988 kernctl_addr.sc_len = sizeof(kernctl_addr); 1989 kernctl_addr.sc_family = AF_SYSTEM; 1990 kernctl_addr.ss_sysaddr = AF_SYS_CONTROL; 1991 kernctl_addr.sc_id = kernctl_info.ctl_id; 1992 kernctl_addr.sc_unit = 0; // we will get the unit number from getpeername 1993 if (connect(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr))) { 1994 SCLog(TRUE, LOG_ERR, CFSTR("create_tun_interface: connect failed on kernel control socket (errno = %d)"), errno); 1995 goto fail; 1996 } 1997 1998 optlen = name_max_len; 1999 if (getsockopt(tunsock, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &optlen)) { 2000 SCLog(TRUE, LOG_ERR, CFSTR("create_tun_interface: getsockopt ifname failed on kernel control socket (errno = %d)"), errno); 2001 goto fail; 2002 } 2003 2004 *index = if_nametoindex(name); 2005 2006 if (flags) { 2007 int optflags = 0; 2008 optlen = sizeof(u_int32_t); 2009 if (getsockopt(tunsock, SYSPROTO_CONTROL, UTUN_OPT_FLAGS, &optflags, &optlen)) { 2010 SCLog(TRUE, LOG_ERR, CFSTR("create_tun_interface: getsockopt flags failed on kernel control socket (errno = %d)"), errno); 2011 goto fail; 2012 } 2013 2014 optflags |= (UTUN_FLAGS_NO_INPUT + UTUN_FLAGS_NO_OUTPUT); 2015 optlen = sizeof(u_int32_t); 2016 if (setsockopt(tunsock, SYSPROTO_CONTROL, UTUN_OPT_FLAGS, &optflags, optlen)) { 2017 SCLog(TRUE, LOG_ERR, CFSTR("create_tun_interface: setsockopt flags failed on kernel control socket (errno = %d)"), errno); 2018 goto fail; 2019 } 2020 } 2021 2022 if (ext_stats) { 2023 int optval = 1; 2024 if (setsockopt(tunsock, SYSPROTO_CONTROL, UTUN_OPT_EXT_IFDATA_STATS, &optval, sizeof(optval))) { 2025 SCLog(TRUE, LOG_ERR, CFSTR("create_tun_interface: setsockopt externat stats failed on kernel control socket (errno = %d)"), errno); 2026 goto fail; 2027 } 2028 } 2029 2030 return tunsock; 2031 2032fail: 2033 my_close(tunsock); 2034 return -1; 2035 2036} 2037 2038/* ----------------------------------------------------------------------------- 2039 Set the delegate interface for the tun interface 2040 ----------------------------------------------------------------------------- */ 2041int set_tun_delegate(int tunsock, char *delegate_ifname) 2042{ 2043 int result = 0; 2044 2045 if ((result = setsockopt(tunsock, SYSPROTO_CONTROL, UTUN_OPT_SET_DELEGATE_INTERFACE, delegate_ifname, strlen(delegate_ifname)))) 2046 SCLog(TRUE, LOG_ERR, CFSTR("set_tun_delegate: setsockopt delegate interface failed on kernel control socket (errno = %s)"), strerror(errno)); 2047 2048 return result; 2049} 2050 2051/* ----------------------------------------------------------------------------- 2052----------------------------------------------------------------------------- */ 2053int event_create_socket(void * ctxt, int *eventfd, CFSocketRef *eventref, CFSocketCallBack callout, Boolean anysubclass) 2054{ 2055 CFRunLoopSourceRef rls; 2056 CFSocketContext context = { 0, ctxt, NULL, NULL, NULL }; 2057 struct kev_request kev_req; 2058 2059 *eventfd = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT); 2060 if (*eventfd < 0) { 2061 SCLog(TRUE, LOG_ERR, CFSTR("event_create_socket cannot create event socket (errno = %d) "), errno); 2062 goto fail; 2063 } 2064 2065 kev_req.vendor_code = KEV_VENDOR_APPLE; 2066 kev_req.kev_class = KEV_NETWORK_CLASS; 2067 kev_req.kev_subclass = anysubclass ? KEV_ANY_SUBCLASS : KEV_INET_SUBCLASS; 2068 ioctl(*eventfd, SIOCSKEVFILT, &kev_req); 2069 2070 if ((*eventref = CFSocketCreateWithNative(NULL, *eventfd, 2071 kCFSocketReadCallBack, callout, &context)) == 0) { 2072 goto fail; 2073 } 2074 if ((rls = CFSocketCreateRunLoopSource(NULL, *eventref, 0)) == 0) 2075 goto fail; 2076 2077 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 2078 CFRelease(rls); 2079 2080 return 0; 2081 2082fail: 2083 if (*eventref) { 2084 CFSocketInvalidate(*eventref); 2085 CFRelease(*eventref); 2086 } 2087 else 2088 if (*eventfd >= 0) { 2089 close(*eventfd); 2090 } 2091 *eventref = 0; 2092 *eventfd = -1; 2093 2094 return -1; 2095} 2096 2097/* ----------------------------------------------------------------------------- 2098 ----------------------------------------------------------------------------- */ 2099typedef struct exec_callback_args { 2100 CFRunLoopRef rl; 2101 CFRunLoopSourceRef rls; 2102 CFRunLoopSourceContext rlc; 2103 pid_t pid; 2104 int status; 2105 struct rusage rusage; 2106 SCDPluginExecCallBack callback; 2107 void *callbackContext; 2108} exec_callback_args_t; 2109 2110/* ----------------------------------------------------------------------------- 2111 ----------------------------------------------------------------------------- */ 2112static 2113void exec_callback(pid_t pid, int status, struct rusage *rusage, void *context) 2114{ 2115 if (isA_CFData(context)) { 2116 exec_callback_args_t *args = ALIGNED_CAST(__typeof__(args))CFDataGetMutableBytePtr((CFMutableDataRef)context); 2117 args->pid = pid; 2118 args->status = status; 2119 bcopy(rusage, &args->rusage, sizeof(args->rusage)); 2120 // args->context already contains the service 2121 CFRunLoopSourceSignal(args->rls); 2122 CFRunLoopWakeUp(args->rl); 2123 } 2124} 2125 2126static void 2127SCNCPluginExecCallbackRunLoopSource (void *info) 2128{ 2129 if (isA_CFData(info)) { 2130 exec_callback_args_t *args = ALIGNED_CAST(__typeof__(args))CFDataGetMutableBytePtr((CFMutableDataRef)info); 2131 if (args->callback) { 2132 args->callback(args->pid, args->status, &args->rusage, args->callbackContext); 2133 } 2134 CFRunLoopSourceInvalidate(args->rls); 2135 CFRelease(args->rls); 2136 CFRelease(args->rl); 2137 CFRelease((CFMutableDataRef)info); // release (was allocated in SCNCPluginExecCallbackRunLoopSourceInit) 2138 } 2139} 2140 2141CFMutableDataRef 2142SCNCPluginExecCallbackRunLoopSourceInit (CFRunLoopRef runloop, 2143 SCDPluginExecCallBack callback, 2144 void *callbackContext) 2145{ 2146 CFMutableDataRef dataRef; // to be used as SCNCPluginExecCallbackRunLoopSource's info 2147 UInt8 *dataPtr; 2148 exec_callback_args_t args; 2149 2150 // create dataref and fill it with runloop args 2151 dataRef = CFDataCreateMutable(NULL, sizeof(args)); 2152 if (dataRef == NULL) { 2153 return NULL; 2154 } 2155 CFDataSetLength(dataRef, sizeof(args)); 2156 dataPtr = CFDataGetMutableBytePtr(dataRef); 2157 2158 bzero(&args, sizeof(args)); 2159 args.rlc.info = dataRef; // use as SCNCPluginExecCallbackRunLoopSource's info 2160 args.rlc.perform = SCNCPluginExecCallbackRunLoopSource; 2161 args.rls = CFRunLoopSourceCreate(NULL, 0, &args.rlc); 2162 if (!args.rls){ 2163 CFRelease(dataRef); 2164 return NULL; 2165 } 2166 args.callback = callback; 2167 args.callbackContext = callbackContext; 2168 if (!runloop) { 2169 args.rl = CFRunLoopGetCurrent(); 2170 } else { 2171 args.rl = runloop; 2172 } 2173 CFRetain(args.rl); 2174 CFRunLoopAddSource(args.rl, args.rls, kCFRunLoopDefaultMode); 2175 bcopy(&args, dataPtr, sizeof(args)); 2176 return dataRef; // to be used as exec_callback's context 2177} 2178 2179pid_t 2180SCNCPluginExecCommand (CFRunLoopRef runloop, 2181 SCDPluginExecCallBack callback, 2182 void *callbackContext, 2183 uid_t uid, 2184 gid_t gid, 2185 const char *path, 2186 char * const argv[]) 2187{ 2188 pid_t rc; 2189 CFMutableDataRef exec_callback_context; 2190 2191 exec_callback_context = SCNCPluginExecCallbackRunLoopSourceInit(runloop, callback, callbackContext); 2192 if (!exec_callback_context){ 2193 SCLog(TRUE, LOG_ERR, CFSTR("SCNC: failed to initialize plugin exec_callback's runloop source")); 2194 return -1; 2195 } 2196 2197 rc = _SCDPluginExecCommand(exec_callback, 2198 exec_callback_context, 2199 uid, 2200 gid, 2201 path, 2202 argv); 2203 return rc; 2204} 2205 2206pid_t 2207SCNCPluginExecCommand2 (CFRunLoopRef runloop, 2208 SCDPluginExecCallBack callback, 2209 void *callbackContext, 2210 uid_t uid, 2211 gid_t gid, 2212 const char *path, 2213 char * const argv[], 2214 SCDPluginExecSetup setup, 2215 void *setupContext) 2216{ 2217 pid_t rc; 2218 CFMutableDataRef exec_callback_context; 2219 2220 exec_callback_context = SCNCPluginExecCallbackRunLoopSourceInit(runloop, callback, callbackContext); 2221 if (!exec_callback_context){ 2222 SCLog(TRUE, LOG_ERR, CFSTR("SCNC: failed to initialize plugin exec_callback's runloop source")); 2223 return -1; 2224 } 2225 2226 rc = _SCDPluginExecCommand2(exec_callback, 2227 exec_callback_context, 2228 uid, 2229 gid, 2230 path, 2231 argv, 2232 setup, 2233 setupContext); 2234 return rc; 2235} 2236 2237#define SBSLAUNCHER_NAME "sbslauncher" 2238#define MAX_SBSLAUNCHER_ARGS 16 2239 2240/* Variable arguments are of type char*, and the last argument must be NULL */ 2241pid_t 2242SCNCExecSBSLauncherCommandWithArguments (char *command, 2243 SCDPluginExecSetup setup, 2244 SCDPluginExecCallBack callback, 2245 void *callbackContext, 2246 ...) 2247{ 2248 va_list arguments; 2249 CFStringRef resourceDir = NULL; 2250 CFURLRef resourceURL = NULL, absoluteURL = NULL; 2251 char thepath[MAXPATHLEN]; 2252 pid_t pid = 0; 2253 char *cmdarg[MAX_SBSLAUNCHER_ARGS]; 2254 2255 resourceURL = CFBundleCopyResourcesDirectoryURL(gBundleRef); 2256 2257 if (resourceURL == NULL) 2258 goto done; 2259 2260 absoluteURL = CFURLCopyAbsoluteURL(resourceURL); 2261 if (absoluteURL == NULL) 2262 goto done; 2263 2264 resourceDir = CFURLCopyPath(absoluteURL); 2265 if (resourceDir == NULL) 2266 goto done; 2267 2268 if (!CFStringGetCString(resourceDir, thepath, sizeof(thepath), kCFStringEncodingMacRoman)) 2269 goto done; 2270 2271 strlcat(thepath, SBSLAUNCHER_NAME, sizeof(thepath)); 2272 2273 cmdarg[0] = SBSLAUNCHER_NAME; 2274 cmdarg[1] = command; 2275 2276 va_start(arguments, callbackContext); 2277 int i = 2; 2278 2279 char *arg_i = va_arg(arguments, char *); 2280 while (arg_i != NULL && i < (MAX_SBSLAUNCHER_ARGS - 1)) { 2281 cmdarg[i++] = arg_i; 2282 arg_i = va_arg(arguments, char *); 2283 } 2284 cmdarg[i] = NULL; 2285 va_end(arguments); 2286 2287 if (setup) { 2288 pid = SCNCPluginExecCommand2(NULL, callback, callbackContext, 0, 0, thepath, cmdarg, setup, callbackContext); 2289 } else { 2290 pid = SCNCPluginExecCommand(NULL, callback, callbackContext, 0, 0, thepath, cmdarg); 2291 } 2292 2293done: 2294 if (resourceDir) 2295 CFRelease(resourceDir); 2296 if (absoluteURL) 2297 CFRelease(absoluteURL); 2298 if (resourceURL) 2299 CFRelease(resourceURL); 2300 2301 return pid; 2302} 2303 2304void 2305extractEnvironmentVariablesApplierFunction (const void *key, const void *value, void *context) 2306{ 2307 struct service *serv = (struct service *)context; 2308 CFRange range; 2309 2310 if (isA_CFString(key)) { 2311 char *key_buf = (char *)serv->envKeys[serv->envCount]; 2312 char *value_buf = (char *)serv->envValues[serv->envCount]; 2313 2314 key_buf[0] = '\0'; 2315 range.location = 0; 2316 range.length = CFStringGetLength((CFStringRef)key); 2317 if (range.length <= 0 || 2318 range.length >= sizeof(*serv->envKeys) || 2319 CFStringGetBytes((CFStringRef)key, range, kCFStringEncodingUTF8, 0, false, (UInt8 *)key_buf, sizeof(*serv->envKeys), NULL) <= 0) { 2320 SCLog(TRUE, LOG_ERR, CFSTR("invalid EnvironmentVariables key %@, value %@"), key, value); 2321 return; 2322 } 2323 key_buf[range.length] = '\0'; 2324 serv->envCount++; 2325 2326 value_buf[0] = '\0'; 2327 if (isA_CFString(value)) { 2328 range.location = 0; 2329 range.length = CFStringGetLength((CFStringRef)value); 2330 if (range.length <= 0 || 2331 range.length >= sizeof(*serv->envValues) || 2332 CFStringGetBytes((CFStringRef)value, range, kCFStringEncodingUTF8, 0, false, (UInt8 *)value_buf, sizeof(*serv->envValues), NULL) <= 0) { 2333 SCLog(TRUE, LOG_ERR, CFSTR("invalid EnvironmentVariables key %@, value %@"), key, value); 2334 return; 2335 } 2336 value_buf[range.length] = '\0'; 2337 } else if (isA_CFNumber(value)) { 2338 int64_t number = 0; 2339 if (CFNumberGetValue((CFNumberRef)value, kCFNumberSInt64Type, &number)) { 2340 snprintf(value_buf, sizeof(*serv->envValues), "%lld", number); 2341 } else { 2342 SCLog(TRUE, LOG_ERR, CFSTR("invalid EnvironmentVariables key %@, value %@"), key, value); 2343 return; 2344 } 2345 } else if (isA_CFBoolean(value)) { 2346 snprintf(value_buf, sizeof(*serv->envValues), "%s", CFBooleanGetValue((CFBooleanRef)value) ? "Yes" : "No"); 2347 } else { 2348 SCLog(TRUE, LOG_ERR, CFSTR("invalid EnvironmentVariables key %@, value %@"), key, value); 2349 return; 2350 } 2351 } else { 2352 SCLog(TRUE, LOG_ERR, CFSTR("invalid EnvironmentVariables key")); 2353 } 2354} 2355 2356CFDictionaryRef 2357collectEnvironmentVariables (SCDynamicStoreRef storeRef, CFStringRef serviceID) 2358{ 2359 if (!storeRef) { 2360 SCLog(TRUE, LOG_ERR, CFSTR("invalid DynamicStore passed to %s"), __FUNCTION__); 2361 return NULL; 2362 } 2363 2364 if (!serviceID) { 2365 SCLog(TRUE, LOG_ERR, CFSTR("invalid serviceID passed to %s"), __FUNCTION__); 2366 return NULL; 2367 } 2368 2369 return copyEntity(storeRef, kSCDynamicStoreDomainSetup, serviceID, CFSTR("EnvironmentVariables")); 2370} 2371 2372void 2373extractEnvironmentVariables (CFDictionaryRef envVarDict, struct service *serv) 2374{ 2375 if (!envVarDict) { 2376 return; 2377 } else if (isA_CFDictionary(envVarDict) && 2378 CFDictionaryGetCount(envVarDict) > 0) { 2379 int count = CFDictionaryGetCount(envVarDict); 2380 2381 if (serv->envKeys) { 2382 free(serv->envKeys); 2383 serv->envKeys = NULL; 2384 } 2385 if (serv->envValues) { 2386 free(serv->envValues); 2387 serv->envValues = NULL; 2388 } 2389 2390 serv->envCount = 0; 2391 serv->envKeys = (char *)malloc(count * sizeof(envKeyValue_t)); 2392 serv->envValues = (char *)malloc(count * sizeof(envKeyValue_t)); 2393 if (!serv->envKeys || !serv->envValues) { 2394 SCLog(TRUE, LOG_ERR, CFSTR("Failed to allocate for environment variables")); 2395 return; 2396 } 2397 2398 CFDictionaryApplyFunction(envVarDict, extractEnvironmentVariablesApplierFunction, serv); 2399 } else { 2400 SCLog(TRUE, LOG_ERR, CFSTR("empty or invalid EnvironmentVariables dictionary")); 2401 } 2402} 2403 2404/* 2405 * Don't call SCLog() in this function as it's unsafe in a post-fork handler that requires async-signal safe. 2406 */ 2407void 2408applyEnvironmentVariables (struct service *serv) 2409{ 2410 int i; 2411 2412 for (i = 0; i < serv->envCount; i++) { 2413 if (serv->envKeys[i]) { 2414 unsetenv(serv->envKeys[i]); 2415 if (serv->envValues[i]) 2416 setenv(serv->envKeys[i], serv->envValues[i], TRUE); 2417 } 2418 } 2419 2420 serv->envCount = 0; 2421 if (serv->envKeys) { 2422 free(serv->envKeys); 2423 serv->envKeys = NULL; 2424 } 2425 if (serv->envValues) { 2426 free(serv->envValues); 2427 serv->envValues = NULL; 2428 } 2429 2430} 2431 2432const char * 2433scnc_get_reason_str(int scnc_reason) 2434{ 2435 switch (scnc_reason) { 2436 case SCNC_STOP_CTRL_STOP: 2437 return scnc_ctrl_stopped; 2438 case SCNC_STOP_SYS_SLEEP: 2439 return scnc_sys_sleep; 2440 case SCNC_STOP_USER_LOGOUT: 2441 return scnc_usr_logout; 2442 case SCNC_STOP_USER_SWITCH: 2443 return scnc_usr_switch; 2444 case SCNC_STOP_SOCK_DISCONNECT: 2445 case SCNC_STOP_SOCK_DISCONNECT_NO_CLIENT: 2446 return scnc_sock_disco; 2447 case SCNC_STOP_PLUGIN_CHANGE: 2448 return scnc_plugin_chg; 2449 case SCNC_STOP_APP_REMOVED: 2450 return scnc_app_rem; 2451 case SCNC_STOP_USER_REQ: 2452 case SCNC_STOP_USER_REQ_NO_CLIENT: 2453 return scnc_usr_req; 2454 case SCNC_STOP_SERV_DISPOSE: 2455 return scnc_serv_disp; 2456 case SCNC_STOP_TERM_ALL: 2457 return scnc_term_all; 2458 } 2459 return CONSTSTR(NULL); 2460} 2461 2462const char * 2463ppp_error_to_string (u_int32_t native_ppp_error) 2464{ 2465 switch (native_ppp_error) { 2466 case EXIT_FATAL_ERROR: 2467 return ppp_fatal; 2468 case EXIT_OPTION_ERROR: 2469 return ppp_option; 2470 case EXIT_NOT_ROOT: 2471 return ppp_not_root; 2472 case EXIT_NO_KERNEL_SUPPORT: 2473 return ppp_no_kern; 2474 case EXIT_USER_REQUEST: 2475 return ppp_user_req; 2476 case EXIT_LOCK_FAILED: 2477 return ppp_lock_fail; 2478 case EXIT_OPEN_FAILED: 2479 return ppp_open_fail; 2480 case EXIT_CONNECT_FAILED: 2481 return ppp_conn_fail; 2482 case EXIT_PTYCMD_FAILED: 2483 return ppp_pty_fail; 2484 case EXIT_NEGOTIATION_FAILED: 2485 return ppp_nego_fail; 2486 case EXIT_PEER_AUTH_FAILED: 2487 return ppp_peer_auth_fail; 2488 case EXIT_IDLE_TIMEOUT: 2489 return ppp_idle_tmo; 2490 case EXIT_CONNECT_TIME: 2491 return ppp_sess_tmo; 2492 case EXIT_CALLBACK: 2493 return ppp_callback; 2494 case EXIT_PEER_DEAD: 2495 return ppp_peer_dead; 2496 case EXIT_HANGUP: 2497 return ppp_disco_by_dev; 2498 case EXIT_LOOPBACK: 2499 return ppp_loopback; 2500 case EXIT_INIT_FAILED: 2501 return ppp_init_fail; 2502 case EXIT_AUTH_TOPEER_FAILED: 2503 return ppp_auth_fail; 2504 case EXIT_TERMINAL_FAILED: 2505 return ppp_term_fail; 2506 case EXIT_DEVICE_ERROR: 2507 return ppp_dev_err; 2508 case EXIT_PEER_NOT_AUTHORIZED: 2509 return ppp_peer_unauth; 2510 case EXIT_CNID_AUTH_FAILED: 2511 return ppp_cnid_auth_fail; 2512 case EXIT_PEER_UNREACHABLE: 2513 return ppp_peer_unreach; 2514 } 2515 2516 return CONSTSTR(NULL); 2517} 2518 2519const char * 2520ppp_dev_error_to_string (u_int16_t subtype, u_int32_t native_dev_error) 2521{ 2522 // override with a more specific error 2523 if (native_dev_error) { 2524 switch (subtype) { 2525 case PPP_TYPE_L2TP: 2526 switch (native_dev_error) { 2527 case EXIT_L2TP_NOSERVER: 2528 return ppp_dev_no_srvr; 2529 case EXIT_L2TP_NOANSWER: 2530 return ppp_dev_no_ans; 2531 case EXIT_L2TP_PROTOCOLERROR: 2532 return ppp_dev_prot_err; 2533 case EXIT_L2TP_NETWORKCHANGED: 2534 return ppp_dev_net_chg; 2535 case EXIT_L2TP_NOSHAREDSECRET: 2536 return ppp_dev_psk; 2537 case EXIT_L2TP_NOCERTIFICATE: 2538 return ppp_dev_cert; 2539 } 2540 break; 2541 2542 case PPP_TYPE_PPTP: 2543 switch (native_dev_error) { 2544 case EXIT_PPTP_NOSERVER: 2545 return ppp_dev_no_srvr; 2546 case EXIT_PPTP_NOANSWER: 2547 return ppp_dev_no_ans; 2548 case EXIT_PPTP_PROTOCOLERROR: 2549 return ppp_dev_prot_err; 2550 case EXIT_PPTP_NETWORKCHANGED: 2551 return ppp_dev_net_chg; 2552 } 2553 break; 2554 2555 case PPP_TYPE_SERIAL: 2556 switch (native_dev_error) { 2557 case EXIT_PPPSERIAL_NOCARRIER: 2558 return ppp_dev_no_car; 2559 case EXIT_PPPSERIAL_NONUMBER: 2560 return ppp_dev_no_num; 2561 case EXIT_PPPSERIAL_BADSCRIPT: 2562 return ppp_dev_bad_script; 2563 case EXIT_PPPSERIAL_BUSY: 2564 return ppp_dev_busy; 2565 case EXIT_PPPSERIAL_NODIALTONE: 2566 return ppp_dev_no_dial; 2567 case EXIT_PPPSERIAL_ERROR: 2568 return ppp_dev_modem_err; 2569 case EXIT_PPPSERIAL_NOANSWER: 2570 return ppp_dev_no_ans; 2571 case EXIT_PPPSERIAL_HANGUP: 2572 return ppp_dev_hang; 2573 } 2574 break; 2575 2576 case PPP_TYPE_PPPoE: 2577 switch (native_dev_error) { 2578 case EXIT_PPPoE_NOSERVER: 2579 return ppp_dev_no_srvr; 2580 case EXIT_PPPoE_NOSERVICE: 2581 return ppp_dev_no_srvc; 2582 case EXIT_PPPoE_NOAC: 2583 return ppp_dev_no_ac; 2584 case EXIT_PPPoE_NOACSERVICE: 2585 return ppp_dev_no_ac_srvc; 2586 case EXIT_PPPoE_CONNREFUSED: 2587 return ppp_dev_conn_refuse; 2588 } 2589 break; 2590 } 2591 } 2592 2593 return CONSTSTR(NULL); 2594} 2595 2596const char * 2597ipsec_error_to_string (int status) 2598{ 2599 switch (status) { 2600 case IPSEC_GENERIC_ERROR: 2601 return ipsec_gen_err; 2602 case IPSEC_NOSERVERADDRESS_ERROR: 2603 return ipsec_no_srvr_addr; 2604 case IPSEC_NOSHAREDSECRET_ERROR: 2605 return ipsec_no_psk; 2606 case IPSEC_NOCERTIFICATE_ERROR: 2607 return ipsec_no_cert; 2608 case IPSEC_RESOLVEADDRESS_ERROR: 2609 return ipsec_dns_err; 2610 case IPSEC_NOLOCALNETWORK_ERROR: 2611 return ipsec_no_local; 2612 case IPSEC_CONFIGURATION_ERROR: 2613 return ipsec_cfg_err; 2614 case IPSEC_RACOONCONTROL_ERROR: 2615 return ipsec_ctrl_err; 2616 case IPSEC_CONNECTION_ERROR: 2617 return ipsec_conn_err; 2618 case IPSEC_NEGOTIATION_ERROR: 2619 return ipsec_nego_err; 2620 case IPSEC_SHAREDSECRET_ERROR: 2621 return ipsec_psk_err; 2622 case IPSEC_SERVER_CERTIFICATE_ERROR: 2623 return ipsec_srvr_cert_err; 2624 case IPSEC_CLIENT_CERTIFICATE_ERROR: 2625 return ipsec_cli_cert_err; 2626 case IPSEC_XAUTH_ERROR: 2627 return ipsec_xauth_err; 2628 case IPSEC_NETWORKCHANGE_ERROR: 2629 return ipsec_net_chg; 2630 case IPSEC_PEERDISCONNECT_ERROR: 2631 return ipsec_peer_disco; 2632 case IPSEC_PEERDEADETECTION_ERROR: 2633 return ipsec_peer_dead; 2634 case IPSEC_EDGE_ACTIVATION_ERROR: 2635 return ipsec_edge_err; 2636 case IPSEC_IDLETIMEOUT_ERROR: 2637 return ipsec_idle_tmo; 2638 case IPSEC_CLIENT_CERTIFICATE_PREMATURE: 2639 return ipsec_cli_cert_pre; 2640 case IPSEC_CLIENT_CERTIFICATE_EXPIRED: 2641 return ipsec_cli_cert_exp; 2642 case IPSEC_SERVER_CERTIFICATE_PREMATURE: 2643 return ipsec_srvr_cert_pre; 2644 case IPSEC_SERVER_CERTIFICATE_EXPIRED: 2645 return ipsec_srvr_cert_exp; 2646 case IPSEC_SERVER_CERTIFICATE_INVALID_ID: 2647 return ipsec_srvr_cert_id; 2648 } 2649 2650 return CONSTSTR(NULL); 2651} 2652 2653const char * 2654vpn_error_to_string (u_int32_t status) 2655{ 2656 switch (status) { 2657 case VPN_GENERIC_ERROR: 2658 return vpn_gen_err; 2659 case VPN_NOSERVERADDRESS_ERROR: 2660 return vpn_no_srvr_addr; 2661 case VPN_NOCERTIFICATE_ERROR: 2662 return vpn_no_cert; 2663 case VPN_RESOLVEADDRESS_ERROR: 2664 return vpn_dns_err; 2665 case VPN_NOLOCALNETWORK_ERROR: 2666 return vpn_no_local; 2667 case VPN_CONFIGURATION_ERROR: 2668 return vpn_cfg_err; 2669 case VPN_CONTROL_ERROR: 2670 return vpn_ctrl_err; 2671 case VPN_CONNECTION_ERROR: 2672 return vpn_conn_err; 2673 case VPN_NETWORKCHANGE_ERROR: 2674 return vpn_net_chg; 2675 case VPN_PEERDISCONNECT_ERROR: 2676 return vpn_peer_disco; 2677 case VPN_PEERDEADETECTION_ERROR: 2678 return vpn_peer_dead; 2679 case VPN_PEERNOTRESPONDING_ERROR: 2680 return vpn_peer_unresp; 2681 case VPN_NEGOTIATION_ERROR: 2682 return vpn_nego_err; 2683 case VPN_XAUTH_ERROR: 2684 return vpn_xauth_err; 2685 case VPN_EDGE_ACTIVATION_ERROR: 2686 return vpn_edge_err; 2687 case VPN_IDLETIMEOUT_ERROR: 2688 return vpn_idle_tmo; 2689 case VPN_ADDRESSINVALID_ERROR: 2690 return vpn_addr_invalid; 2691 case VPN_APPREQUIRED_ERROR: 2692 return vpn_ap_req; 2693 case VPN_CLIENT_CERTIFICATE_PREMATURE: 2694 return vpn_cli_cert_pre; 2695 case VPN_CLIENT_CERTIFICATE_EXPIRED: 2696 return vpn_cli_cert_exp; 2697 case VPN_SERVER_CERTIFICATE_PREMATURE: 2698 return vpn_srvr_cert_pre; 2699 case VPN_SERVER_CERTIFICATE_EXPIRED: 2700 return vpn_srvr_cert_exp; 2701 case VPN_SERVER_CERTIFICATE_INVALID_ID: 2702 return vpn_srvr_cert_id; 2703 case VPN_PLUGIN_UPDATE_REQUIRED: 2704 return vpn_plugin_upd; 2705 case VPN_PLUGIN_DISABLED: 2706 return vpn_plugin_dis; 2707 } 2708 2709 return CONSTSTR(NULL); 2710} 2711 2712/* ----------------------------------------------------------------------------- 2713 cleanup dynamic store for serv->serviceID. 2714 ----------------------------------------------------------------------------- */ 2715static void 2716removekeys( void *key, const void *value, void *context) 2717{ 2718 Boolean ret; 2719 2720 ret = SCDynamicStoreRemoveValue((SCDynamicStoreRef)context, (CFStringRef)key); 2721 if (!ret) 2722 SCLog(TRUE, LOG_ERR, CFSTR("PPP Controller: removekeys SCDynamicStoreRemoveValue fails to remove key %@."), key); 2723} 2724 2725void 2726cleanup_dynamicstore(void *serv) 2727{ 2728 CFDictionaryRef entities = NULL; 2729 CFMutableArrayRef patterns = NULL; 2730 CFStringRef pattern = NULL; 2731 2732 /* clean up dynamic store */ 2733 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, ((struct service*)serv)->serviceID, kSCCompAnyRegex); 2734 if (pattern == NULL) 2735 return; 2736 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2737 if (patterns == NULL) 2738 goto fail; 2739 CFArrayAppendValue(patterns, pattern); 2740 entities = SCDynamicStoreCopyMultiple(gDynamicStore, NULL, patterns); 2741 if (entities) 2742 CFDictionaryApplyFunction(entities, (CFDictionaryApplierFunction)removekeys, (void*)gDynamicStore); 2743 2744fail: 2745 my_CFRelease((void *)&pattern); 2746 my_CFRelease((void *)&patterns); 2747 my_CFRelease((void *)&entities); 2748} 2749 2750/* ----------------------------------------------------------------------------- 2751 Pass in the optional exceptionServiceID to find the primary interface excluding 2752 the specified service; if the exceptionServiceID is primary, find the next active 2753 service interface based on NWI order. 2754 2755 If NULL is passed for exceptionServiceID, find the true primary interface. 2756 ----------------------------------------------------------------------------- */ 2757CFStringRef copy_primary_interface_name(CFStringRef exceptionServiceID) 2758{ 2759 CFStringRef interfaceName = NULL, string = NULL, key = NULL, serviceID = NULL; 2760 CFDictionaryRef dict = NULL; 2761 Boolean mustSearchNWIOrder = FALSE; 2762 2763 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); 2764 if (key) { 2765 dict = SCDynamicStoreCopyValue(gDynamicStore, key); 2766 CFRelease(key); 2767 if (isDictionary(dict)) { 2768 string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface); 2769 if (isString(string)) { 2770 serviceID = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryService); 2771 if (serviceID && my_CFEqual(serviceID, exceptionServiceID)) { 2772 mustSearchNWIOrder = TRUE; 2773 } else { 2774 // The interface is not the exception, so allow 2775 interfaceName = CFStringCreateCopy(NULL, string); 2776 } 2777 } 2778 CFRelease(dict); 2779 } 2780 } 2781 2782 if (interfaceName == NULL && mustSearchNWIOrder && exceptionServiceID != NULL) { 2783 CFStringRef exceptionInterfaceName = copy_interface_name(exceptionServiceID); 2784 nwi_state_t nwi_state = nwi_state_copy(); 2785 if (exceptionInterfaceName && nwi_state) { 2786 for (nwi_ifstate_t interface = nwi_state_get_first_ifstate(nwi_state, AF_INET); interface != NULL; interface = nwi_ifstate_get_next(interface, AF_INET)) { 2787 char *nwi_interface_name = nwi_ifstate_get_ifname(interface); 2788 CFStringRef nwiInterfaceName = CFStringCreateWithCString(kCFAllocatorDefault, nwi_interface_name, kCFStringEncodingASCII); 2789 if (nwiInterfaceName && !my_CFEqual(nwiInterfaceName, exceptionInterfaceName)) { 2790 nwi_ifstate_flags flags = nwi_ifstate_get_flags(interface); 2791 if ((flags & NWI_IFSTATE_FLAGS_HAS_IPV4) && (flags & NWI_IFSTATE_FLAGS_HAS_DNS)) { 2792 interfaceName = my_CFRetain(nwiInterfaceName); 2793 } 2794 } 2795 my_CFRelease(&nwiInterfaceName); 2796 2797 // If we found the desired interface, exit now 2798 if (interfaceName != NULL) { 2799 break; 2800 } 2801 } 2802 } 2803 my_CFRelease(&exceptionInterfaceName); 2804 nwi_state_release(nwi_state); 2805 } 2806 2807 return interfaceName; 2808} 2809 2810/* ----------------------------------------------------------------------------- 2811 copy the string separatedy by / at index 2812 ----------------------------------------------------------------------------- */ 2813static 2814CFStringRef copy_str_at_index(CFStringRef key, int index) 2815{ 2816 2817 CFArrayRef components; 2818 CFStringRef foundstr = NULL; 2819 2820 components = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/")); 2821 if (CFArrayGetCount(components) == 5) { 2822 if ((foundstr = CFArrayGetValueAtIndex(components, index))){ 2823 CFRetain(foundstr); 2824 } 2825 } 2826 CFRelease(components); 2827 return foundstr; 2828} 2829 2830/* ----------------------------------------------------------------------------- 2831 ----------------------------------------------------------------------------- */ 2832CFStringRef copy_service_id_for_interface(CFStringRef interfaceName) 2833{ 2834 CFDictionaryRef dict = NULL; 2835 CFStringRef pattern = NULL; 2836 CFMutableArrayRef patterns = NULL; 2837 CFStringRef *keys = NULL; 2838 CFDictionaryRef *values = NULL; 2839 CFIndex count = 0; 2840 CFIndex i = 0; 2841 CFStringRef serviceID = NULL; 2842 2843 if (!isString(interfaceName)) { 2844 goto done; 2845 } 2846 2847 patterns = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 2848 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault, 2849 kSCDynamicStoreDomainState, 2850 kSCCompAnyRegex, 2851 kSCEntNetIPv4); 2852 2853 if (patterns == NULL || pattern == NULL) 2854 goto done; 2855 CFArrayAppendValue(patterns, pattern); 2856 2857 dict = SCDynamicStoreCopyMultiple(gDynamicStore, NULL, patterns); 2858 count = CFDictionaryGetCount(dict); 2859 2860 keys = calloc(count, sizeof(CFStringRef)); 2861 values = calloc(count, sizeof(CFDictionaryRef)); 2862 if (keys == NULL || values == NULL) 2863 goto done; 2864 CFDictionaryGetKeysAndValues(dict, (const void**)keys, (const void**)values); 2865 2866 for (i=0; i < count; i++) { 2867 CFDictionaryRef ipv4Dict = NULL; 2868 CFStringRef ipv4Key = NULL; 2869 2870 ipv4Key = keys[i]; 2871 ipv4Dict = values[i]; 2872 2873 if (!isString(ipv4Key) || !isDictionary(ipv4Dict)) { 2874 continue; 2875 } 2876 2877 /* Match interface name here */ 2878 if (my_CFEqual(CFDictionaryGetValue(ipv4Dict, kSCPropInterfaceName), interfaceName)) { 2879 if ((CFStringHasPrefix(ipv4Key, kSCDynamicStoreDomainState)) && (CFStringHasSuffix(ipv4Key, kSCEntNetIPv4))) { 2880 /* Copy Service ID */ 2881 serviceID = copy_str_at_index(ipv4Key, 3); 2882 } 2883 break; 2884 } 2885 } 2886 2887done: 2888 my_CFRelease(&pattern); 2889 my_CFRelease(&patterns); 2890 my_CFRelease(&dict); 2891 if (keys) { 2892 free(keys); 2893 } 2894 if (values) { 2895 free(values); 2896 } 2897 2898 return serviceID; 2899} 2900 2901/* ----------------------------------------------------------------------------- 2902 ----------------------------------------------------------------------------- */ 2903CFStringRef copy_interface_type(CFStringRef serviceID) 2904{ 2905 CFDictionaryRef interface_dict = NULL; 2906 CFStringRef interface_key = NULL; 2907 CFStringRef hardware = NULL; 2908 CFStringRef interface_type = NULL; 2909 2910 if (!isString(serviceID)) { 2911 goto done; 2912 } 2913 2914 interface_key = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault, 2915 kSCDynamicStoreDomainSetup, 2916 serviceID, 2917 kSCEntNetInterface); 2918 2919 interface_dict = SCDynamicStoreCopyValue(gDynamicStore, interface_key); 2920 if (!isDictionary(interface_dict)) { 2921 goto done; 2922 } 2923 2924 hardware = CFDictionaryGetValue(interface_dict, kSCPropNetInterfaceHardware); 2925 2926 if (isString(hardware)) { 2927 if (my_CFEqual(hardware, kSCEntNetAirPort)) { 2928 interface_type = CFRetain(kSCValNetVPNOnDemandRuleInterfaceTypeMatchWiFi); 2929 } else if (my_CFEqual(hardware, kSCEntNetEthernet)) { 2930 interface_type = CFRetain(kSCValNetVPNOnDemandRuleInterfaceTypeMatchEthernet); 2931 } 2932#if TARGET_OS_IPHONE 2933 else if (my_CFEqual(hardware, kSCEntNetCommCenter)) { 2934 interface_type = CFRetain(kSCValNetVPNOnDemandRuleInterfaceTypeMatchCellular); 2935 } 2936#endif 2937 } 2938 2939done: 2940 my_CFRelease(&interface_key); 2941 my_CFRelease(&interface_dict); 2942 2943 return interface_type; 2944} 2945 2946Boolean primary_interface_is_cellular(Boolean *hasPrimaryInterface) 2947{ 2948 Boolean isCellular = FALSE; 2949#if TARGET_OS_IPHONE 2950 Boolean foundPrimaryInterface = FALSE; 2951 nwi_state_t state = nwi_state_copy(); 2952 if (state != NULL) { 2953 int families[] = { AF_INET, AF_INET6 }; 2954 for (uint32_t i = 0; !foundPrimaryInterface && (i < sizeof(families) / sizeof(families[0])); i++) { 2955 nwi_ifstate_t ifstate; 2956 for (ifstate = nwi_state_get_first_ifstate(state, families[i]); 2957 ifstate != NULL; 2958 ifstate = nwi_ifstate_get_next(ifstate, families[i])) 2959 { 2960 if (nwi_ifstate_get_vpn_server(ifstate) != NULL) { 2961 // Skip VPN interfaces 2962 continue; 2963 } 2964 2965 foundPrimaryInterface = TRUE; 2966 isCellular = nwi_ifstate_get_reachability_flags(ifstate) & kSCNetworkReachabilityFlagsIsWWAN; 2967 break; 2968 } 2969 } 2970 nwi_state_release(state); 2971 } 2972 2973 if (hasPrimaryInterface) { 2974 *hasPrimaryInterface = foundPrimaryInterface; 2975 } 2976#endif 2977 return isCellular; 2978} 2979 2980Boolean interface_is_cellular(const char *interface_name) 2981{ 2982 Boolean isCellular = FALSE; 2983 if (interface_name == NULL) { 2984 return isCellular; 2985 } 2986 2987#if TARGET_OS_IPHONE 2988 nwi_state_t state = nwi_state_copy(); 2989 2990 if (state != NULL) { 2991 nwi_ifstate_t ifstate = nwi_state_get_ifstate(state, interface_name); 2992 if (ifstate != NULL) { 2993 isCellular = ((nwi_ifstate_get_reachability_flags(ifstate) & kSCNetworkReachabilityFlagsIsWWAN) != 0); 2994 } 2995 nwi_state_release(state); 2996 } 2997#endif 2998 2999 return isCellular; 3000} 3001 3002/* ----------------------------------------------------------------------------- 3003 ----------------------------------------------------------------------------- */ 3004CFDictionaryRef copy_dns_dict(CFStringRef serviceID) 3005{ 3006 CFStringRef dnsKey = NULL; 3007 CFDictionaryRef dnsDict = NULL; 3008 3009 if (!isString(serviceID)) { 3010 goto done; 3011 } 3012 3013 dnsKey = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault, 3014 kSCDynamicStoreDomainState, 3015 serviceID, 3016 kSCEntNetDNS); 3017 if (dnsKey == NULL) { 3018 goto done; 3019 } 3020 3021 dnsDict = SCDynamicStoreCopyValue(gDynamicStore, dnsKey); 3022 if (dnsDict == NULL) { 3023 goto done; 3024 } 3025 3026done: 3027 my_CFRelease(&dnsKey); 3028 3029 return dnsDict; 3030} 3031 3032/* ----------------------------------------------------------------------------- 3033 ----------------------------------------------------------------------------- */ 3034CFStringRef copy_interface_name(CFStringRef serviceID) 3035{ 3036 CFStringRef interfaceName = NULL; 3037 CFStringRef ipv4Key = NULL; 3038 CFDictionaryRef ipv4Dict = NULL; 3039 3040 if (!isString(serviceID)) { 3041 goto done; 3042 } 3043 3044 ipv4Key = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault, 3045 kSCDynamicStoreDomainState, 3046 serviceID, 3047 kSCEntNetIPv4); 3048 if (ipv4Key == NULL) { 3049 goto done; 3050 } 3051 3052 ipv4Dict = SCDynamicStoreCopyValue(gDynamicStore, ipv4Key); 3053 if (ipv4Dict == NULL) { 3054 goto done; 3055 } 3056 3057 interfaceName = CFDictionaryGetValue(ipv4Dict, kSCPropInterfaceName); 3058 if (interfaceName) { 3059 interfaceName = CFStringCreateCopy(kCFAllocatorDefault, interfaceName); 3060 } 3061 3062done: 3063 my_CFRelease(&ipv4Key); 3064 my_CFRelease(&ipv4Dict); 3065 3066 return interfaceName; 3067} 3068 3069/* ----------------------------------------------------------------------------- 3070 ----------------------------------------------------------------------------- */ 3071CFArrayRef 3072copy_service_order(void) 3073{ 3074 CFDictionaryRef ip_dict = NULL; 3075 CFStringRef key; 3076 CFArrayRef serviceorder = NULL; 3077 3078 key = CREATEGLOBALSETUP(kSCEntNetIPv4); 3079 if (key) { 3080 ip_dict = (CFDictionaryRef)SCDynamicStoreCopyValue(gDynamicStore, key); 3081 if (ip_dict) { 3082 serviceorder = CFDictionaryGetValue(ip_dict, kSCPropNetServiceOrder); 3083 if (serviceorder) { 3084 CFRetain(serviceorder); 3085 } 3086 CFRelease(ip_dict); 3087 } 3088 CFRelease(key); 3089 } 3090 3091 return serviceorder; 3092} 3093 3094CFStringRef scnc_copy_remote_server (struct service *serv, Boolean *isHostname) 3095{ 3096 CFStringRef remote_address_key = NULL; 3097 3098 switch (serv->type) { 3099 case TYPE_PPP: 3100 remote_address_key = kSCPropNetPPPCommRemoteAddress; 3101 break; 3102 case TYPE_IPSEC: 3103 remote_address_key = kSCPropNetIPSecRemoteAddress; 3104 break; 3105 case TYPE_VPN: 3106 remote_address_key = kSCPropNetVPNRemoteAddress; 3107 break; 3108 } 3109 3110 if (isHostname) 3111 { 3112 *isHostname = FALSE; 3113 } 3114 3115 if (remote_address_key == NULL) { 3116 return NULL; 3117 } 3118 3119 CFStringRef remote_address = CFDictionaryGetValue(serv->systemprefs, remote_address_key); 3120 if (isA_CFString(remote_address) && CFStringGetLength(remote_address) > 0) { 3121 CFCharacterSetRef slash_set = CFCharacterSetCreateWithCharactersInString(kCFAllocatorDefault, CFSTR("/")); 3122 CFCharacterSetRef colon_set = CFCharacterSetCreateWithCharactersInString(kCFAllocatorDefault, CFSTR(":")); 3123 CFRange slash_range; 3124 CFRange colon_range; 3125 3126 CFRetain(remote_address); 3127 3128 3129 if (CFStringFindCharacterFromSet(remote_address, 3130 slash_set, 3131 CFRangeMake(0, CFStringGetLength(remote_address)), 3132 0, 3133 &slash_range)) 3134 { 3135 CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, remote_address, NULL); 3136 if (url != NULL) { 3137 /* Check to see if there is a scheme on the URL. If not, add one. The hostname will not parse without a scheme */ 3138 CFRange schemeRange = CFURLGetByteRangeForComponent(url, kCFURLComponentScheme, NULL); 3139 if (schemeRange.location == kCFNotFound) { 3140 CFRelease(url); 3141 CFStringRef address = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("https://%@"), remote_address); 3142 url = CFURLCreateWithString(kCFAllocatorDefault, address, NULL); 3143 CFRelease(address); 3144 } 3145 if (url != NULL) { 3146 CFRelease(remote_address); 3147 remote_address = CFURLCopyHostName(url); 3148 CFRelease(url); 3149 } 3150 } 3151 } else if (CFStringFindCharacterFromSet(remote_address, 3152 colon_set, 3153 CFRangeMake(0, CFStringGetLength(remote_address)), 3154 0, 3155 &colon_range)) 3156 { 3157 CFStringRef address = CFStringCreateWithSubstring(kCFAllocatorDefault, 3158 remote_address, 3159 CFRangeMake(0, colon_range.location)); 3160 CFRelease(remote_address); 3161 remote_address = address; 3162 } 3163 3164 CFRelease(slash_set); 3165 CFRelease(colon_set); 3166 3167 if (remote_address == NULL) { 3168 return NULL; 3169 } 3170 3171 if (isHostname) 3172 { 3173 char *addr_cstr; 3174 CFIndex addr_cstr_len; 3175 struct sockaddr_storage sa_storage; 3176 memset(&sa_storage, 0, sizeof(sa_storage)); 3177 addr_cstr_len = CFStringGetLength(remote_address); /* Assume that the address is ASCII */ 3178 addr_cstr = CFAllocatorAllocate(kCFAllocatorDefault, addr_cstr_len + 1, 0); 3179 3180 CFStringGetCString(remote_address, addr_cstr, addr_cstr_len, kCFStringEncodingASCII); 3181 3182 if (inet_pton(AF_INET, addr_cstr, &((struct sockaddr_in *)&sa_storage)->sin_addr) == 1 || 3183 inet_pton(AF_INET6, addr_cstr, &((struct sockaddr_in6 *)&sa_storage)->sin6_addr) == 1) { 3184 *isHostname = FALSE; 3185 } else { 3186 *isHostname = TRUE; 3187 } 3188 3189 CFAllocatorDeallocate(kCFAllocatorDefault, addr_cstr); 3190 } 3191 } 3192 return remote_address; 3193} 3194 3195void 3196scnc_log(int level, CFStringRef format, ...) 3197{ 3198 if (ne_sm_bridge_is_logging_at_level(level)) { 3199 va_list args; 3200 va_start(args, format); 3201 if (!ne_sm_bridge_logv(level, format, args)) { 3202 SCLoggerVLog(NULL, level, format, args); 3203 } 3204 va_end(args); 3205 } 3206} 3207