2 * Copyright (c) 2005-2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * January 15, 2005 Allan Nathanson <ajn@apple.com>
33 #include <sys/filio.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
37 #include <sys/types.h>
39 #include <net/if_dl.h>
40 #include <net/if_media.h>
41 #include <net/if_types.h>
42 #include <net/if_var.h>
43 #include <sys/kern_event.h>
44 #include <netinet/in.h>
45 #include <netinet/in_var.h>
46 #include <netinet6/in6_var.h>
48 #include <arpa/inet.h>
50 #include <TargetConditionals.h>
51 #include <CoreFoundation/CoreFoundation.h>
52 #include <SystemConfiguration/SystemConfiguration.h>
53 #include <SystemConfiguration/SCPrivate.h>
54 #include <IOKit/IOKitLib.h>
55 #include <IOKit/IOMessage.h>
56 #include <IOKit/pwr_mgt/IOPM.h>
57 #include <IOKit/pwr_mgt/IOPMLib.h>
64 /* generic MessageTracer keys */
65 #define MSGTRACER_KEY_DOMAIN "com.apple.message.domain"
66 #define MSGTRACER_KEY_SIG "com.apple.message.signature"
67 #define MSGTRACER_KEY_UUID "com.apple.message.uuid"
68 #define MSGTRACER_KEY_VALUE1 "com.apple.message.value"
71 #define MY_ASL_FACILITY "com.apple.SystemConfiguration.Logger"
72 #define MY_MSGTRACER_DOMAIN "com.apple.network.log"
75 static aslmsg log_msg
= NULL
;
76 static io_connect_t power
= MACH_PORT_NULL
;
77 static Boolean verbose
= FALSE
;
86 struct timeval tv_diff
;
87 struct timeval tv_now
;
88 static struct timeval tv_then
= { 0, 0 };
90 (void)gettimeofday(&tv_now
, NULL
);
92 (void)localtime_r(&tv_now
.tv_sec
, &tm_now
);
94 timersub(&tv_now
, &tv_then
, &tv_diff
);
95 (void)localtime_r(&tv_diff
.tv_sec
, &tm_diff
);
97 sprintf(str
, "%2d:%02d:%02d.%03d (+%ld.%03d)",
101 tv_now
.tv_usec
/ 1000,
103 tv_diff
.tv_usec
/ 1000);
105 sprintf(str
, ".%03d (+%ld.%03d)",
106 tv_now
.tv_usec
/ 1000,
108 tv_diff
.tv_usec
/ 1000);
117 #pragma mark [Network] Kernel Events
121 copyInterfaceFlags(const char *if_name
)
123 const char * iff_up
= "? ";
125 const char *ifm_active
= "? ";
127 CFStringRef str
= NULL
;
129 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
131 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("socket() failed"));
135 bzero((char *)&ifr
, sizeof(ifr
));
136 (void) strncpy(ifr
.ifr_name
, if_name
, sizeof(ifr
.ifr_name
));
137 if (ioctl(sock
, SIOCGIFFLAGS
, (caddr_t
)&ifr
) == 0) {
138 struct ifmediareq ifm
;
140 iff_up
= (ifr
.ifr_flags
& IFF_UP
) ? "yes" : "no ";
142 bzero((char *)&ifm
, sizeof(ifm
));
143 (void) strncpy(ifm
.ifm_name
, if_name
, sizeof(ifm
.ifm_name
));
144 if ((ioctl(sock
, SIOCGIFMEDIA
, (caddr_t
)&ifm
) == 0) &&
145 (ifm
.ifm_count
> 0) &&
146 (ifm
.ifm_status
& IFM_AVALID
)) {
147 ifm_active
= (ifm
.ifm_status
& IFM_ACTIVE
) ? "yes" : "no ";
150 str
= CFStringCreateWithFormat(NULL
,
152 CFSTR("\n%-5s: IFF_UP = %s IFM_ACTIVE = %s"),
165 prefixLength(struct sockaddr_in6
*sin6
)
167 register u_int8_t
*name
= &sin6
->sin6_addr
.s6_addr
[0];
172 for (byte
= 0; byte
< sizeof(struct in6_addr
); byte
++, plen
+= 8) {
173 if (name
[byte
] != 0xff) {
178 if (byte
== sizeof(struct in6_addr
)) {
182 for (bit
= 7; bit
!= 0; bit
--, plen
++) {
183 if (!(name
[byte
] & (1 << bit
))) {
188 for (; bit
!= 0; bit
--) {
189 if (name
[byte
] & (1 << bit
)) {
195 for (; byte
< sizeof(struct in6_addr
); byte
++) {
206 KernelEvent_notification(CFSocketRef s
, CFSocketCallBackType type
, CFDataRef address
, const void *data
, void *info
)
208 int so
= CFSocketGetNative(s
);
211 struct kern_event_msg
*ev_msg
= (struct kern_event_msg
*)&buf
[0];
214 status
= recv(so
, &buf
, sizeof(buf
), 0);
216 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("recv() failed: %s"), strerror(errno
));
217 CFSocketInvalidate(s
);
221 while (offset
< status
) {
222 if ((offset
+ ev_msg
->total_size
) > status
) {
223 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("missed SYSPROTO_EVENT event, buffer not big enough"));
227 switch (ev_msg
->vendor_code
) {
228 case KEV_VENDOR_APPLE
:
229 switch (ev_msg
->kev_class
) {
230 case KEV_NETWORK_CLASS
: {
231 void *event_data
= &ev_msg
->event_data
[0];
233 switch (ev_msg
->kev_subclass
) {
234 case KEV_DL_SUBCLASS
: {
235 struct net_event_data
*ev
;
236 char if_name
[IFNAMSIZ
+1];
238 ev
= (struct net_event_data
*)event_data
;
240 bzero(&if_name
, sizeof(if_name
));
241 snprintf(if_name
, IFNAMSIZ
, "%s%d",
245 switch (ev_msg
->event_code
) {
246 case KEV_DL_IF_ATTACHED
: {
247 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
248 CFSTR("%s kernel event: %s: attached"),
253 case KEV_DL_IF_DETACHING
: {
254 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
255 CFSTR("%s kernel event: %s: detaching"),
260 case KEV_DL_IF_DETACHED
: {
261 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
262 CFSTR("%s kernel event: %s: detached"),
267 case KEV_DL_LINK_OFF
: {
270 str
= verbose
? copyInterfaceFlags(if_name
) : NULL
;
271 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
272 CFSTR("%s kernel event: %s: link down%@"),
275 str
!= NULL
? str
: CFSTR(""));
276 if (str
!= NULL
) CFRelease(str
);
279 case KEV_DL_LINK_ON
: {
282 str
= verbose
? copyInterfaceFlags(if_name
) : NULL
;
283 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
284 CFSTR("%s kernel event: %s: link up%@"),
287 str
!= NULL
? str
: CFSTR(""));
288 if (str
!= NULL
) CFRelease(str
);
296 case KEV_INET_SUBCLASS
: {
298 struct kev_in_data
*ev
;
299 char if_name
[IFNAMSIZ
+1];
302 ev
= (struct kev_in_data
*)event_data
;
304 bzero(&if_name
, sizeof(if_name
));
305 snprintf(if_name
, IFNAMSIZ
, "%s%d",
306 ev
->link_data
.if_name
,
307 ev
->link_data
.if_unit
);
309 switch (ev_msg
->event_code
) {
310 case KEV_INET_NEW_ADDR
:
311 case KEV_INET_CHANGED_ADDR
:
312 case KEV_INET_ADDR_DELETED
: {
313 struct sockaddr_in sin
;
315 bzero(&sin
, sizeof(sin
));
316 sin
.sin_len
= sizeof(sin
);
317 sin
.sin_family
= AF_INET
;
318 sin
.sin_addr
= ev
->ia_addr
;
319 _SC_sockaddr_to_string((struct sockaddr
*)&sin
, addr
, sizeof(addr
));
321 bzero(&sin
, sizeof(sin
));
322 sin
.sin_len
= sizeof(sin
);
323 sin
.sin_family
= AF_INET
;
324 sin
.sin_addr
.s_addr
= ntohl(ev
->ia_subnetmask
);
325 _SC_sockaddr_to_string((struct sockaddr
*)&sin
, mask
, sizeof(mask
));
332 switch (ev_msg
->event_code
) {
333 case KEV_INET_NEW_ADDR
: {
334 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
335 CFSTR("%s kernel event: %s: IPv4 address added (%s/%s)"),
342 case KEV_INET_CHANGED_ADDR
: {
343 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
344 CFSTR("%s kernel event: %s: IPv4 address changed (%s/%s)"),
351 case KEV_INET_ADDR_DELETED
: {
352 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
353 CFSTR("%s kernel event: %s: IPv4 address removed (%s/%s)"),
365 case KEV_INET6_SUBCLASS
: {
367 struct kev_in6_data
*ev
;
368 char if_name
[IFNAMSIZ
+1];
371 ev
= (struct kev_in6_data
*)event_data
;
373 bzero(&if_name
, sizeof(if_name
));
374 snprintf(if_name
, IFNAMSIZ
, "%s%d",
375 ev
->link_data
.if_name
,
376 ev
->link_data
.if_unit
);
378 switch (ev_msg
->event_code
) {
379 case KEV_INET6_NEW_USER_ADDR
:
380 case KEV_INET6_NEW_LL_ADDR
:
381 case KEV_INET6_CHANGED_ADDR
:
382 case KEV_INET6_ADDR_DELETED
: {
383 _SC_sockaddr_to_string((struct sockaddr
*)&ev
->ia_addr
, addr
, sizeof(addr
));
384 plen
= prefixLength(&ev
->ia_prefixmask
);
391 switch (ev_msg
->event_code
) {
392 case KEV_INET6_NEW_USER_ADDR
:
393 case KEV_INET6_NEW_LL_ADDR
: {
394 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
395 CFSTR("%s kernel event: %s: IPv6 address added (%s/%d)"),
402 case KEV_INET6_CHANGED_ADDR
: {
403 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
404 CFSTR("%s kernel event: %s: IPv6 address changed (%s/%d)"),
411 case KEV_INET6_ADDR_DELETED
: {
412 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
413 CFSTR("%s kernel event: %s: IPv6 address removed"),
433 /* unrecognized vendor code */
436 offset
+= ev_msg
->total_size
;
437 ev_msg
= (struct kern_event_msg
*)&buf
[offset
];
445 add_KernelEvent_notification()
448 CFSocketContext es_context
= { 0, NULL
, NULL
, NULL
, NULL
};
449 struct kev_request kev_req
;
450 CFRunLoopSourceRef rls
;
454 /* Open an event socket */
455 so
= socket(PF_SYSTEM
, SOCK_RAW
, SYSPROTO_EVENT
);
457 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("socket() failed"));
461 /* establish filter to return all events */
462 kev_req
.vendor_code
= 0;
463 kev_req
.kev_class
= 0; /* Not used if vendor_code is 0 */
464 kev_req
.kev_subclass
= 0; /* Not used if either kev_class OR vendor_code are 0 */
465 if (ioctl(so
, SIOCSKEVFILT
, &kev_req
) == -1) {
466 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("ioctl(, SIOCSKEVFILT, ) failed"));
471 if (ioctl(so
, FIONBIO
, &yes
) == -1) {
472 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("ioctl(, FIONBIO, ) failed"));
477 /* Create a CFSocketRef for the PF_SYSTEM kernel event socket */
478 es
= CFSocketCreateWithNative(NULL
,
480 kCFSocketReadCallBack
,
481 KernelEvent_notification
,
484 /* Create and add a run loop source for the event socket */
485 rls
= CFSocketCreateRunLoopSource(NULL
, es
, -1);
488 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
496 #pragma mark Power Management Events
500 power_notification(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
502 switch (messageType
) {
503 case kIOMessageCanDevicePowerOff
:
504 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
505 CFSTR("%s IORegisterForSystemPower: can device power off?"),
508 case kIOMessageDeviceWillPowerOff
:
509 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
510 CFSTR("%s IORegisterForSystemPower: device will power off"),
513 case kIOMessageDeviceWillNotPowerOff
:
514 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
515 CFSTR("%s IORegisterForSystemPower: device will not power off"),
518 case kIOMessageDeviceHasPoweredOn
:
519 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
520 CFSTR("%s IORegisterForSystemPower: device has powered on"),
523 case kIOMessageCanSystemPowerOff
:
524 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
525 CFSTR("%s IORegisterForSystemPower: can system power off?"),
528 case kIOMessageSystemWillPowerOff
:
529 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
530 CFSTR("%s IORegisterForSystemPower: system will power off"),
533 case kIOMessageSystemWillNotPowerOff
:
534 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
535 CFSTR("%s IORegisterForSystemPower: system will not power off"),
538 case kIOMessageCanSystemSleep
:
539 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
540 CFSTR("%s IORegisterForSystemPower: can system sleep?"),
543 * Idle sleep is about to kick in, but applications have
544 * a chance to allow sleep (by calling IOAllowPowerChange)
545 * or to prevent sleep (by calling IOCancelPowerChange).
547 IOAllowPowerChange(power
, (long)messageArgument
);
549 case kIOMessageSystemWillSleep
:
550 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
551 CFSTR("%s IORegisterForSystemPower: system will sleep"),
553 IOAllowPowerChange(power
, (long)messageArgument
);
555 case kIOMessageSystemWillNotSleep
:
556 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
557 CFSTR("%s IORegisterForSystemPower: system will not sleep"),
560 case kIOMessageSystemHasPoweredOn
:
561 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
562 CFSTR("%s IORegisterForSystemPower: system has powered on"),
565 case kIOMessageSystemWillRestart
:
566 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
567 CFSTR("%s IORegisterForSystemPower: system will restart"),
570 case kIOMessageSystemWillPowerOn
:
571 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
572 CFSTR("%s IORegisterForSystemPower: system will power on"),
576 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
577 CFSTR("%s IORegisterForSystemPower: message=%08lx"),
579 (long unsigned int)messageType
);
588 add_power_notification()
590 io_object_t iterator
;
591 IONotificationPortRef notify
;
593 power
= IORegisterForSystemPower(0, ¬ify
, power_notification
, &iterator
);
594 if (power
== MACH_PORT_NULL
) {
595 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("IORegisterForSystemPower() failed"));
599 CFRunLoopAddSource(CFRunLoopGetCurrent(),
600 IONotificationPortGetRunLoopSource(notify
),
601 kCFRunLoopCommonModes
);
607 #ifdef kIOPMMessageSleepWakeUUIDChange
609 wake_uuid_notification(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
611 CFStringRef wake_uuid
= NULL
;
613 if (messageType
== kIOPMMessageSleepWakeUUIDChange
) {
614 if (messageArgument
== kIOPMMessageSleepWakeUUIDSet
) {
615 wake_uuid
= IORegistryEntryCreateCFProperty(service
, CFSTR(kIOPMSleepWakeUUIDKey
), NULL
, 0);
618 if (wake_uuid
!= NULL
) {
621 _SC_cfstring_to_cstring(wake_uuid
, uuid
, sizeof(uuid
), kCFStringEncodingUTF8
);
622 asl_set(log_msg
, MSGTRACER_KEY_DOMAIN
, MY_MSGTRACER_DOMAIN
);
623 asl_set(log_msg
, MSGTRACER_KEY_UUID
, uuid
);
625 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
626 CFSTR("%s wake UUID notification: UUID set (%@)"),
630 CFRelease(wake_uuid
);
632 asl_unset(log_msg
, MSGTRACER_KEY_DOMAIN
);
633 asl_unset(log_msg
, MSGTRACER_KEY_UUID
);
635 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
636 CFSTR("%s wake UUID notification: UUID not set"),
646 add_wake_uuid_notification()
649 io_object_t notification
= IO_OBJECT_NULL
;
650 IONotificationPortRef notifyPort
;
651 io_service_t service
;
653 notifyPort
= IONotificationPortCreate(kIOMasterPortDefault
);
654 service
= IORegistryEntryFromPath(kIOMasterPortDefault
,
655 kIOPowerPlane
":/IOPowerConnection/IOPMrootDomain");
656 kr
= IOServiceAddInterestNotification(notifyPort
,
659 wake_uuid_notification
,
662 if (kr
!= KERN_SUCCESS
) {
663 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
,
664 CFSTR("IOServiceAddInterestNotification() failed, kr=0x%x"),
669 CFRunLoopAddSource(CFRunLoopGetCurrent(),
670 IONotificationPortGetRunLoopSource(notifyPort
),
671 kCFRunLoopDefaultMode
);
673 wake_uuid_notification(NULL
,
675 kIOPMMessageSleepWakeUUIDChange
,
676 kIOPMMessageSleepWakeUUIDSet
);
680 #endif // kIOPMMessageSleepWakeUUIDChange
684 #pragma mark SCDynamicStore "network" Events
688 NetworkChange_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
692 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
694 CFStringAppendFormat(str
,
696 CFSTR("%s SCDynamicStore \"network\" notification"),
699 n
= CFArrayGetCount(changedKeys
);
700 for (i
= 0; i
< n
; i
++) {
703 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
704 if (CFStringHasSuffix(key
, kSCEntNetLink
)) {
705 CFDictionaryRef dict
;
706 const char *val
= "?";
708 dict
= SCDynamicStoreCopyValue(store
, key
);
712 link
= CFDictionaryGetValue(dict
, kSCPropNetLinkActive
);
714 val
= CFBooleanGetValue(link
) ? "up" : "down";
719 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ (%s)"), key
, val
);
720 } else if (CFStringHasSuffix(key
, kSCEntNetIPv4
) ||
721 CFStringHasSuffix(key
, kSCEntNetIPv6
)) {
722 CFDictionaryRef dict
;
724 dict
= SCDynamicStoreCopyValue(store
, key
);
728 val
= _SCCopyDescription(dict
, NULL
);
729 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : %@"), key
, val
);
733 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : removed"), key
);
736 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
740 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
747 add_NetworkChange_notification()
751 CFMutableArrayRef keys
;
754 CFMutableArrayRef patterns
;
755 SCDynamicStoreRef store
;
756 CFRunLoopSourceRef rls
;
758 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-NetworkChange"), NetworkChange_notification
, NULL
);
760 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
764 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
765 patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
769 key
= SCDynamicStoreKeyCreateNetworkInterface(NULL
, kSCDynamicStoreDomainState
);
770 CFArrayAppendValue(keys
, key
);
775 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
776 CFArrayAppendValue(keys
, key
);
779 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv4
);
780 CFArrayAppendValue(patterns
, pattern
);
783 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv4
);
784 CFArrayAppendValue(patterns
, pattern
);
789 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv6
);
790 CFArrayAppendValue(keys
, key
);
793 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv6
);
794 CFArrayAppendValue(patterns
, pattern
);
797 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv6
);
798 CFArrayAppendValue(patterns
, pattern
);
803 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetLink
);
804 CFArrayAppendValue(patterns
, pattern
);
807 // AirPort (e.g. BSSID)
809 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetAirPort
);
810 CFArrayAppendValue(patterns
, pattern
);
815 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
816 CFArrayAppendValue(keys
, key
);
819 dns_key
= CFStringCreateWithCString(NULL
,
820 dns_configuration_notify_key(),
821 kCFStringEncodingASCII
);
822 key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("Notify:%@"), dns_key
);
824 CFArrayAppendValue(keys
, key
);
829 key
= SCDynamicStoreKeyCreateProxies(NULL
);
830 CFArrayAppendValue(keys
, key
);
833 // ComputerName, LocalHostName
835 key
= SCDynamicStoreKeyCreateComputerName(NULL
);
836 CFArrayAppendValue(keys
, key
);
839 key
= SCDynamicStoreKeyCreateHostNames(NULL
);
840 CFArrayAppendValue(keys
, key
);
843 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
);
847 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
852 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
854 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
858 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
867 PrimaryService_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
869 CFDictionaryRef entity
;
871 static CFStringRef oldPrimary
= NULL
;
872 CFStringRef newPrimary
= NULL
;
874 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
875 entity
= SCDynamicStoreCopyValue(store
, key
);
877 if (isA_CFDictionary(entity
) &&
878 CFDictionaryGetValueIfPresent(entity
,
879 kSCDynamicStorePropNetPrimaryService
,
880 (const void **)&newPrimary
) &&
881 isA_CFString(newPrimary
)) {
882 CFRetain(newPrimary
);
887 if (!_SC_CFEqual(oldPrimary
, newPrimary
)) {
888 if (newPrimary
!= NULL
) {
889 CFStringRef newInterface
;
891 newInterface
= CFDictionaryGetValue(entity
, kSCDynamicStorePropNetPrimaryInterface
);
892 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
893 CFSTR("%s Primary service: %@ (%@)"),
896 newInterface
!= NULL
? newInterface
: CFSTR("?"));
898 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
899 CFSTR("%s Primary service: removed"),
904 if (oldPrimary
!= NULL
) CFRelease(oldPrimary
);
905 oldPrimary
= newPrimary
;
907 if (entity
!= NULL
) CFRelease(entity
);
913 add_PrimaryService_notification()
916 CFMutableArrayRef keys
;
918 SCDynamicStoreRef store
;
919 CFRunLoopSourceRef rls
;
921 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-PrimaryService"), PrimaryService_notification
, NULL
);
923 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
927 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
928 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
929 CFArrayAppendValue(keys
, key
);
932 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
935 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
940 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
942 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
946 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
955 #pragma mark Reachability Events
959 reachability_notification(SCNetworkReachabilityRef ref
, SCNetworkReachabilityFlags flags
, void *info
)
961 CFStringRef hostname
= (CFStringRef
)info
;
963 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
964 CFSTR("%s reachability changed: %@: flags=0x%08x"),
973 add_reachability_notification(CFArrayRef hosts
)
975 SCNetworkReachabilityContext context
= { 0, NULL
, CFRetain
, CFRelease
, CFCopyDescription
};
978 SCNetworkReachabilityRef target
;
983 } watchAddresses
[] = { { 0, CFSTR("0.0.0.0") },
984 { IN_LINKLOCALNETNUM
, CFSTR("169.254.0.0") },
985 { (u_int32_t
)0xe00000fb, CFSTR("224.0.0.251") },
988 for (i
= 0; i
< sizeof(watchAddresses
)/sizeof(watchAddresses
[0]); i
++) {
989 struct sockaddr_in sin
;
991 bzero(&sin
, sizeof(sin
));
992 sin
.sin_len
= sizeof(sin
);
993 sin
.sin_family
= AF_INET
;
994 sin
.sin_addr
.s_addr
= htonl(watchAddresses
[i
].addr
);
996 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin
);
997 if (target
== NULL
) {
998 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityCreateWithAddress() failed"));
1002 context
.info
= (void *)watchAddresses
[i
].name
;
1003 if (!SCNetworkReachabilitySetCallback(target
, reachability_notification
, &context
)) {
1004 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilitySetCallback() failed"));
1009 if (!SCNetworkReachabilityScheduleWithRunLoop(target
, CFRunLoopGetCurrent(), kCFRunLoopCommonModes
)) {
1010 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityScheduleWithRunLoop() failed"));
1018 n
= (hosts
!= NULL
) ? CFArrayGetCount(hosts
) : 0;
1019 for (i
= 0; i
< n
; i
++) {
1023 host
= CFArrayGetValueAtIndex(hosts
, i
);
1024 if (!isA_CFString(host
) || (CFStringGetLength(host
) == 0)) {
1028 nodename
= _SC_cfstring_to_cstring(host
, NULL
, 0, kCFStringEncodingUTF8
);
1029 target
= SCNetworkReachabilityCreateWithName(NULL
, nodename
);
1030 CFAllocatorDeallocate(NULL
, nodename
);
1031 if (target
== NULL
) {
1032 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityCreateWithName() failed"));
1036 context
.info
= (void *)host
;
1037 if (!SCNetworkReachabilitySetCallback(target
, reachability_notification
, &context
)) {
1038 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilitySetCallback() failed"));
1043 if (!SCNetworkReachabilityScheduleWithRunLoop(target
, CFRunLoopGetCurrent(), kCFRunLoopCommonModes
)) {
1044 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityScheduleWithRunLoop() failed"));
1057 #pragma mark Console User/Information Events
1060 #if !TARGET_OS_EMBEDDED
1062 console_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1066 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1070 CFStringAppendFormat(str
,
1072 CFSTR("%s SCDynamicStore console notification"),
1075 user
= SCDynamicStoreCopyConsoleUser(store
, &uid
, &gid
);
1077 CFStringAppendFormat(str
, NULL
, CFSTR("\nconsole user = %@"), user
);
1080 CFStringAppendFormat(str
, NULL
, CFSTR("\nno console user"));
1083 info
= SCDynamicStoreCopyConsoleInformation(store
);
1088 n
= CFArrayGetCount(info
);
1089 for (i
= 0; i
< n
; i
++) {
1090 CFDictionaryRef session
;
1091 CFNumberRef sessionID
;
1092 CFStringRef sessionUserName
;
1093 CFBooleanRef sessionOnConsole
;
1095 session
= CFArrayGetValueAtIndex(info
, i
);
1096 sessionID
= CFDictionaryGetValue(session
, kSCConsoleSessionID
);
1097 sessionUserName
= CFDictionaryGetValue(session
, kSCConsoleSessionUserName
);
1098 sessionOnConsole
= CFDictionaryGetValue(session
, kSCConsoleSessionOnConsole
);
1100 CFStringAppendFormat(str
, NULL
, CFSTR("\n%d : id=%@, user=%@, console=%s"),
1103 sessionUserName
!= NULL
? sessionUserName
: CFSTR("?"),
1104 sessionOnConsole
!= NULL
? CFBooleanGetValue(sessionOnConsole
) ? "yes" : "no" : "?");
1110 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1117 add_console_notification()
1120 CFMutableArrayRef keys
;
1122 SCDynamicStoreRef store
;
1123 CFRunLoopSourceRef rls
;
1125 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-console"), console_notification
, NULL
);
1126 if (store
== NULL
) {
1127 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
1131 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1133 key
= SCDynamicStoreKeyCreateConsoleUser(NULL
);
1134 CFArrayAppendValue(keys
, key
);
1137 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1140 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1145 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1147 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1151 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1157 #endif // !TARGET_OS_EMBEDDED
1161 #pragma mark Directory Services Events
1164 //#include <DirectoryServices/DirServicesPriv.h>
1165 #ifndef kDSStdNotifySearchPolicyChanged
1166 #define kDSStdNotifySearchPolicyChanged "com.apple.DirectoryService.NotifyTypeStandard:SearchPolicyChanged"
1170 #if !TARGET_OS_EMBEDDED
1172 directoryServices_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1176 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1178 CFStringAppendFormat(str
,
1180 CFSTR("%s SCDynamicStore DirectoryServices notification"),
1183 n
= CFArrayGetCount(changedKeys
);
1184 for (i
= 0; i
< n
; i
++) {
1187 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
1188 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
1191 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1198 add_DirectoryServices_notification()
1201 CFMutableArrayRef keys
;
1203 SCDynamicStoreRef store
;
1204 CFRunLoopSourceRef rls
;
1206 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-directoryServices"), directoryServices_notification
, NULL
);
1207 if (store
== NULL
) {
1208 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
1212 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1214 key
= CFSTR(kDSStdNotifySearchPolicyChanged
);
1215 CFArrayAppendValue(keys
, key
);
1218 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1221 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1226 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1228 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1232 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1238 #endif // !TARGET_OS_EMBEDDED
1242 #pragma mark DNS Configuration Events
1246 dnsinfo_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1248 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1249 CFSTR("%s dnsinfo notification"),
1257 add_dnsinfo_notification()
1261 mach_port_t notify_port
;
1263 CFRunLoopSourceRef rls
;
1266 key
= dns_configuration_notify_key();
1267 status
= notify_register_mach_port(key
, ¬ify_port
, 0, ¬ify_token
);
1268 if (status
!= NOTIFY_STATUS_OK
) {
1269 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1273 mp
= CFMachPortCreateWithPort(NULL
, notify_port
, dnsinfo_notification
, NULL
, NULL
);
1275 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1276 (void)notify_cancel(notify_token
);
1280 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1282 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1284 (void)notify_cancel(notify_token
);
1287 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1296 #pragma mark Network Configuration Change Events
1299 #define NETWORKCHANGED_NOTIFY_KEY "com.apple.system.config.network_change"
1302 network_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1304 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1305 CFSTR("%s network_change notification"),
1313 add_network_notification()
1316 mach_port_t notify_port
;
1318 CFRunLoopSourceRef rls
;
1321 status
= notify_register_mach_port(NETWORKCHANGED_NOTIFY_KEY
,
1325 if (status
!= NOTIFY_STATUS_OK
) {
1326 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1330 mp
= CFMachPortCreateWithPort(NULL
, notify_port
, network_notification
, NULL
, NULL
);
1332 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1333 (void)notify_cancel(notify_token
);
1337 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1339 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1341 (void)notify_cancel(notify_token
);
1344 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1353 #pragma mark SMB Configuration Events
1356 #define SMBCONFIGURATION_NOTIFY_KEY "com.apple.system.SystemConfiguration.smb_configuration"
1359 #if !TARGET_OS_EMBEDDED
1361 smbconf_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1363 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1364 CFSTR("%s smb.conf notification"),
1372 add_smbconf_notification()
1375 mach_port_t notify_port
;
1377 CFRunLoopSourceRef rls
;
1380 status
= notify_register_mach_port(SMBCONFIGURATION_NOTIFY_KEY
,
1384 if (status
!= NOTIFY_STATUS_OK
) {
1385 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1389 mp
= CFMachPortCreateWithPort(NULL
, notify_port
, smbconf_notification
, NULL
, NULL
);
1391 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1392 (void)notify_cancel(notify_token
);
1396 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1398 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1400 (void)notify_cancel(notify_token
);
1403 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1409 #endif // !TARGET_OS_EMBEDDED
1413 #pragma mark pututxline Events
1416 #if !TARGET_OS_EMBEDDED
1418 ut_time(struct utmpx
*utmpx
)
1420 static char str
[16];
1423 (void)localtime_r(&utmpx
->ut_tv
.tv_sec
, &tm
);
1424 snprintf(str
, sizeof(str
), "%2d:%02d:%02d.%03d",
1428 utmpx
->ut_tv
.tv_usec
/ 1000);
1435 ut_id(struct utmpx
*utmpx
)
1438 static char str
[16];
1440 cp
= utmpx
->ut_id
+ sizeof(utmpx
->ut_id
);
1441 while(--cp
>= utmpx
->ut_id
&& isprint(*cp
)) {}
1442 if(cp
< utmpx
->ut_id
) {
1443 snprintf(str
, sizeof(str
), "%-4.4s", utmpx
->ut_id
);
1445 snprintf(str
, sizeof(str
),
1446 "0x%2.2x%2.2x%2.2x%2.2x",
1458 ut_pid(struct utmpx
*utmpx
)
1460 static char pid
[16];
1462 snprintf(pid
, sizeof(pid
), "%d", utmpx
->ut_pid
);
1469 pututxline_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1471 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1472 struct utmpx
*utmpx
;
1474 CFStringAppendFormat(str
,
1476 CFSTR("%s pututxline notification"),
1480 while ((utmpx
= getutxent()) != NULL
) {
1481 const char * entry_id
= NULL
;
1482 const char * entry_line
= NULL
;
1483 const char * entry_pid
= NULL
;
1484 const char * entry_tv
= NULL
;
1485 const char * entry_type
;
1486 const char * entry_user
= NULL
;
1490 switch (utmpx
->ut_type
) {
1491 case BOOT_TIME
: // Time of a system boot.
1492 entry_type
= "Boot";
1493 entry_tv
= ut_time(utmpx
);
1495 case DEAD_PROCESS
: // A session leader exited.
1496 entry_type
= "Dead process";
1497 entry_id
= ut_id (utmpx
);
1498 entry_pid
= ut_pid (utmpx
);
1499 entry_tv
= ut_time(utmpx
);
1501 case EMPTY
: // No valid user accounting information.
1503 case INIT_PROCESS
: // A process spawned by init(8).
1504 entry_type
= "Init process";
1505 entry_id
= ut_id (utmpx
);
1506 entry_pid
= ut_pid (utmpx
);
1507 entry_tv
= ut_time(utmpx
);
1509 case LOGIN_PROCESS
: // The session leader of a logged-in user.
1510 entry_type
= "Login";
1511 entry_id
= ut_id (utmpx
);
1512 entry_user
= utmpx
->ut_user
;
1513 entry_pid
= ut_pid (utmpx
);
1514 entry_tv
= ut_time(utmpx
);
1516 case NEW_TIME
: // Time after system clock change.
1517 entry_type
= "New time";
1518 entry_tv
= ut_time(utmpx
);
1520 case OLD_TIME
: // Time before system clock change.
1521 entry_type
= "Old time";
1522 entry_tv
= ut_time(utmpx
);
1524 case RUN_LVL
: // Run level. Provided for compatibility, not used.
1525 entry_type
= "Run level";
1527 case USER_PROCESS
: // A user process.
1528 entry_type
= "User Process";
1529 entry_id
= ut_id (utmpx
);
1530 entry_user
= utmpx
->ut_user
;
1531 entry_line
= utmpx
->ut_line
;
1532 entry_pid
= ut_pid (utmpx
);
1533 entry_tv
= ut_time(utmpx
);
1535 case SHUTDOWN_TIME
: // Time of system shutdown
1536 entry_type
= "Shutdown time";
1537 entry_tv
= ut_time(utmpx
);
1540 entry_type
= "Unknown";
1544 snprintf(line
, sizeof(line
),
1545 // type time id=0x12345678 pid=12345 user=abcdefgh line
1546 "\n%-13s %2s%12s %3s%-10s %4s%-5s %5s%-8s %5s%s",
1548 entry_tv
!= NULL
? "@ " : "",
1549 entry_tv
!= NULL
? entry_tv
: "", // hh:mm:ss.ddd
1550 entry_id
!= NULL
? "id=" : "",
1551 entry_id
!= NULL
? entry_id
: "", // 0x12345678
1552 entry_pid
!= NULL
? "pid=" : "",
1553 entry_pid
!= NULL
? entry_pid
: "", // #####
1554 entry_user
!= NULL
? "user=" : "",
1555 entry_user
!= NULL
? entry_user
: "", // <=256 chars
1556 entry_line
!= NULL
? "line=" : "",
1557 entry_line
!= NULL
? entry_line
: "" // <= 32 chars
1560 n
= strlen(line
) - 1;
1561 while ((n
> 0) && (line
[n
] == ' ')) {
1566 CFStringAppendFormat(str
, NULL
, CFSTR("%s"), line
);
1570 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1577 add_pututxline_notification()
1580 mach_port_t notify_port
;
1582 CFRunLoopSourceRef rls
;
1585 status
= notify_register_mach_port(UTMPX_CHANGE_NOTIFICATION
, ¬ify_port
, 0, ¬ify_token
);
1586 if (status
!= NOTIFY_STATUS_OK
) {
1587 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1591 mp
= CFMachPortCreateWithPort(NULL
, notify_port
, pututxline_notification
, NULL
, NULL
);
1593 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1594 (void)notify_cancel(notify_token
);
1598 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1600 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1602 (void)notify_cancel(notify_token
);
1605 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1611 #endif // !TARGET_OS_EMBEDDED
1615 #pragma mark BackToMyMac Status Events
1618 #ifndef kDSStdNotifyBTMMStatusChanged
1619 #define kDSStdNotifyBTMMStatusChanged "State:/Network/BackToMyMac"
1623 #if !TARGET_OS_EMBEDDED
1625 BTMM_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1629 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1631 CFStringAppendFormat(str
,
1633 CFSTR("%s SCDynamicStore Back to My Mac notification"),
1636 n
= CFArrayGetCount(changedKeys
);
1637 for (i
= 0; i
< n
; i
++) {
1639 CFDictionaryRef dict
;
1641 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
1642 dict
= SCDynamicStoreCopyValue(store
, key
);
1646 val
= _SCCopyDescription(dict
, NULL
);
1647 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : %@"), key
, val
);
1651 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : removed"), key
);
1655 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1662 add_BTMM_notification()
1665 CFMutableArrayRef keys
;
1667 SCDynamicStoreRef store
;
1668 CFRunLoopSourceRef rls
;
1670 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-BackToMyMac"), BTMM_notification
, NULL
);
1671 if (store
== NULL
) {
1672 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
1676 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1678 key
= CFSTR(kDSStdNotifyBTMMStatusChanged
);
1679 CFArrayAppendValue(keys
, key
);
1681 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1684 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1689 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1691 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1695 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1701 #endif // !TARGET_OS_EMBEDDED
1707 static inline Boolean
1708 bValFromDictionary(CFDictionaryRef dict
, CFStringRef key
)
1711 Boolean result
= FALSE
;
1713 if ((dict
!= NULL
) &&
1714 CFDictionaryGetValueIfPresent(dict
, key
, (const void **)&bVal
) &&
1715 isA_CFBoolean(bVal
)) {
1716 result
= CFBooleanGetValue(bVal
);
1724 load(CFBundleRef bundle
, Boolean bundleVerbose
)
1726 CFDictionaryRef config
;
1729 verbose
= bundleVerbose
;
1731 log_msg
= asl_new(ASL_TYPE_MSG
);
1732 asl_set(log_msg
, ASL_KEY_FACILITY
, MY_ASL_FACILITY
);
1736 config
= CFBundleGetInfoDictionary(bundle
);
1737 config
= isA_CFDictionary(config
);
1738 log_all
= bValFromDictionary(config
, CFSTR("LOG_ALL"));
1740 #ifdef kIOPMMessageSleepWakeUUIDChange
1741 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_IO_WAKEUUID_EVENTS"))) {
1742 add_wake_uuid_notification();
1744 #endif // kIOPMMessageSleepWakeUUIDChange
1746 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_IO_SYSTEMPOWER_EVENTS"))) {
1747 add_power_notification();
1750 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NETWORK_KERNEL_EVENTS"))) {
1751 add_KernelEvent_notification();
1754 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_DNS_CONFIGURATION"))) {
1755 add_dnsinfo_notification();
1758 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_NETWORK_CHANGE"))) {
1759 add_network_notification();
1762 #if !TARGET_OS_EMBEDDED
1763 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_SMB_CONFIGURATION"))) {
1764 add_smbconf_notification();
1766 #endif // !TARGET_OS_EMBEDDED
1768 #if !TARGET_OS_EMBEDDED
1769 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_UTMPX_CHANGE"))) {
1770 add_pututxline_notification();
1772 #endif // !TARGET_OS_EMBEDDED
1774 #if !TARGET_OS_EMBEDDED
1775 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_BTMM_CONFIGURATION"))) {
1776 add_BTMM_notification();
1778 #endif // !TARGET_OS_EMBEDDED
1780 #if !TARGET_OS_EMBEDDED
1781 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_CONSOLEUSER"))) {
1782 add_console_notification();
1784 #endif // !TARGET_OS_EMBEDDED
1786 #if !TARGET_OS_EMBEDDED
1787 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_DIRECTORYSERVICES_SEARCHPOLICY"))) {
1788 add_DirectoryServices_notification();
1790 #endif // !TARGET_OS_EMBEDDED
1792 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_NETWORKCHANGE"))) {
1793 add_NetworkChange_notification();
1796 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_PRIMARYSERVICE"))) {
1797 add_PrimaryService_notification();
1800 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_REACHABILITY"))) {
1801 CFArrayRef hosts
= NULL
;
1803 if ((config
== NULL
) ||
1804 !CFDictionaryGetValueIfPresent(config
, CFSTR("LOG_SC_REACHABILITY_HOSTS"), (const void **)&hosts
) ||
1805 !isA_CFArray(hosts
) ||
1806 (CFArrayGetCount(hosts
) == 0)) {
1810 add_reachability_notification(hosts
);
1819 main(int argc
, char **argv
)
1822 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
1825 load(CFBundleGetMainBundle(), (argc
> 1) ? TRUE
: FALSE
);