1/* 2 * Copyright (c) 2005-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Modification History 26 * 27 * January 15, 2005 Allan Nathanson <ajn@apple.com> 28 * - initial revision 29 */ 30 31#include <stdlib.h> 32#include <unistd.h> 33#include <sys/filio.h> 34#include <sys/ioctl.h> 35#include <sys/socket.h> 36#include <sys/time.h> 37#include <sys/types.h> 38#include <net/ethernet.h> 39#include <net/if.h> 40#include <net/if_dl.h> 41#include <net/if_media.h> 42#include <net/if_types.h> 43#include <net/if_var.h> 44#include <sys/kern_event.h> 45#include <netinet/in.h> 46#include <netinet/in_var.h> 47#include <netinet6/in6_var.h> 48#include <ifaddrs.h> 49#include <arpa/inet.h> 50 51#include <TargetConditionals.h> 52#include <CoreFoundation/CoreFoundation.h> 53#include <SystemConfiguration/SystemConfiguration.h> 54#include <SystemConfiguration/SCPrivate.h> 55#include <IOKit/IOKitLib.h> 56#include <IOKit/IOMessage.h> 57#include <IOKit/pwr_mgt/IOPM.h> 58#include <IOKit/pwr_mgt/IOPMLib.h> 59#include <IOKit/pwr_mgt/IOPMLibPrivate.h> 60 61#include <dnsinfo.h> 62#include <network_information.h> 63#include <notify.h> 64#ifndef TARGET_OS_EMBEDDED 65#include <utmpx.h> 66#include <utmpx_thread.h> 67#endif // !TARGET_OS_EMBEDDED 68 69 70/* generic MessageTracer keys */ 71#define MSGTRACER_KEY_DOMAIN "com.apple.message.domain" 72#define MSGTRACER_KEY_SIG "com.apple.message.signature" 73#define MSGTRACER_KEY_UUID "com.apple.message.uuid" 74#define MSGTRACER_KEY_VALUE1 "com.apple.message.value" 75 76 77#define MY_ASL_FACILITY "com.apple.SystemConfiguration.Logger" 78#define MY_MSGTRACER_DOMAIN "com.apple.network.log" 79 80 81static asl_object_t log_msg = NULL; 82static io_connect_t power = MACH_PORT_NULL; 83static Boolean verbose = FALSE; 84 85 86static char * 87elapsed() 88{ 89 static char str[128]; 90 struct tm tm_diff; 91 struct tm tm_now; 92 struct timeval tv_diff; 93 struct timeval tv_now; 94 static struct timeval tv_then = { 0, 0 }; 95 96 (void)gettimeofday(&tv_now, NULL); 97 98 (void)localtime_r(&tv_now.tv_sec, &tm_now); 99 100 timersub(&tv_now, &tv_then, &tv_diff); 101 (void)localtime_r(&tv_diff.tv_sec, &tm_diff); 102#ifdef MAIN 103 sprintf(str, "%2d:%02d:%02d.%03d (+%ld.%03d)", 104 tm_now.tm_hour, 105 tm_now.tm_min, 106 tm_now.tm_sec, 107 tv_now.tv_usec / 1000, 108 tv_diff.tv_sec, 109 tv_diff.tv_usec / 1000); 110#else 111 sprintf(str, ".%03d (+%ld.%03d)", 112 tv_now.tv_usec / 1000, 113 tv_diff.tv_sec, 114 tv_diff.tv_usec / 1000); 115#endif 116 117 tv_then = tv_now; 118 return str; 119} 120 121 122#pragma mark - 123#pragma mark [Network] Kernel Events 124 125 126static CFStringRef 127copyInterfaceFlags(const char *if_name) 128{ 129 const char * iff_up = "? "; 130 struct ifreq ifr; 131 const char *ifm_active = "? "; 132 int sock; 133 CFStringRef str = NULL; 134 135 sock = socket(AF_INET, SOCK_DGRAM, 0); 136 if (sock == -1) { 137 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("socket() failed")); 138 return NULL; 139 } 140 141 bzero((char *)&ifr, sizeof(ifr)); 142 (void) strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 143 if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)&ifr) == 0) { 144 struct ifmediareq ifm; 145 146 iff_up = (ifr.ifr_flags & IFF_UP) ? "yes" : "no "; 147 148 bzero((char *)&ifm, sizeof(ifm)); 149 (void) strncpy(ifm.ifm_name, if_name, sizeof(ifm.ifm_name)); 150 if ((ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifm) == 0) && 151 (ifm.ifm_count > 0) && 152 (ifm.ifm_status & IFM_AVALID)) { 153 ifm_active = (ifm.ifm_status & IFM_ACTIVE) ? "yes" : "no "; 154 } 155 156 str = CFStringCreateWithFormat(NULL, 157 NULL, 158 CFSTR("\n%-5s: IFF_UP = %s IFM_ACTIVE = %s"), 159 if_name, 160 iff_up, 161 ifm_active); 162 } 163 164 (void)close(sock); 165 166 return str; 167} 168 169 170static int 171prefixLength(struct sockaddr_in6 *sin6) 172{ 173 register u_int8_t *name = &sin6->sin6_addr.s6_addr[0]; 174 register int byte; 175 register int bit; 176 int plen = 0; 177 178 for (byte = 0; byte < sizeof(struct in6_addr); byte++, plen += 8) { 179 if (name[byte] != 0xff) { 180 break; 181 } 182 } 183 184 if (byte == sizeof(struct in6_addr)) { 185 return plen; 186 } 187 188 for (bit = 7; bit != 0; bit--, plen++) { 189 if (!(name[byte] & (1 << bit))) { 190 break; 191 } 192 } 193 194 for (; bit != 0; bit--) { 195 if (name[byte] & (1 << bit)) { 196 return 0; 197 } 198 } 199 200 byte++; 201 for (; byte < sizeof(struct in6_addr); byte++) { 202 if (name[byte]) { 203 return 0; 204 } 205 } 206 207 return plen; 208} 209 210 211static void 212KernelEvent_notification(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) 213{ 214 int so = CFSocketGetNative(s); 215 size_t status; 216 union { 217 char bytes[1024]; 218 struct kern_event_msg ev_msg1; // first kernel event 219 } buf; 220 struct kern_event_msg *ev_msg = &buf.ev_msg1; 221 size_t offset = 0; 222 223 status = recv(so, &buf, sizeof(buf), 0); 224 if (status == -1) { 225 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("recv() failed: %s"), strerror(errno)); 226 CFSocketInvalidate(s); 227 return; 228 } 229 230 while (offset < status) { 231 if ((offset + ev_msg->total_size) > status) { 232 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("missed SYSPROTO_EVENT event, buffer not big enough")); 233 break; 234 } 235 236 switch (ev_msg->vendor_code) { 237 case KEV_VENDOR_APPLE : 238 switch (ev_msg->kev_class) { 239 case KEV_NETWORK_CLASS : { 240 void *event_data = &ev_msg->event_data[0]; 241 242 switch (ev_msg->kev_subclass) { 243 case KEV_DL_SUBCLASS : { 244 struct net_event_data *ev; 245 char if_name[IFNAMSIZ]; 246 247 ev = (struct net_event_data *)event_data; 248 249 snprintf(if_name, IFNAMSIZ, "%s%d", 250 ev->if_name, 251 ev->if_unit); 252 253 switch (ev_msg->event_code) { 254 case KEV_DL_IF_ATTACHED : { 255 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 256 CFSTR("%s kernel event: %s: attached"), 257 elapsed(), 258 if_name); 259 break; 260 } 261 case KEV_DL_IF_DETACHING : { 262 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 263 CFSTR("%s kernel event: %s: detaching"), 264 elapsed(), 265 if_name); 266 break; 267 } 268 case KEV_DL_IF_DETACHED : { 269 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 270 CFSTR("%s kernel event: %s: detached"), 271 elapsed(), 272 if_name); 273 break; 274 } 275 case KEV_DL_LINK_OFF : { 276 CFStringRef str; 277 278 str = verbose ? copyInterfaceFlags(if_name) : NULL; 279 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 280 CFSTR("%s kernel event: %s: link down%@"), 281 elapsed(), 282 if_name, 283 str != NULL ? str : CFSTR("")); 284 if (str != NULL) CFRelease(str); 285 break; 286 } 287 case KEV_DL_LINK_ON : { 288 CFStringRef str; 289 290 str = verbose ? copyInterfaceFlags(if_name) : NULL; 291 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 292 CFSTR("%s kernel event: %s: link up%@"), 293 elapsed(), 294 if_name, 295 str != NULL ? str : CFSTR("")); 296 if (str != NULL) CFRelease(str); 297 break; 298 } 299 default : 300 break; 301 } 302 break; 303 } 304 case KEV_INET_SUBCLASS : { 305 char addr[128]; 306 struct kev_in_data *ev; 307 char if_name[IFNAMSIZ]; 308 char mask[128]; 309 310 ev = (struct kev_in_data *)event_data; 311 312 snprintf(if_name, IFNAMSIZ, "%s%d", 313 ev->link_data.if_name, 314 ev->link_data.if_unit); 315 316 switch (ev_msg->event_code) { 317 case KEV_INET_NEW_ADDR : 318 case KEV_INET_CHANGED_ADDR : 319 case KEV_INET_ADDR_DELETED : { 320 struct sockaddr_in sin; 321 322 bzero(&sin, sizeof(sin)); 323 sin.sin_len = sizeof(sin); 324 sin.sin_family = AF_INET; 325 sin.sin_addr = ev->ia_addr; 326 _SC_sockaddr_to_string((struct sockaddr *)&sin, addr, sizeof(addr)); 327 328 bzero(&sin, sizeof(sin)); 329 sin.sin_len = sizeof(sin); 330 sin.sin_family = AF_INET; 331 sin.sin_addr.s_addr = ntohl(ev->ia_subnetmask); 332 _SC_sockaddr_to_string((struct sockaddr *)&sin, mask, sizeof(mask)); 333 break; 334 } 335 default : 336 break; 337 } 338 339 switch (ev_msg->event_code) { 340 case KEV_INET_NEW_ADDR : { 341 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 342 CFSTR("%s kernel event: %s: IPv4 address added (%s/%s)"), 343 elapsed(), 344 if_name, 345 addr, 346 mask); 347 break; 348 } 349 case KEV_INET_CHANGED_ADDR : { 350 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 351 CFSTR("%s kernel event: %s: IPv4 address changed (%s/%s)"), 352 elapsed(), 353 if_name, 354 addr, 355 mask); 356 break; 357 } 358 case KEV_INET_ADDR_DELETED : { 359 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 360 CFSTR("%s kernel event: %s: IPv4 address removed (%s/%s)"), 361 elapsed(), 362 if_name, 363 addr, 364 mask); 365 break; 366 } 367 default : 368 break; 369 } 370 break; 371 } 372 case KEV_INET6_SUBCLASS : { 373 char addr[128]; 374 struct kev_in6_data *ev; 375 char if_name[IFNAMSIZ]; 376 int plen = 0; 377 378 ev = (struct kev_in6_data *)event_data; 379 380 snprintf(if_name, IFNAMSIZ, "%s%d", 381 ev->link_data.if_name, 382 ev->link_data.if_unit); 383 384 switch (ev_msg->event_code) { 385 case KEV_INET6_NEW_USER_ADDR : 386 case KEV_INET6_NEW_LL_ADDR : 387 case KEV_INET6_CHANGED_ADDR : 388 case KEV_INET6_ADDR_DELETED : { 389 _SC_sockaddr_to_string((struct sockaddr *)&ev->ia_addr, addr, sizeof(addr)); 390 plen = prefixLength(&ev->ia_prefixmask); 391 break; 392 } 393 default : 394 break; 395 } 396 397 switch (ev_msg->event_code) { 398 case KEV_INET6_NEW_USER_ADDR : 399 case KEV_INET6_NEW_LL_ADDR : { 400 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 401 CFSTR("%s kernel event: %s: IPv6 address added (%s/%d)"), 402 elapsed(), 403 if_name, 404 addr, 405 plen); 406 break; 407 } 408 case KEV_INET6_CHANGED_ADDR : { 409 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 410 CFSTR("%s kernel event: %s: IPv6 address changed (%s/%d)"), 411 elapsed(), 412 if_name, 413 addr, 414 plen); 415 break; 416 } 417 case KEV_INET6_ADDR_DELETED : { 418 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 419 CFSTR("%s kernel event: %s: IPv6 address removed"), 420 elapsed(), 421 if_name); 422 break; 423 } 424 default : 425 break; 426 } 427 break; 428 } 429 default : 430 break; 431 } 432 break; 433 } 434 default : 435 break; 436 } 437 break; 438 default : 439 /* unrecognized vendor code */ 440 break; 441 } 442 offset += ev_msg->total_size; 443 ev_msg = (struct kern_event_msg *)(void *)&buf.bytes[offset]; 444 } 445 446 return; 447} 448 449 450static void 451add_KernelEvent_notification() 452{ 453 CFSocketRef es; 454 CFSocketContext es_context = { 0, NULL, NULL, NULL, NULL }; 455 struct kev_request kev_req; 456 CFRunLoopSourceRef rls; 457 int so; 458 int yes = 1; 459 460 /* Open an event socket */ 461 so = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT); 462 if (so == -1) { 463 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("socket() failed")); 464 return; 465 } 466 467 /* establish filter to return all events */ 468 kev_req.vendor_code = KEV_VENDOR_APPLE; 469 kev_req.kev_class = KEV_NETWORK_CLASS; 470 kev_req.kev_subclass = KEV_ANY_SUBCLASS; 471 if (ioctl(so, SIOCSKEVFILT, &kev_req) == -1) { 472 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("ioctl(, SIOCSKEVFILT, ) failed")); 473 (void)close(so); 474 return; 475 } 476 477 if (ioctl(so, FIONBIO, &yes) == -1) { 478 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("ioctl(, FIONBIO, ) failed")); 479 (void)close(so); 480 return; 481 } 482 483 /* Create a CFSocketRef for the PF_SYSTEM kernel event socket */ 484 es = CFSocketCreateWithNative(NULL, 485 so, 486 kCFSocketReadCallBack, 487 KernelEvent_notification, 488 &es_context); 489 490 /* Create and add a run loop source for the event socket */ 491 rls = CFSocketCreateRunLoopSource(NULL, es, -1); 492 CFRelease(es); 493 494 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 495 CFRelease(rls); 496 497 return; 498} 499 500 501#pragma mark - 502#pragma mark Power Management Events 503 504 505static void 506power_notification(void *refcon, io_service_t service, natural_t messageType, void *messageArgument) 507{ 508 switch (messageType) { 509 case kIOMessageCanDevicePowerOff : 510 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 511 CFSTR("%s IORegisterForSystemPower: can device power off?"), 512 elapsed()); 513 break; 514 case kIOMessageDeviceWillPowerOff : 515 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 516 CFSTR("%s IORegisterForSystemPower: device will power off"), 517 elapsed()); 518 break; 519 case kIOMessageDeviceWillNotPowerOff : 520 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 521 CFSTR("%s IORegisterForSystemPower: device will not power off"), 522 elapsed()); 523 break; 524 case kIOMessageDeviceHasPoweredOn : 525 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 526 CFSTR("%s IORegisterForSystemPower: device has powered on"), 527 elapsed()); 528 break; 529 case kIOMessageCanSystemPowerOff : 530 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 531 CFSTR("%s IORegisterForSystemPower: can system power off?"), 532 elapsed()); 533 break; 534 case kIOMessageSystemWillPowerOff : 535 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 536 CFSTR("%s IORegisterForSystemPower: system will power off"), 537 elapsed()); 538 break; 539 case kIOMessageSystemWillNotPowerOff : 540 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 541 CFSTR("%s IORegisterForSystemPower: system will not power off"), 542 elapsed()); 543 break; 544 case kIOMessageCanSystemSleep : 545 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 546 CFSTR("%s IORegisterForSystemPower: can system sleep?"), 547 elapsed()); 548 /* 549 * Idle sleep is about to kick in, but applications have 550 * a chance to allow sleep (by calling IOAllowPowerChange) 551 * or to prevent sleep (by calling IOCancelPowerChange). 552 */ 553 IOAllowPowerChange(power, (long)messageArgument); 554 break; 555 case kIOMessageSystemWillSleep : 556 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 557 CFSTR("%s IORegisterForSystemPower: system will sleep"), 558 elapsed()); 559 IOAllowPowerChange(power, (long)messageArgument); 560 break; 561 case kIOMessageSystemWillNotSleep : 562 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 563 CFSTR("%s IORegisterForSystemPower: system will not sleep"), 564 elapsed()); 565 break; 566 case kIOMessageSystemHasPoweredOn : 567 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 568 CFSTR("%s IORegisterForSystemPower: system has powered on"), 569 elapsed()); 570 break; 571 case kIOMessageSystemWillRestart : 572 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 573 CFSTR("%s IORegisterForSystemPower: system will restart"), 574 elapsed()); 575 break; 576 case kIOMessageSystemWillPowerOn : 577 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 578 CFSTR("%s IORegisterForSystemPower: system will power on"), 579 elapsed()); 580 break; 581 default : 582 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 583 CFSTR("%s IORegisterForSystemPower: message=%08lx"), 584 elapsed(), 585 (long unsigned int)messageType); 586 break; 587 } 588 589 return; 590} 591 592 593static void 594add_power_notification() 595{ 596 io_object_t iterator; 597 IONotificationPortRef notify; 598 599 power = IORegisterForSystemPower(0, ¬ify, power_notification, &iterator); 600 if (power == MACH_PORT_NULL) { 601 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("IORegisterForSystemPower() failed")); 602 return; 603 } 604 605 CFRunLoopAddSource(CFRunLoopGetCurrent(), 606 IONotificationPortGetRunLoopSource(notify), 607 kCFRunLoopCommonModes); 608 609 return; 610} 611 612 613#ifdef kIOPMMessageSleepWakeUUIDChange 614static void 615wake_uuid_notification(void *refcon, io_service_t service, natural_t messageType, void *messageArgument) 616{ 617 CFStringRef wake_uuid = NULL; 618 619 if (messageType == kIOPMMessageSleepWakeUUIDChange) { 620 if (messageArgument == kIOPMMessageSleepWakeUUIDSet) { 621 wake_uuid = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPMSleepWakeUUIDKey), NULL, 0); 622 } 623 624 if (wake_uuid != NULL) { 625 char uuid[256]; 626 627 _SC_cfstring_to_cstring(wake_uuid, uuid, sizeof(uuid), kCFStringEncodingUTF8); 628 asl_set(log_msg, MSGTRACER_KEY_DOMAIN, MY_MSGTRACER_DOMAIN); 629 asl_set(log_msg, MSGTRACER_KEY_UUID , uuid); 630 631 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 632 CFSTR("%s wake UUID notification: UUID set (%@)"), 633 elapsed(), 634 wake_uuid); 635 636 CFRelease(wake_uuid); 637 } else { 638 asl_unset(log_msg, MSGTRACER_KEY_DOMAIN); 639 asl_unset(log_msg, MSGTRACER_KEY_UUID); 640 641 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 642 CFSTR("%s wake UUID notification: UUID not set"), 643 elapsed()); 644 } 645 } 646 647 return; 648} 649 650 651static void 652add_wake_uuid_notification() 653{ 654 kern_return_t kr; 655 io_object_t notification = IO_OBJECT_NULL; 656 IONotificationPortRef notifyPort; 657 io_service_t service; 658 659 notifyPort = IONotificationPortCreate(kIOMasterPortDefault); 660 service = IORegistryEntryFromPath(kIOMasterPortDefault, 661 kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain"); 662 kr = IOServiceAddInterestNotification(notifyPort, 663 service, 664 kIOGeneralInterest, 665 wake_uuid_notification, 666 NULL, // refCon 667 ¬ification); 668 if (kr != KERN_SUCCESS) { 669 SCLOG(NULL, NULL, ASL_LEVEL_ERR, 670 CFSTR("IOServiceAddInterestNotification() failed, kr=0x%x"), 671 kr); 672 return; 673 } 674 675 CFRunLoopAddSource(CFRunLoopGetCurrent(), 676 IONotificationPortGetRunLoopSource(notifyPort), 677 kCFRunLoopDefaultMode); 678 679 wake_uuid_notification(NULL, 680 service, 681 kIOPMMessageSleepWakeUUIDChange, 682 kIOPMMessageSleepWakeUUIDSet); 683 684 return; 685} 686#endif // kIOPMMessageSleepWakeUUIDChange 687 688 689#pragma mark - 690#pragma mark SCDynamicStore "network" Events 691 692 693static void 694NetworkChange_notification(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) 695{ 696 CFIndex i; 697 CFIndex nk; 698 CFMutableStringRef str; 699 700 str = CFStringCreateMutable(NULL, 0); 701 CFStringAppendFormat(str, 702 NULL, 703 CFSTR("%s SCDynamicStore \"network\" notification"), 704 elapsed()); 705 706 nk = CFArrayGetCount(changedKeys); 707 for (i = 0; i < nk; i++) { 708 CFArrayRef components; 709 CFStringRef key; 710 CFIndex nc; 711 712 key = CFArrayGetValueAtIndex(changedKeys, i); 713 714 components = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/")); 715 if (components == NULL) { 716 CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key); 717 continue; 718 } 719 720 nc = CFArrayGetCount(components); 721 switch (nc) { 722 case 5 : { 723 CFStringRef entity_id; 724 725 entity_id = CFArrayGetValueAtIndex(components, 4); 726 if (CFEqual(entity_id, kSCEntNetLink)) { 727 CFDictionaryRef dict; 728 const char *val = "?"; 729 730 dict = SCDynamicStoreCopyValue(store, key); 731 if (dict != NULL) { 732 CFBooleanRef link; 733 734 link = CFDictionaryGetValue(dict, kSCPropNetLinkActive); 735 if (link != NULL) { 736 val = CFBooleanGetValue(link) ? "up" : "down"; 737 } 738 739 CFRelease(dict); 740 } 741 CFStringAppendFormat(str, NULL, CFSTR("\n%@ (%s)"), key, val); 742 } else if (CFEqual(entity_id, kSCEntNetIPv4) || 743 CFEqual(entity_id, kSCEntNetIPv6) || 744 CFEqual(entity_id, kSCEntNetDNS)) { 745 CFDictionaryRef dict; 746 747 dict = SCDynamicStoreCopyValue(store, key); 748 if (dict != NULL) { 749 CFStringRef val; 750 751 val = _SCCopyDescription(dict, NULL); 752 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : %@"), key, val); 753 CFRelease(val); 754 CFRelease(dict); 755 } else { 756 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : removed"), key); 757 } 758 } else if (CFEqual(entity_id, kSCEntNetAirPort)) { 759 CFDictionaryRef dict; 760 761 dict = SCDynamicStoreCopyValue(store, key); 762 if (dict != NULL) { 763 CFStringRef ssid_str; 764 765 ssid_str = CFDictionaryGetValue(dict, CFSTR("SSID_STR")); 766 if (ssid_str != NULL) { 767 CFDataRef bssid; 768 769 bssid = CFDictionaryGetValue(dict, CFSTR("BSSID")); 770 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : SSID: %@ BSSID: %s"), 771 key, 772 ssid_str, 773 (bssid != NULL) ? ether_ntoa((struct ether_addr *)CFDataGetBytePtr(bssid)) : "<unknown>"); 774 } else { 775 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : no SSID"), key); 776 } 777 CFRelease(dict); 778 } else { 779 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : removed"), key); 780 } 781 } else if (CFEqual(entity_id, kSCEntNetService)) { 782 CFDictionaryRef dict; 783 CFStringRef rank = kSCNetworkServicePrimaryRankDefault; 784 785 dict = SCDynamicStoreCopyValue(store, key); 786 if ((dict == NULL) || 787 !CFDictionaryGetValueIfPresent(dict, 788 kSCPropNetServicePrimaryRank, 789 (const void **)&rank)) { 790 rank = kSCNetworkServicePrimaryRankDefault; 791 } 792 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : Rank = %@"), key, rank); 793 if (dict != NULL) CFRelease(dict); 794 } else { 795 CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key); 796 } 797 break; 798 } 799 800 case 4 : { 801 static CFStringRef rank_setup_prefix = NULL; 802 static CFStringRef rank_state_prefix = NULL; 803 804 if (rank_setup_prefix == NULL) { 805 rank_setup_prefix = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 806 kSCDynamicStoreDomainSetup, 807 CFSTR(""), 808 NULL); 809 rank_state_prefix = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 810 kSCDynamicStoreDomainState, 811 CFSTR(""), 812 NULL); 813 } 814 815 if (CFStringHasPrefix(key, rank_setup_prefix) || 816 CFStringHasPrefix(key, rank_state_prefix)) { 817 CFDictionaryRef dict; 818 CFStringRef rank = kSCNetworkServicePrimaryRankDefault; 819 820 dict = SCDynamicStoreCopyValue(store, key); 821 if ((dict == NULL) || 822 !CFDictionaryGetValueIfPresent(dict, 823 kSCPropNetServicePrimaryRank, 824 (const void **)&rank)) { 825 rank = kSCNetworkServicePrimaryRankDefault; 826 } 827 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : Rank = %@"), key, rank); 828 if (dict != NULL) CFRelease(dict); 829 } else { 830 CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key); 831 } 832 break; 833 } 834 835 case 2 : 836 if (CFEqual(CFArrayGetValueAtIndex(components, 1), 837 CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix))) { 838 CFNumberRef num; 839 840 num = SCDynamicStoreCopyValue(store, key); 841 if (num != NULL) { 842 IOPMSystemPowerStateCapabilities capabilities; 843 844 if (isA_CFNumber(num) && 845 CFNumberGetValue(num, kCFNumberSInt32Type, &capabilities)) { 846 CFStringAppendFormat(str, NULL, CFSTR("\n%@ (0x%x)"), key, capabilities); 847 } 848 849 CFRelease(num); 850 } 851 } else { 852 CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key); 853 } 854 break; 855 856 default : 857 CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key); 858 break; 859 } 860 861 CFRelease(components); 862 } 863 864 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, CFSTR("%@"), str); 865 CFRelease(str); 866 return; 867} 868 869 870static void 871add_NetworkChange_keys(CFMutableArrayRef keys, 872 CFMutableArrayRef patterns, 873 CFStringRef entity, 874 Boolean doGlobal, 875 Boolean doService, 876 Boolean doInterface) 877{ 878 CFStringRef key; 879 CFStringRef pattern; 880 881 if (doGlobal) { 882 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, entity); 883 CFArrayAppendValue(keys, key); 884 CFRelease(key); 885 886 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, entity); 887 CFArrayAppendValue(keys, key); 888 CFRelease(key); 889 } 890 891 if (doService) { 892 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, entity); 893 CFArrayAppendValue(patterns, pattern); 894 CFRelease(pattern); 895 896 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, entity); 897 CFArrayAppendValue(patterns, pattern); 898 CFRelease(pattern); 899 } 900 901 if (doInterface) { 902 pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, entity); 903 CFArrayAppendValue(patterns, pattern); 904 CFRelease(pattern); 905 } 906 907 return; 908} 909 910 911static void 912add_NetworkChange_notification() 913{ 914 CFStringRef dns_key; 915 CFStringRef key; 916 CFMutableArrayRef keys; 917 Boolean ok; 918 CFMutableArrayRef patterns; 919 SCDynamicStoreRef store; 920 CFRunLoopSourceRef rls; 921 922 store = SCDynamicStoreCreate(NULL, CFSTR("Logger.bundle-NetworkChange"), NetworkChange_notification, NULL); 923 if (store == NULL) { 924 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreate() failed")); 925 return; 926 } 927 928 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 929 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 930 931 // Interface list 932 933 key = SCDynamicStoreKeyCreateNetworkInterface(NULL, kSCDynamicStoreDomainState); 934 CFArrayAppendValue(keys, key); 935 CFRelease(key); 936 937 // IPv4 938 939 add_NetworkChange_keys(keys, patterns, kSCEntNetIPv4, TRUE, TRUE, TRUE); 940 941 // IPv6 942 943 add_NetworkChange_keys(keys, patterns, kSCEntNetIPv6, TRUE, TRUE, TRUE); 944 945 // PPP, VPN 946 947 add_NetworkChange_keys(keys, patterns, kSCEntNetPPP, FALSE, TRUE, TRUE); 948 add_NetworkChange_keys(keys, patterns, kSCEntNetVPN, FALSE, TRUE, TRUE); 949 add_NetworkChange_keys(keys, patterns, kSCEntNetL2TP, FALSE, TRUE, TRUE); 950 add_NetworkChange_keys(keys, patterns, kSCEntNetPPTP, FALSE, TRUE, TRUE); 951 add_NetworkChange_keys(keys, patterns, kSCEntNetIPSec, FALSE, TRUE, TRUE); 952 953 // Link 954 955 add_NetworkChange_keys(keys, patterns, kSCEntNetLink, FALSE, FALSE, TRUE); 956 957 // AirPort (e.g. BSSID) 958 959 add_NetworkChange_keys(keys, patterns, kSCEntNetAirPort, FALSE, FALSE, TRUE); 960 961 // DNS 962 963 add_NetworkChange_keys(keys, patterns, kSCEntNetDNS, TRUE, TRUE, TRUE); 964 965 dns_key = CFStringCreateWithCString(NULL, 966 dns_configuration_notify_key(), 967 kCFStringEncodingASCII); 968 key = CFStringCreateWithFormat(NULL, NULL, CFSTR("Notify:%@"), dns_key); 969 CFRelease(dns_key); 970 CFArrayAppendValue(keys, key); 971 CFRelease(key); 972 973 // Proxies 974 975 key = SCDynamicStoreKeyCreateProxies(NULL); 976 CFArrayAppendValue(keys, key); 977 CFRelease(key); 978 979 // Rank 980 981 add_NetworkChange_keys(keys, patterns, NULL, FALSE, TRUE, FALSE); // per-service 982 add_NetworkChange_keys(keys, patterns, kSCEntNetService, FALSE, FALSE, TRUE); // per-interface 983 984 // ComputerName, LocalHostName 985 986 key = SCDynamicStoreKeyCreateComputerName(NULL); 987 CFArrayAppendValue(keys, key); 988 CFRelease(key); 989 990 key = SCDynamicStoreKeyCreateHostNames(NULL); 991 CFArrayAppendValue(keys, key); 992 CFRelease(key); 993 994 // Power Management 995 996 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@%@"), 997 kSCDynamicStoreDomainState, 998 CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix)); 999 CFArrayAppendValue(keys, key); 1000 CFRelease(key); 1001 1002 1003 // Setup monitoring 1004 1005 ok = SCDynamicStoreSetNotificationKeys(store, keys, patterns); 1006 CFRelease(keys); 1007 CFRelease(patterns); 1008 if (!ok) { 1009 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreSetNotificationKeys() failed")); 1010 CFRelease(store); 1011 return; 1012 } 1013 1014 rls = SCDynamicStoreCreateRunLoopSource(NULL, store, -1); 1015 if (rls == NULL) { 1016 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1017 CFRelease(store); 1018 return; 1019 } 1020 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1021 CFRelease(rls); 1022 1023 CFRelease(store); 1024 return; 1025} 1026 1027 1028static void 1029PrimaryService_notification(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) 1030{ 1031 CFDictionaryRef entity; 1032 CFStringRef key; 1033 static CFStringRef oldPrimary = NULL; 1034 CFStringRef newPrimary = NULL; 1035 1036 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); 1037 entity = SCDynamicStoreCopyValue(store, key); 1038 CFRelease(key); 1039 if (isA_CFDictionary(entity) && 1040 CFDictionaryGetValueIfPresent(entity, 1041 kSCDynamicStorePropNetPrimaryService, 1042 (const void **)&newPrimary) && 1043 isA_CFString(newPrimary)) { 1044 CFRetain(newPrimary); 1045 } else { 1046 newPrimary = NULL; 1047 } 1048 1049 if (!_SC_CFEqual(oldPrimary, newPrimary)) { 1050 if (newPrimary != NULL) { 1051 CFStringRef newInterface; 1052 1053 newInterface = CFDictionaryGetValue(entity, kSCDynamicStorePropNetPrimaryInterface); 1054 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 1055 CFSTR("%s Primary service: %@ (%@)"), 1056 elapsed(), 1057 newPrimary, 1058 newInterface != NULL ? newInterface : CFSTR("?")); 1059 } else { 1060 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 1061 CFSTR("%s Primary service: removed"), 1062 elapsed()); 1063 } 1064 } 1065 1066 if (oldPrimary != NULL) CFRelease(oldPrimary); 1067 oldPrimary = newPrimary; 1068 1069 if (entity != NULL) CFRelease(entity); 1070 return; 1071} 1072 1073 1074static void 1075add_PrimaryService_notification() 1076{ 1077 CFStringRef key; 1078 CFMutableArrayRef keys; 1079 Boolean ok; 1080 SCDynamicStoreRef store; 1081 CFRunLoopSourceRef rls; 1082 1083 store = SCDynamicStoreCreate(NULL, CFSTR("Logger.bundle-PrimaryService"), PrimaryService_notification, NULL); 1084 if (store == NULL) { 1085 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreate() failed")); 1086 return; 1087 } 1088 1089 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1090 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); 1091 CFArrayAppendValue(keys, key); 1092 CFRelease(key); 1093 1094 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL); 1095 CFRelease(keys); 1096 if (!ok) { 1097 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreSetNotificationKeys() failed")); 1098 CFRelease(store); 1099 return; 1100 } 1101 1102 rls = SCDynamicStoreCreateRunLoopSource(NULL, store, -1); 1103 if (rls == NULL) { 1104 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1105 CFRelease(store); 1106 return; 1107 } 1108 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1109 CFRelease(rls); 1110 1111 CFRelease(store); 1112 return; 1113} 1114 1115 1116#pragma mark - 1117#pragma mark Reachability Events 1118 1119 1120static void 1121reachability_notification(SCNetworkReachabilityRef ref, SCNetworkReachabilityFlags flags, void *info) 1122{ 1123 CFStringRef hostname = (CFStringRef)info; 1124 1125 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 1126 CFSTR("%s reachability changed: %@: flags=0x%08x"), 1127 elapsed(), 1128 hostname, 1129 flags); 1130 return; 1131} 1132 1133 1134static void 1135add_reachability_notification(CFArrayRef hosts) 1136{ 1137 SCNetworkReachabilityContext context = { 0, NULL, CFRetain, CFRelease, CFCopyDescription }; 1138 CFIndex i; 1139 CFIndex n; 1140 SCNetworkReachabilityRef target; 1141 1142 struct watch { 1143 in_addr_t addr; 1144 CFStringRef name; 1145 } watchAddresses[] = { { 0, CFSTR("0.0.0.0") }, 1146 { IN_LINKLOCALNETNUM, CFSTR("169.254.0.0") }, 1147 { (u_int32_t)0xe00000fb, CFSTR("224.0.0.251") }, 1148 }; 1149 1150 for (i = 0; i < sizeof(watchAddresses)/sizeof(watchAddresses[0]); i++) { 1151 struct sockaddr_in sin; 1152 1153 bzero(&sin, sizeof(sin)); 1154 sin.sin_len = sizeof(sin); 1155 sin.sin_family = AF_INET; 1156 sin.sin_addr.s_addr = htonl(watchAddresses[i].addr); 1157 1158 target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin); 1159 if (target == NULL) { 1160 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCNetworkReachabilityCreateWithAddress() failed")); 1161 return; 1162 } 1163 1164 context.info = (void *)watchAddresses[i].name; 1165 if (!SCNetworkReachabilitySetCallback(target, reachability_notification, &context)) { 1166 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCNetworkReachabilitySetCallback() failed")); 1167 CFRelease(target); 1168 return; 1169 } 1170 1171 if (!SCNetworkReachabilityScheduleWithRunLoop(target, CFRunLoopGetCurrent(), kCFRunLoopCommonModes)) { 1172 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCNetworkReachabilityScheduleWithRunLoop() failed")); 1173 CFRelease(target); 1174 return; 1175 } 1176 1177 CFRelease(target); 1178 } 1179 1180 n = (hosts != NULL) ? CFArrayGetCount(hosts) : 0; 1181 for (i = 0; i < n; i++) { 1182 CFStringRef host; 1183 char *nodename; 1184 1185 host = CFArrayGetValueAtIndex(hosts, i); 1186 if (!isA_CFString(host) || (CFStringGetLength(host) == 0)) { 1187 continue; 1188 } 1189 1190 nodename = _SC_cfstring_to_cstring(host, NULL, 0, kCFStringEncodingUTF8); 1191 target = SCNetworkReachabilityCreateWithName(NULL, nodename); 1192 CFAllocatorDeallocate(NULL, nodename); 1193 if (target == NULL) { 1194 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCNetworkReachabilityCreateWithName() failed")); 1195 return; 1196 } 1197 1198 context.info = (void *)host; 1199 if (!SCNetworkReachabilitySetCallback(target, reachability_notification, &context)) { 1200 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCNetworkReachabilitySetCallback() failed")); 1201 CFRelease(target); 1202 return; 1203 } 1204 1205 if (!SCNetworkReachabilityScheduleWithRunLoop(target, CFRunLoopGetCurrent(), kCFRunLoopCommonModes)) { 1206 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCNetworkReachabilityScheduleWithRunLoop() failed")); 1207 CFRelease(target); 1208 return; 1209 } 1210 1211 CFRelease(target); 1212 } 1213 1214 return; 1215} 1216 1217 1218#pragma mark - 1219#pragma mark Console User/Information Events 1220 1221 1222#if !TARGET_OS_EMBEDDED 1223static void 1224console_notification(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) 1225{ 1226 gid_t gid; 1227 CFArrayRef info; 1228 CFMutableStringRef str = CFStringCreateMutable(NULL, 0); 1229 uid_t uid; 1230 CFStringRef user; 1231 1232 CFStringAppendFormat(str, 1233 NULL, 1234 CFSTR("%s SCDynamicStore console notification"), 1235 elapsed()); 1236 1237 user = SCDynamicStoreCopyConsoleUser(store, &uid, &gid); 1238 if (user != NULL) { 1239 CFStringAppendFormat(str, NULL, CFSTR("\nconsole user = %@"), user); 1240 CFRelease(user); 1241 } else { 1242 CFStringAppendFormat(str, NULL, CFSTR("\nno console user")); 1243 } 1244 1245 info = SCDynamicStoreCopyConsoleInformation(store); 1246 if (info != NULL) { 1247 CFIndex i; 1248 CFIndex n; 1249 1250 n = CFArrayGetCount(info); 1251 for (i = 0; i < n; i++) { 1252 CFDictionaryRef session; 1253 CFNumberRef sessionID; 1254 CFStringRef sessionUserName; 1255 CFBooleanRef sessionOnConsole; 1256 1257 session = CFArrayGetValueAtIndex(info, i); 1258 sessionID = CFDictionaryGetValue(session, kSCConsoleSessionID); 1259 sessionUserName = CFDictionaryGetValue(session, kSCConsoleSessionUserName); 1260 sessionOnConsole = CFDictionaryGetValue(session, kSCConsoleSessionOnConsole); 1261 1262 CFStringAppendFormat(str, NULL, CFSTR("\n%ld : id=%@, user=%@, console=%s"), 1263 i, 1264 sessionID, 1265 sessionUserName != NULL ? sessionUserName : CFSTR("?"), 1266 sessionOnConsole != NULL ? CFBooleanGetValue(sessionOnConsole) ? "yes" : "no" : "?"); 1267 } 1268 1269 CFRelease(info); 1270 } 1271 1272 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, CFSTR("%@"), str); 1273 CFRelease(str); 1274 return; 1275} 1276 1277 1278static void 1279add_console_notification() 1280{ 1281 CFStringRef key; 1282 CFMutableArrayRef keys; 1283 Boolean ok; 1284 SCDynamicStoreRef store; 1285 CFRunLoopSourceRef rls; 1286 1287 store = SCDynamicStoreCreate(NULL, CFSTR("Logger.bundle-console"), console_notification, NULL); 1288 if (store == NULL) { 1289 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreate() failed")); 1290 return; 1291 } 1292 1293 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1294 1295 key = SCDynamicStoreKeyCreateConsoleUser(NULL); 1296 CFArrayAppendValue(keys, key); 1297 CFRelease(key); 1298 1299 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL); 1300 CFRelease(keys); 1301 if (!ok) { 1302 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreSetNotificationKeys() failed")); 1303 CFRelease(store); 1304 return; 1305 } 1306 1307 rls = SCDynamicStoreCreateRunLoopSource(NULL, store, -1); 1308 if (rls == NULL) { 1309 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1310 CFRelease(store); 1311 return; 1312 } 1313 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1314 CFRelease(rls); 1315 1316 CFRelease(store); 1317 return; 1318} 1319#endif // !TARGET_OS_EMBEDDED 1320 1321 1322#pragma mark - 1323#pragma mark Directory Services Events 1324 1325 1326//#include <DirectoryServices/DirServicesPriv.h> 1327#ifndef kDSStdNotifySearchPolicyChanged 1328#define kDSStdNotifySearchPolicyChanged "com.apple.DirectoryService.NotifyTypeStandard:SearchPolicyChanged" 1329#endif 1330 1331 1332#if !TARGET_OS_EMBEDDED 1333static void 1334directoryServices_notification(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) 1335{ 1336 CFIndex i; 1337 CFIndex n; 1338 CFMutableStringRef str = CFStringCreateMutable(NULL, 0); 1339 1340 CFStringAppendFormat(str, 1341 NULL, 1342 CFSTR("%s SCDynamicStore DirectoryServices notification"), 1343 elapsed()); 1344 1345 n = CFArrayGetCount(changedKeys); 1346 for (i = 0; i < n; i++) { 1347 CFStringRef key; 1348 1349 key = CFArrayGetValueAtIndex(changedKeys, i); 1350 CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key); 1351 } 1352 1353 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, CFSTR("%@"), str); 1354 CFRelease(str); 1355 return; 1356} 1357 1358 1359static void 1360add_DirectoryServices_notification() 1361{ 1362 CFStringRef key; 1363 CFMutableArrayRef keys; 1364 Boolean ok; 1365 SCDynamicStoreRef store; 1366 CFRunLoopSourceRef rls; 1367 1368 store = SCDynamicStoreCreate(NULL, CFSTR("Logger.bundle-directoryServices"), directoryServices_notification, NULL); 1369 if (store == NULL) { 1370 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreate() failed")); 1371 return; 1372 } 1373 1374 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1375 1376 key = CFSTR(kDSStdNotifySearchPolicyChanged); 1377 CFArrayAppendValue(keys, key); 1378// CFRelease(key); 1379 1380 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL); 1381 CFRelease(keys); 1382 if (!ok) { 1383 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreSetNotificationKeys() failed")); 1384 CFRelease(store); 1385 return; 1386 } 1387 1388 rls = SCDynamicStoreCreateRunLoopSource(NULL, store, -1); 1389 if (rls == NULL) { 1390 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1391 CFRelease(store); 1392 return; 1393 } 1394 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1395 CFRelease(rls); 1396 1397 CFRelease(store); 1398 return; 1399} 1400#endif // !TARGET_OS_EMBEDDED 1401 1402 1403#pragma mark - 1404#pragma mark DNS Configuration Events 1405 1406 1407static void 1408dnsinfo_notification(CFMachPortRef port, void *msg, CFIndex size, void *info) 1409{ 1410 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 1411 CFSTR("%s dnsinfo notification"), 1412 elapsed()); 1413 1414 return; 1415} 1416 1417 1418static void 1419add_dnsinfo_notification() 1420{ 1421 const char *key; 1422 CFMachPortRef mp; 1423 mach_port_t notify_port; 1424 int notify_token; 1425 CFRunLoopSourceRef rls; 1426 uint32_t status; 1427 1428 key = dns_configuration_notify_key(); 1429 status = notify_register_mach_port(key, ¬ify_port, 0, ¬ify_token); 1430 if (status != NOTIFY_STATUS_OK) { 1431 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("notify_register_mach_port() failed")); 1432 return; 1433 } 1434 1435 mp = _SC_CFMachPortCreateWithPort("Logger/dns_configuration", notify_port, dnsinfo_notification, NULL); 1436 if (mp == NULL) { 1437 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("CFMachPortCreateWithPort() failed")); 1438 (void)notify_cancel(notify_token); 1439 return; 1440 } 1441 1442 rls = CFMachPortCreateRunLoopSource(NULL, mp, -1); 1443 if (rls == NULL) { 1444 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1445 CFRelease(mp); 1446 (void)notify_cancel(notify_token); 1447 return; 1448 } 1449 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1450 CFRelease(rls); 1451 1452 CFRelease(mp); 1453 return; 1454} 1455 1456 1457#pragma mark - 1458#pragma mark Network Information Events 1459 1460 1461static void 1462nwi_notification(CFMachPortRef port, void *msg, CFIndex size, void *info) 1463{ 1464 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 1465 CFSTR("%s network_information notification"), 1466 elapsed()); 1467 1468 return; 1469} 1470 1471 1472static void 1473add_nwi_notification() 1474{ 1475 const char *key; 1476 CFMachPortRef mp; 1477 mach_port_t notify_port; 1478 int notify_token; 1479 CFRunLoopSourceRef rls; 1480 uint32_t status; 1481 1482 key = nwi_state_get_notify_key(); 1483 status = notify_register_mach_port(key, ¬ify_port, 0, ¬ify_token); 1484 if (status != NOTIFY_STATUS_OK) { 1485 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("notify_register_mach_port() failed")); 1486 return; 1487 } 1488 1489 mp = _SC_CFMachPortCreateWithPort("Logger/nwi", notify_port, nwi_notification, NULL); 1490 if (mp == NULL) { 1491 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("CFMachPortCreateWithPort() failed")); 1492 (void)notify_cancel(notify_token); 1493 return; 1494 } 1495 1496 rls = CFMachPortCreateRunLoopSource(NULL, mp, -1); 1497 if (rls == NULL) { 1498 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1499 CFRelease(mp); 1500 (void)notify_cancel(notify_token); 1501 return; 1502 } 1503 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1504 CFRelease(rls); 1505 1506 CFRelease(mp); 1507 return; 1508} 1509 1510 1511#pragma mark - 1512#pragma mark Network Configuration Change Events 1513 1514 1515static void 1516network_notification(CFMachPortRef port, void *msg, CFIndex size, void *info) 1517{ 1518 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 1519 CFSTR("%s network_change notification"), 1520 elapsed()); 1521 1522 return; 1523} 1524 1525 1526static void 1527add_network_notification() 1528{ 1529 CFMachPortRef mp; 1530 mach_port_t notify_port; 1531 int notify_token; 1532 CFRunLoopSourceRef rls; 1533 uint32_t status; 1534 1535 status = notify_register_mach_port(_SC_NOTIFY_NETWORK_CHANGE, 1536 ¬ify_port, 1537 0, 1538 ¬ify_token); 1539 if (status != NOTIFY_STATUS_OK) { 1540 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("notify_register_mach_port() failed")); 1541 return; 1542 } 1543 1544 mp = _SC_CFMachPortCreateWithPort("Logger/network_change", notify_port, network_notification, NULL); 1545 if (mp == NULL) { 1546 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("CFMachPortCreateWithPort() failed")); 1547 (void)notify_cancel(notify_token); 1548 return; 1549 } 1550 1551 rls = CFMachPortCreateRunLoopSource(NULL, mp, -1); 1552 if (rls == NULL) { 1553 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1554 CFRelease(mp); 1555 (void)notify_cancel(notify_token); 1556 return; 1557 } 1558 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1559 CFRelease(rls); 1560 1561 CFRelease(mp); 1562 return; 1563} 1564 1565 1566#pragma mark - 1567#pragma mark SMB Configuration Events 1568 1569 1570#define SMBCONFIGURATION_NOTIFY_KEY "com.apple.system.SystemConfiguration.smb_configuration" 1571 1572 1573#if !TARGET_OS_EMBEDDED 1574static void 1575smbconf_notification(CFMachPortRef port, void *msg, CFIndex size, void *info) 1576{ 1577 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, 1578 CFSTR("%s smb.conf notification"), 1579 elapsed()); 1580 1581 return; 1582} 1583 1584 1585static void 1586add_smbconf_notification() 1587{ 1588 CFMachPortRef mp; 1589 mach_port_t notify_port; 1590 int notify_token; 1591 CFRunLoopSourceRef rls; 1592 uint32_t status; 1593 1594 status = notify_register_mach_port(SMBCONFIGURATION_NOTIFY_KEY, 1595 ¬ify_port, 1596 0, 1597 ¬ify_token); 1598 if (status != NOTIFY_STATUS_OK) { 1599 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("notify_register_mach_port() failed")); 1600 return; 1601 } 1602 1603 mp = _SC_CFMachPortCreateWithPort("Logger/smb_configuration", notify_port, smbconf_notification, NULL); 1604 if (mp == NULL) { 1605 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("CFMachPortCreateWithPort() failed")); 1606 (void)notify_cancel(notify_token); 1607 return; 1608 } 1609 1610 rls = CFMachPortCreateRunLoopSource(NULL, mp, -1); 1611 if (rls == NULL) { 1612 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1613 CFRelease(mp); 1614 (void)notify_cancel(notify_token); 1615 return; 1616 } 1617 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1618 CFRelease(rls); 1619 1620 CFRelease(mp); 1621 return; 1622} 1623#endif // !TARGET_OS_EMBEDDED 1624 1625 1626#pragma mark - 1627#pragma mark pututxline Events 1628 1629 1630#ifndef TARGET_OS_EMBEDDED 1631static const char * 1632ut_time(struct utmpx *utmpx) 1633{ 1634 static char str[16]; 1635 struct tm tm; 1636 1637 (void)localtime_r(&utmpx->ut_tv.tv_sec, &tm); 1638 snprintf(str, sizeof(str), "%2d:%02d:%02d.%03d", 1639 tm.tm_hour, 1640 tm.tm_min, 1641 tm.tm_sec, 1642 utmpx->ut_tv.tv_usec / 1000); 1643 1644 return str; 1645} 1646 1647 1648static const char * 1649ut_id(struct utmpx *utmpx) 1650{ 1651 char *cp; 1652 static char str[16]; 1653 1654 cp = utmpx->ut_id + sizeof(utmpx->ut_id); 1655 while(--cp >= utmpx->ut_id && isprint(*cp)) {} 1656 if(cp < utmpx->ut_id) { 1657 snprintf(str, sizeof(str), "%-4.4s", utmpx->ut_id); 1658 } else { 1659 snprintf(str, sizeof(str), 1660 "0x%2.2x%2.2x%2.2x%2.2x", 1661 utmpx->ut_id[0], 1662 utmpx->ut_id[1], 1663 utmpx->ut_id[2], 1664 utmpx->ut_id[3]); 1665 } 1666 1667 return str; 1668} 1669 1670 1671static const char * 1672ut_pid(struct utmpx *utmpx) 1673{ 1674 static char pid[16]; 1675 1676 snprintf(pid, sizeof(pid), "%d", utmpx->ut_pid); 1677 1678 return pid; 1679} 1680 1681 1682static void 1683pututxline_notification(CFMachPortRef port, void *msg, CFIndex size, void *info) 1684{ 1685 CFMutableStringRef str = CFStringCreateMutable(NULL, 0); 1686 struct utmpx *utmpx; 1687 utmpx_t utx; 1688 1689 CFStringAppendFormat(str, 1690 NULL, 1691 CFSTR("%s pututxline notification"), 1692 elapsed()); 1693 1694 utx = _openutx(NULL); 1695 while ((utmpx = _getutxent(utx)) != NULL) { 1696 const char * entry_id = NULL; 1697 const char * entry_line = NULL; 1698 const char * entry_pid = NULL; 1699 const char * entry_tv = NULL; 1700 const char * entry_type; 1701 const char * entry_user = NULL; 1702 char line[128]; 1703 int n; 1704 1705 switch (utmpx->ut_type) { 1706 case BOOT_TIME : // Time of a system boot. 1707 entry_type = "Boot"; 1708 entry_tv = ut_time(utmpx); 1709 break; 1710 case DEAD_PROCESS : // A session leader exited. 1711 entry_type = "Dead process"; 1712 entry_id = ut_id (utmpx); 1713 entry_pid = ut_pid (utmpx); 1714 entry_tv = ut_time(utmpx); 1715 break; 1716 case EMPTY : // No valid user accounting information. 1717 continue; 1718 case INIT_PROCESS : // A process spawned by init(8). 1719 entry_type = "Init process"; 1720 entry_id = ut_id (utmpx); 1721 entry_pid = ut_pid (utmpx); 1722 entry_tv = ut_time(utmpx); 1723 break; 1724 case LOGIN_PROCESS : // The session leader of a logged-in user. 1725 entry_type = "Login"; 1726 entry_id = ut_id (utmpx); 1727 entry_user = utmpx->ut_user; 1728 entry_pid = ut_pid (utmpx); 1729 entry_tv = ut_time(utmpx); 1730 break; 1731 case NEW_TIME : // Time after system clock change. 1732 entry_type = "New time"; 1733 entry_tv = ut_time(utmpx); 1734 break; 1735 case OLD_TIME : // Time before system clock change. 1736 entry_type = "Old time"; 1737 entry_tv = ut_time(utmpx); 1738 break; 1739 case RUN_LVL : // Run level. Provided for compatibility, not used. 1740 entry_type = "Run level"; 1741 break; 1742 case USER_PROCESS : // A user process. 1743 entry_type = "User Process"; 1744 entry_id = ut_id (utmpx); 1745 entry_user = utmpx->ut_user; 1746 entry_line = utmpx->ut_line; 1747 entry_pid = ut_pid (utmpx); 1748 entry_tv = ut_time(utmpx); 1749 break; 1750 case SHUTDOWN_TIME : // Time of system shutdown 1751 entry_type = "Shutdown time"; 1752 entry_tv = ut_time(utmpx); 1753 break; 1754 default : 1755 entry_type = "Unknown"; 1756 break; 1757 } 1758 1759 snprintf(line, sizeof(line), 1760 // type time id=0x12345678 pid=12345 user=abcdefgh line 1761 "\n%-13s %2s%12s %3s%-10s %4s%-5s %5s%-8s %5s%s", 1762 entry_type, 1763 entry_tv != NULL ? "@ " : "", 1764 entry_tv != NULL ? entry_tv : "", // hh:mm:ss.ddd 1765 entry_id != NULL ? "id=" : "", 1766 entry_id != NULL ? entry_id : "", // 0x12345678 1767 entry_pid != NULL ? "pid=" : "", 1768 entry_pid != NULL ? entry_pid : "", // ##### 1769 entry_user != NULL ? "user=" : "", 1770 entry_user != NULL ? entry_user : "", // <=256 chars 1771 entry_line != NULL ? "line=" : "", 1772 entry_line != NULL ? entry_line : "" // <= 32 chars 1773 ); 1774 1775 n = (int)strlen(line) - 1; 1776 while ((n > 0) && (line[n] == ' ')) { 1777 line[n] = '\0'; 1778 --n; 1779 } 1780 1781 CFStringAppendFormat(str, NULL, CFSTR("%s"), line); 1782 } 1783 _endutxent(utx); 1784 1785 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, CFSTR("%@"), str); 1786 CFRelease(str); 1787 return; 1788} 1789 1790 1791static void 1792add_pututxline_notification() 1793{ 1794 CFMachPortRef mp; 1795 mach_port_t notify_port; 1796 int notify_token; 1797 CFRunLoopSourceRef rls; 1798 uint32_t status; 1799 1800 status = notify_register_mach_port(UTMPX_CHANGE_NOTIFICATION, ¬ify_port, 0, ¬ify_token); 1801 if (status != NOTIFY_STATUS_OK) { 1802 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("notify_register_mach_port() failed")); 1803 return; 1804 } 1805 1806 mp = _SC_CFMachPortCreateWithPort("Logger/utmpx", notify_port, pututxline_notification, NULL); 1807 if (mp == NULL) { 1808 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("CFMachPortCreateWithPort() failed")); 1809 (void)notify_cancel(notify_token); 1810 return; 1811 } 1812 1813 rls = CFMachPortCreateRunLoopSource(NULL, mp, -1); 1814 if (rls == NULL) { 1815 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1816 CFRelease(mp); 1817 (void)notify_cancel(notify_token); 1818 return; 1819 } 1820 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1821 CFRelease(rls); 1822 1823 CFRelease(mp); 1824 return; 1825} 1826#endif // !TARGET_OS_EMBEDDED 1827 1828 1829#pragma mark - 1830#pragma mark BackToMyMac Status Events 1831 1832 1833#ifndef kDSStdNotifyBTMMStatusChanged 1834#define kDSStdNotifyBTMMStatusChanged "State:/Network/BackToMyMac" 1835#endif 1836 1837 1838#if !TARGET_OS_EMBEDDED 1839static void 1840BTMM_notification(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) 1841{ 1842 CFIndex i; 1843 CFIndex n; 1844 CFMutableStringRef str = CFStringCreateMutable(NULL, 0); 1845 1846 CFStringAppendFormat(str, 1847 NULL, 1848 CFSTR("%s SCDynamicStore Back to My Mac notification"), 1849 elapsed()); 1850 1851 n = CFArrayGetCount(changedKeys); 1852 for (i = 0; i < n; i++) { 1853 CFStringRef key; 1854 CFDictionaryRef dict; 1855 1856 key = CFArrayGetValueAtIndex(changedKeys, i); 1857 dict = SCDynamicStoreCopyValue(store, key); 1858 if (dict != NULL) { 1859 CFStringRef val; 1860 1861 val = _SCCopyDescription(dict, NULL); 1862 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : %@"), key, val); 1863 CFRelease(val); 1864 CFRelease(dict); 1865 } else { 1866 CFStringAppendFormat(str, NULL, CFSTR("\n%@ : removed"), key); 1867 } 1868 } 1869 1870 SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, CFSTR("%@"), str); 1871 CFRelease(str); 1872 return; 1873} 1874 1875 1876static void 1877add_BTMM_notification() 1878{ 1879 CFStringRef key; 1880 CFMutableArrayRef keys; 1881 Boolean ok; 1882 SCDynamicStoreRef store; 1883 CFRunLoopSourceRef rls; 1884 1885 store = SCDynamicStoreCreate(NULL, CFSTR("Logger.bundle-BackToMyMac"), BTMM_notification, NULL); 1886 if (store == NULL) { 1887 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreate() failed")); 1888 return; 1889 } 1890 1891 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1892 1893 key = CFSTR(kDSStdNotifyBTMMStatusChanged); 1894 CFArrayAppendValue(keys, key); 1895 1896 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL); 1897 CFRelease(keys); 1898 if (!ok) { 1899 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreSetNotificationKeys() failed")); 1900 CFRelease(store); 1901 return; 1902 } 1903 1904 rls = SCDynamicStoreCreateRunLoopSource(NULL, store, -1); 1905 if (rls == NULL) { 1906 SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed")); 1907 CFRelease(store); 1908 return; 1909 } 1910 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 1911 CFRelease(rls); 1912 1913 CFRelease(store); 1914 return; 1915} 1916#endif // !TARGET_OS_EMBEDDED 1917 1918 1919#pragma mark - 1920 1921 1922static __inline__ Boolean 1923bValFromDictionary(CFDictionaryRef dict, CFStringRef key) 1924{ 1925 CFBooleanRef bVal; 1926 Boolean result = FALSE; 1927 1928 if ((dict != NULL) && 1929 CFDictionaryGetValueIfPresent(dict, key, (const void **)&bVal) && 1930 isA_CFBoolean(bVal)) { 1931 result = CFBooleanGetValue(bVal); 1932 } 1933 1934 return result; 1935} 1936 1937 1938void 1939load(CFBundleRef bundle, Boolean bundleVerbose) 1940{ 1941 CFDictionaryRef config; 1942 Boolean log_all; 1943 1944 verbose = bundleVerbose; 1945 1946 log_msg = asl_new(ASL_TYPE_MSG); 1947 asl_set(log_msg, ASL_KEY_FACILITY, MY_ASL_FACILITY); 1948 1949 elapsed(); 1950 1951 config = CFBundleGetInfoDictionary(bundle); 1952 config = isA_CFDictionary(config); 1953 log_all = bValFromDictionary(config, CFSTR("LOG_ALL")); 1954 1955#ifdef kIOPMMessageSleepWakeUUIDChange 1956 if (log_all || bValFromDictionary(config, CFSTR("LOG_IO_WAKEUUID_EVENTS"))) { 1957 add_wake_uuid_notification(); 1958 } 1959#endif // kIOPMMessageSleepWakeUUIDChange 1960 1961 if (log_all || bValFromDictionary(config, CFSTR("LOG_IO_SYSTEMPOWER_EVENTS"))) { 1962 add_power_notification(); 1963 } 1964 1965 if (log_all || bValFromDictionary(config, CFSTR("LOG_NETWORK_KERNEL_EVENTS"))) { 1966 add_KernelEvent_notification(); 1967 } 1968 1969 if (log_all || bValFromDictionary(config, CFSTR("LOG_NETWORK_INFORMATION"))) { 1970 add_nwi_notification(); 1971 } 1972 1973 if (log_all || bValFromDictionary(config, CFSTR("LOG_NOTIFY_DNS_CONFIGURATION"))) { 1974 add_dnsinfo_notification(); 1975 } 1976 1977 if (log_all || bValFromDictionary(config, CFSTR("LOG_NOTIFY_NETWORK_CHANGE"))) { 1978 add_network_notification(); 1979 } 1980 1981#if !TARGET_OS_EMBEDDED 1982 if (log_all || bValFromDictionary(config, CFSTR("LOG_NOTIFY_SMB_CONFIGURATION"))) { 1983 add_smbconf_notification(); 1984 } 1985#endif // !TARGET_OS_EMBEDDED 1986 1987#ifndef TARGET_OS_EMBEDDED 1988 if (log_all || bValFromDictionary(config, CFSTR("LOG_NOTIFY_UTMPX_CHANGE"))) { 1989 add_pututxline_notification(); 1990 } 1991#endif // !TARGET_OS_EMBEDDED 1992 1993#if !TARGET_OS_EMBEDDED 1994 if (log_all || bValFromDictionary(config, CFSTR("LOG_SC_BTMM_CONFIGURATION"))) { 1995 add_BTMM_notification(); 1996 } 1997#endif // !TARGET_OS_EMBEDDED 1998 1999#if !TARGET_OS_EMBEDDED 2000 if (log_all || bValFromDictionary(config, CFSTR("LOG_SC_CONSOLEUSER"))) { 2001 add_console_notification(); 2002 } 2003#endif // !TARGET_OS_EMBEDDED 2004 2005#if !TARGET_OS_EMBEDDED 2006 if (log_all || bValFromDictionary(config, CFSTR("LOG_SC_DIRECTORYSERVICES_SEARCHPOLICY"))) { 2007 add_DirectoryServices_notification(); 2008 } 2009#endif // !TARGET_OS_EMBEDDED 2010 2011 if (log_all || bValFromDictionary(config, CFSTR("LOG_SC_NETWORKCHANGE"))) { 2012 add_NetworkChange_notification(); 2013 } 2014 2015 if (log_all || bValFromDictionary(config, CFSTR("LOG_SC_PRIMARYSERVICE"))) { 2016 add_PrimaryService_notification(); 2017 } 2018 2019 if (log_all || bValFromDictionary(config, CFSTR("LOG_SC_REACHABILITY"))) { 2020 CFArrayRef hosts = NULL; 2021 2022 if ((config == NULL) || 2023 !CFDictionaryGetValueIfPresent(config, CFSTR("LOG_SC_REACHABILITY_HOSTS"), (const void **)&hosts) || 2024 !isA_CFArray(hosts) || 2025 (CFArrayGetCount(hosts) == 0)) { 2026 hosts = NULL; 2027 } 2028 2029 if (verbose) { 2030 _sc_debug = TRUE; 2031 } 2032 2033 add_reachability_notification(hosts); 2034 } 2035 2036 return; 2037} 2038 2039#ifdef MAIN 2040 2041int 2042main(int argc, char **argv) 2043{ 2044 _sc_log = FALSE; 2045 _sc_verbose = (argc > 1) ? TRUE : FALSE; 2046 _sc_debug = TRUE; 2047 2048 load(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE); 2049 CFRunLoopRun(); 2050 /* not reached */ 2051 exit(0); 2052 return 0; 2053} 2054 2055#endif /* MAIN */ 2056