2 * Copyright (c) 2005-2011 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>
38 #include <net/ethernet.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>
49 #include <arpa/inet.h>
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>
62 #include <network_information.h>
64 #if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
66 #include <utmpx_thread.h>
67 #endif // !(__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
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"
77 #define MY_ASL_FACILITY "com.apple.SystemConfiguration.Logger"
78 #define MY_MSGTRACER_DOMAIN "com.apple.network.log"
81 static aslmsg log_msg
= NULL
;
82 static io_connect_t power
= MACH_PORT_NULL
;
83 static Boolean verbose
= FALSE
;
92 struct timeval tv_diff
;
93 struct timeval tv_now
;
94 static struct timeval tv_then
= { 0, 0 };
96 (void)gettimeofday(&tv_now
, NULL
);
98 (void)localtime_r(&tv_now
.tv_sec
, &tm_now
);
100 timersub(&tv_now
, &tv_then
, &tv_diff
);
101 (void)localtime_r(&tv_diff
.tv_sec
, &tm_diff
);
103 sprintf(str
, "%2d:%02d:%02d.%03d (+%ld.%03d)",
107 tv_now
.tv_usec
/ 1000,
109 tv_diff
.tv_usec
/ 1000);
111 sprintf(str
, ".%03d (+%ld.%03d)",
112 tv_now
.tv_usec
/ 1000,
114 tv_diff
.tv_usec
/ 1000);
123 #pragma mark [Network] Kernel Events
127 copyInterfaceFlags(const char *if_name
)
129 const char * iff_up
= "? ";
131 const char *ifm_active
= "? ";
133 CFStringRef str
= NULL
;
135 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
137 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("socket() failed"));
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
;
146 iff_up
= (ifr
.ifr_flags
& IFF_UP
) ? "yes" : "no ";
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 ";
156 str
= CFStringCreateWithFormat(NULL
,
158 CFSTR("\n%-5s: IFF_UP = %s IFM_ACTIVE = %s"),
171 prefixLength(struct sockaddr_in6
*sin6
)
173 register u_int8_t
*name
= &sin6
->sin6_addr
.s6_addr
[0];
178 for (byte
= 0; byte
< sizeof(struct in6_addr
); byte
++, plen
+= 8) {
179 if (name
[byte
] != 0xff) {
184 if (byte
== sizeof(struct in6_addr
)) {
188 for (bit
= 7; bit
!= 0; bit
--, plen
++) {
189 if (!(name
[byte
] & (1 << bit
))) {
194 for (; bit
!= 0; bit
--) {
195 if (name
[byte
] & (1 << bit
)) {
201 for (; byte
< sizeof(struct in6_addr
); byte
++) {
212 KernelEvent_notification(CFSocketRef s
, CFSocketCallBackType type
, CFDataRef address
, const void *data
, void *info
)
214 int so
= CFSocketGetNative(s
);
218 struct kern_event_msg ev_msg1
; // first kernel event
220 struct kern_event_msg
*ev_msg
= &buf
.ev_msg1
;
223 status
= recv(so
, &buf
, sizeof(buf
), 0);
225 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("recv() failed: %s"), strerror(errno
));
226 CFSocketInvalidate(s
);
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"));
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];
242 switch (ev_msg
->kev_subclass
) {
243 case KEV_DL_SUBCLASS
: {
244 struct net_event_data
*ev
;
245 char if_name
[IFNAMSIZ
];
247 ev
= (struct net_event_data
*)event_data
;
249 snprintf(if_name
, IFNAMSIZ
, "%s%d",
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"),
261 case KEV_DL_IF_DETACHING
: {
262 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
263 CFSTR("%s kernel event: %s: detaching"),
268 case KEV_DL_IF_DETACHED
: {
269 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
270 CFSTR("%s kernel event: %s: detached"),
275 case KEV_DL_LINK_OFF
: {
278 str
= verbose
? copyInterfaceFlags(if_name
) : NULL
;
279 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
280 CFSTR("%s kernel event: %s: link down%@"),
283 str
!= NULL
? str
: CFSTR(""));
284 if (str
!= NULL
) CFRelease(str
);
287 case KEV_DL_LINK_ON
: {
290 str
= verbose
? copyInterfaceFlags(if_name
) : NULL
;
291 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
292 CFSTR("%s kernel event: %s: link up%@"),
295 str
!= NULL
? str
: CFSTR(""));
296 if (str
!= NULL
) CFRelease(str
);
304 case KEV_INET_SUBCLASS
: {
306 struct kev_in_data
*ev
;
307 char if_name
[IFNAMSIZ
];
310 ev
= (struct kev_in_data
*)event_data
;
312 snprintf(if_name
, IFNAMSIZ
, "%s%d",
313 ev
->link_data
.if_name
,
314 ev
->link_data
.if_unit
);
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
;
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
));
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
));
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)"),
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)"),
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)"),
372 case KEV_INET6_SUBCLASS
: {
374 struct kev_in6_data
*ev
;
375 char if_name
[IFNAMSIZ
];
378 ev
= (struct kev_in6_data
*)event_data
;
380 snprintf(if_name
, IFNAMSIZ
, "%s%d",
381 ev
->link_data
.if_name
,
382 ev
->link_data
.if_unit
);
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
);
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)"),
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)"),
417 case KEV_INET6_ADDR_DELETED
: {
418 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
419 CFSTR("%s kernel event: %s: IPv6 address removed"),
439 /* unrecognized vendor code */
442 offset
+= ev_msg
->total_size
;
443 ev_msg
= (struct kern_event_msg
*)(void *)&buf
.bytes
[offset
];
451 add_KernelEvent_notification()
454 CFSocketContext es_context
= { 0, NULL
, NULL
, NULL
, NULL
};
455 struct kev_request kev_req
;
456 CFRunLoopSourceRef rls
;
460 /* Open an event socket */
461 so
= socket(PF_SYSTEM
, SOCK_RAW
, SYSPROTO_EVENT
);
463 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("socket() failed"));
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"));
477 if (ioctl(so
, FIONBIO
, &yes
) == -1) {
478 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("ioctl(, FIONBIO, ) failed"));
483 /* Create a CFSocketRef for the PF_SYSTEM kernel event socket */
484 es
= CFSocketCreateWithNative(NULL
,
486 kCFSocketReadCallBack
,
487 KernelEvent_notification
,
490 /* Create and add a run loop source for the event socket */
491 rls
= CFSocketCreateRunLoopSource(NULL
, es
, -1);
494 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
502 #pragma mark Power Management Events
506 power_notification(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
508 switch (messageType
) {
509 case kIOMessageCanDevicePowerOff
:
510 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
511 CFSTR("%s IORegisterForSystemPower: can device power off?"),
514 case kIOMessageDeviceWillPowerOff
:
515 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
516 CFSTR("%s IORegisterForSystemPower: device will power off"),
519 case kIOMessageDeviceWillNotPowerOff
:
520 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
521 CFSTR("%s IORegisterForSystemPower: device will not power off"),
524 case kIOMessageDeviceHasPoweredOn
:
525 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
526 CFSTR("%s IORegisterForSystemPower: device has powered on"),
529 case kIOMessageCanSystemPowerOff
:
530 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
531 CFSTR("%s IORegisterForSystemPower: can system power off?"),
534 case kIOMessageSystemWillPowerOff
:
535 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
536 CFSTR("%s IORegisterForSystemPower: system will power off"),
539 case kIOMessageSystemWillNotPowerOff
:
540 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
541 CFSTR("%s IORegisterForSystemPower: system will not power off"),
544 case kIOMessageCanSystemSleep
:
545 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
546 CFSTR("%s IORegisterForSystemPower: can system sleep?"),
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).
553 IOAllowPowerChange(power
, (long)messageArgument
);
555 case kIOMessageSystemWillSleep
:
556 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
557 CFSTR("%s IORegisterForSystemPower: system will sleep"),
559 IOAllowPowerChange(power
, (long)messageArgument
);
561 case kIOMessageSystemWillNotSleep
:
562 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
563 CFSTR("%s IORegisterForSystemPower: system will not sleep"),
566 case kIOMessageSystemHasPoweredOn
:
567 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
568 CFSTR("%s IORegisterForSystemPower: system has powered on"),
571 case kIOMessageSystemWillRestart
:
572 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
573 CFSTR("%s IORegisterForSystemPower: system will restart"),
576 case kIOMessageSystemWillPowerOn
:
577 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
578 CFSTR("%s IORegisterForSystemPower: system will power on"),
582 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
583 CFSTR("%s IORegisterForSystemPower: message=%08lx"),
585 (long unsigned int)messageType
);
594 add_power_notification()
596 io_object_t iterator
;
597 IONotificationPortRef notify
;
599 power
= IORegisterForSystemPower(0, ¬ify
, power_notification
, &iterator
);
600 if (power
== MACH_PORT_NULL
) {
601 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("IORegisterForSystemPower() failed"));
605 CFRunLoopAddSource(CFRunLoopGetCurrent(),
606 IONotificationPortGetRunLoopSource(notify
),
607 kCFRunLoopCommonModes
);
613 #ifdef kIOPMMessageSleepWakeUUIDChange
615 wake_uuid_notification(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
617 CFStringRef wake_uuid
= NULL
;
619 if (messageType
== kIOPMMessageSleepWakeUUIDChange
) {
620 if (messageArgument
== kIOPMMessageSleepWakeUUIDSet
) {
621 wake_uuid
= IORegistryEntryCreateCFProperty(service
, CFSTR(kIOPMSleepWakeUUIDKey
), NULL
, 0);
624 if (wake_uuid
!= NULL
) {
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
);
631 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
632 CFSTR("%s wake UUID notification: UUID set (%@)"),
636 CFRelease(wake_uuid
);
638 asl_unset(log_msg
, MSGTRACER_KEY_DOMAIN
);
639 asl_unset(log_msg
, MSGTRACER_KEY_UUID
);
641 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
642 CFSTR("%s wake UUID notification: UUID not set"),
652 add_wake_uuid_notification()
655 io_object_t notification
= IO_OBJECT_NULL
;
656 IONotificationPortRef notifyPort
;
657 io_service_t service
;
659 notifyPort
= IONotificationPortCreate(kIOMasterPortDefault
);
660 service
= IORegistryEntryFromPath(kIOMasterPortDefault
,
661 kIOPowerPlane
":/IOPowerConnection/IOPMrootDomain");
662 kr
= IOServiceAddInterestNotification(notifyPort
,
665 wake_uuid_notification
,
668 if (kr
!= KERN_SUCCESS
) {
669 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
,
670 CFSTR("IOServiceAddInterestNotification() failed, kr=0x%x"),
675 CFRunLoopAddSource(CFRunLoopGetCurrent(),
676 IONotificationPortGetRunLoopSource(notifyPort
),
677 kCFRunLoopDefaultMode
);
679 wake_uuid_notification(NULL
,
681 kIOPMMessageSleepWakeUUIDChange
,
682 kIOPMMessageSleepWakeUUIDSet
);
686 #endif // kIOPMMessageSleepWakeUUIDChange
690 #pragma mark SCDynamicStore "network" Events
694 NetworkChange_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
698 CFMutableStringRef str
;
700 str
= CFStringCreateMutable(NULL
, 0);
701 CFStringAppendFormat(str
,
703 CFSTR("%s SCDynamicStore \"network\" notification"),
706 nk
= CFArrayGetCount(changedKeys
);
707 for (i
= 0; i
< nk
; i
++) {
708 CFArrayRef components
;
712 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
714 components
= CFStringCreateArrayBySeparatingStrings(NULL
, key
, CFSTR("/"));
715 if (components
== NULL
) {
716 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
720 nc
= CFArrayGetCount(components
);
723 CFStringRef entity_id
;
725 entity_id
= CFArrayGetValueAtIndex(components
, 4);
726 if (CFEqual(entity_id
, kSCEntNetLink
)) {
727 CFDictionaryRef dict
;
728 const char *val
= "?";
730 dict
= SCDynamicStoreCopyValue(store
, key
);
734 link
= CFDictionaryGetValue(dict
, kSCPropNetLinkActive
);
736 val
= CFBooleanGetValue(link
) ? "up" : "down";
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
;
747 dict
= SCDynamicStoreCopyValue(store
, key
);
751 val
= _SCCopyDescription(dict
, NULL
);
752 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : %@"), key
, val
);
756 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : removed"), key
);
758 } else if (CFEqual(entity_id
, kSCEntNetAirPort
)) {
759 CFDictionaryRef dict
;
761 dict
= SCDynamicStoreCopyValue(store
, key
);
763 CFStringRef ssid_str
;
765 ssid_str
= CFDictionaryGetValue(dict
, CFSTR("SSID_STR"));
766 if (ssid_str
!= NULL
) {
769 bssid
= CFDictionaryGetValue(dict
, CFSTR("BSSID"));
770 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : SSID: %@ BSSID: %s"),
773 (bssid
!= NULL
) ? ether_ntoa((struct ether_addr
*)CFDataGetBytePtr(bssid
)) : "<unknown>");
775 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : no SSID"), key
);
779 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : removed"), key
);
781 } else if (CFEqual(entity_id
, kSCEntNetService
)) {
782 CFDictionaryRef dict
;
783 CFStringRef rank
= kSCNetworkServicePrimaryRankDefault
;
785 dict
= SCDynamicStoreCopyValue(store
, key
);
786 if ((dict
== NULL
) ||
787 !CFDictionaryGetValueIfPresent(dict
,
788 kSCPropNetServicePrimaryRank
,
789 (const void **)&rank
)) {
790 rank
= kSCNetworkServicePrimaryRankDefault
;
792 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : Rank = %@"), key
, rank
);
793 if (dict
!= NULL
) CFRelease(dict
);
795 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
801 static CFStringRef rank_setup_prefix
= NULL
;
802 static CFStringRef rank_state_prefix
= NULL
;
804 if (rank_setup_prefix
== NULL
) {
805 rank_setup_prefix
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
806 kSCDynamicStoreDomainSetup
,
809 rank_state_prefix
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
810 kSCDynamicStoreDomainState
,
815 if (CFStringHasPrefix(key
, rank_setup_prefix
) ||
816 CFStringHasPrefix(key
, rank_state_prefix
)) {
817 CFDictionaryRef dict
;
818 CFStringRef rank
= kSCNetworkServicePrimaryRankDefault
;
820 dict
= SCDynamicStoreCopyValue(store
, key
);
821 if ((dict
== NULL
) ||
822 !CFDictionaryGetValueIfPresent(dict
,
823 kSCPropNetServicePrimaryRank
,
824 (const void **)&rank
)) {
825 rank
= kSCNetworkServicePrimaryRankDefault
;
827 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : Rank = %@"), key
, rank
);
828 if (dict
!= NULL
) CFRelease(dict
);
830 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
836 if (CFEqual(CFArrayGetValueAtIndex(components
, 1),
837 CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix
))) {
840 num
= SCDynamicStoreCopyValue(store
, key
);
842 IOPMSystemPowerStateCapabilities capabilities
;
844 if (isA_CFNumber(num
) &&
845 CFNumberGetValue(num
, kCFNumberSInt32Type
, &capabilities
)) {
846 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ (0x%x)"), key
, capabilities
);
852 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
857 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
861 CFRelease(components
);
864 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
871 add_NetworkChange_keys(CFMutableArrayRef keys
,
872 CFMutableArrayRef patterns
,
882 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainSetup
, entity
);
883 CFArrayAppendValue(keys
, key
);
886 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, entity
);
887 CFArrayAppendValue(keys
, key
);
892 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, kSCDynamicStoreDomainSetup
, kSCCompAnyRegex
, entity
);
893 CFArrayAppendValue(patterns
, pattern
);
896 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, entity
);
897 CFArrayAppendValue(patterns
, pattern
);
902 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, entity
);
903 CFArrayAppendValue(patterns
, pattern
);
912 add_NetworkChange_notification()
916 CFMutableArrayRef keys
;
918 CFMutableArrayRef patterns
;
919 SCDynamicStoreRef store
;
920 CFRunLoopSourceRef rls
;
922 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-NetworkChange"), NetworkChange_notification
, NULL
);
924 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
928 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
929 patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
933 key
= SCDynamicStoreKeyCreateNetworkInterface(NULL
, kSCDynamicStoreDomainState
);
934 CFArrayAppendValue(keys
, key
);
939 add_NetworkChange_keys(keys
, patterns
, kSCEntNetIPv4
, TRUE
, TRUE
, TRUE
);
943 add_NetworkChange_keys(keys
, patterns
, kSCEntNetIPv6
, TRUE
, TRUE
, TRUE
);
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
);
955 add_NetworkChange_keys(keys
, patterns
, kSCEntNetLink
, FALSE
, FALSE
, TRUE
);
957 // AirPort (e.g. BSSID)
959 add_NetworkChange_keys(keys
, patterns
, kSCEntNetAirPort
, FALSE
, FALSE
, TRUE
);
963 add_NetworkChange_keys(keys
, patterns
, kSCEntNetDNS
, TRUE
, TRUE
, TRUE
);
965 dns_key
= CFStringCreateWithCString(NULL
,
966 dns_configuration_notify_key(),
967 kCFStringEncodingASCII
);
968 key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("Notify:%@"), dns_key
);
970 CFArrayAppendValue(keys
, key
);
975 key
= SCDynamicStoreKeyCreateProxies(NULL
);
976 CFArrayAppendValue(keys
, key
);
981 add_NetworkChange_keys(keys
, patterns
, NULL
, FALSE
, TRUE
, FALSE
); // per-service
982 add_NetworkChange_keys(keys
, patterns
, kSCEntNetService
, FALSE
, FALSE
, TRUE
); // per-interface
984 // ComputerName, LocalHostName
986 key
= SCDynamicStoreKeyCreateComputerName(NULL
);
987 CFArrayAppendValue(keys
, key
);
990 key
= SCDynamicStoreKeyCreateHostNames(NULL
);
991 CFArrayAppendValue(keys
, key
);
996 key
= SCDynamicStoreKeyCreate(NULL
, CFSTR("%@%@"),
997 kSCDynamicStoreDomainState
,
998 CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix
));
999 CFArrayAppendValue(keys
, key
);
1005 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
);
1007 CFRelease(patterns
);
1009 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1014 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1016 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1020 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1029 PrimaryService_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1031 CFDictionaryRef entity
;
1033 static CFStringRef oldPrimary
= NULL
;
1034 CFStringRef newPrimary
= NULL
;
1036 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
1037 entity
= SCDynamicStoreCopyValue(store
, key
);
1039 if (isA_CFDictionary(entity
) &&
1040 CFDictionaryGetValueIfPresent(entity
,
1041 kSCDynamicStorePropNetPrimaryService
,
1042 (const void **)&newPrimary
) &&
1043 isA_CFString(newPrimary
)) {
1044 CFRetain(newPrimary
);
1049 if (!_SC_CFEqual(oldPrimary
, newPrimary
)) {
1050 if (newPrimary
!= NULL
) {
1051 CFStringRef newInterface
;
1053 newInterface
= CFDictionaryGetValue(entity
, kSCDynamicStorePropNetPrimaryInterface
);
1054 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1055 CFSTR("%s Primary service: %@ (%@)"),
1058 newInterface
!= NULL
? newInterface
: CFSTR("?"));
1060 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1061 CFSTR("%s Primary service: removed"),
1066 if (oldPrimary
!= NULL
) CFRelease(oldPrimary
);
1067 oldPrimary
= newPrimary
;
1069 if (entity
!= NULL
) CFRelease(entity
);
1075 add_PrimaryService_notification()
1078 CFMutableArrayRef keys
;
1080 SCDynamicStoreRef store
;
1081 CFRunLoopSourceRef rls
;
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"));
1089 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1090 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
1091 CFArrayAppendValue(keys
, key
);
1094 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1097 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1102 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1104 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1108 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1117 #pragma mark Reachability Events
1121 reachability_notification(SCNetworkReachabilityRef ref
, SCNetworkReachabilityFlags flags
, void *info
)
1123 CFStringRef hostname
= (CFStringRef
)info
;
1125 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1126 CFSTR("%s reachability changed: %@: flags=0x%08x"),
1135 add_reachability_notification(CFArrayRef hosts
)
1137 SCNetworkReachabilityContext context
= { 0, NULL
, CFRetain
, CFRelease
, CFCopyDescription
};
1140 SCNetworkReachabilityRef target
;
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") },
1150 for (i
= 0; i
< sizeof(watchAddresses
)/sizeof(watchAddresses
[0]); i
++) {
1151 struct sockaddr_in sin
;
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
);
1158 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin
);
1159 if (target
== NULL
) {
1160 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityCreateWithAddress() failed"));
1164 context
.info
= (void *)watchAddresses
[i
].name
;
1165 if (!SCNetworkReachabilitySetCallback(target
, reachability_notification
, &context
)) {
1166 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilitySetCallback() failed"));
1171 if (!SCNetworkReachabilityScheduleWithRunLoop(target
, CFRunLoopGetCurrent(), kCFRunLoopCommonModes
)) {
1172 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityScheduleWithRunLoop() failed"));
1180 n
= (hosts
!= NULL
) ? CFArrayGetCount(hosts
) : 0;
1181 for (i
= 0; i
< n
; i
++) {
1185 host
= CFArrayGetValueAtIndex(hosts
, i
);
1186 if (!isA_CFString(host
) || (CFStringGetLength(host
) == 0)) {
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"));
1198 context
.info
= (void *)host
;
1199 if (!SCNetworkReachabilitySetCallback(target
, reachability_notification
, &context
)) {
1200 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilitySetCallback() failed"));
1205 if (!SCNetworkReachabilityScheduleWithRunLoop(target
, CFRunLoopGetCurrent(), kCFRunLoopCommonModes
)) {
1206 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityScheduleWithRunLoop() failed"));
1219 #pragma mark Console User/Information Events
1222 #if !TARGET_OS_EMBEDDED
1224 console_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1228 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1232 CFStringAppendFormat(str
,
1234 CFSTR("%s SCDynamicStore console notification"),
1237 user
= SCDynamicStoreCopyConsoleUser(store
, &uid
, &gid
);
1239 CFStringAppendFormat(str
, NULL
, CFSTR("\nconsole user = %@"), user
);
1242 CFStringAppendFormat(str
, NULL
, CFSTR("\nno console user"));
1245 info
= SCDynamicStoreCopyConsoleInformation(store
);
1250 n
= CFArrayGetCount(info
);
1251 for (i
= 0; i
< n
; i
++) {
1252 CFDictionaryRef session
;
1253 CFNumberRef sessionID
;
1254 CFStringRef sessionUserName
;
1255 CFBooleanRef sessionOnConsole
;
1257 session
= CFArrayGetValueAtIndex(info
, i
);
1258 sessionID
= CFDictionaryGetValue(session
, kSCConsoleSessionID
);
1259 sessionUserName
= CFDictionaryGetValue(session
, kSCConsoleSessionUserName
);
1260 sessionOnConsole
= CFDictionaryGetValue(session
, kSCConsoleSessionOnConsole
);
1262 CFStringAppendFormat(str
, NULL
, CFSTR("\n%d : id=%@, user=%@, console=%s"),
1265 sessionUserName
!= NULL
? sessionUserName
: CFSTR("?"),
1266 sessionOnConsole
!= NULL
? CFBooleanGetValue(sessionOnConsole
) ? "yes" : "no" : "?");
1272 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1279 add_console_notification()
1282 CFMutableArrayRef keys
;
1284 SCDynamicStoreRef store
;
1285 CFRunLoopSourceRef rls
;
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"));
1293 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1295 key
= SCDynamicStoreKeyCreateConsoleUser(NULL
);
1296 CFArrayAppendValue(keys
, key
);
1299 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1302 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1307 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1309 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1313 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1319 #endif // !TARGET_OS_EMBEDDED
1323 #pragma mark Directory Services Events
1326 //#include <DirectoryServices/DirServicesPriv.h>
1327 #ifndef kDSStdNotifySearchPolicyChanged
1328 #define kDSStdNotifySearchPolicyChanged "com.apple.DirectoryService.NotifyTypeStandard:SearchPolicyChanged"
1332 #if !TARGET_OS_EMBEDDED
1334 directoryServices_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1338 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1340 CFStringAppendFormat(str
,
1342 CFSTR("%s SCDynamicStore DirectoryServices notification"),
1345 n
= CFArrayGetCount(changedKeys
);
1346 for (i
= 0; i
< n
; i
++) {
1349 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
1350 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
1353 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1360 add_DirectoryServices_notification()
1363 CFMutableArrayRef keys
;
1365 SCDynamicStoreRef store
;
1366 CFRunLoopSourceRef rls
;
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"));
1374 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1376 key
= CFSTR(kDSStdNotifySearchPolicyChanged
);
1377 CFArrayAppendValue(keys
, key
);
1380 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1383 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1388 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1390 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1394 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1400 #endif // !TARGET_OS_EMBEDDED
1404 #pragma mark DNS Configuration Events
1408 dnsinfo_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1410 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1411 CFSTR("%s dnsinfo notification"),
1419 add_dnsinfo_notification()
1423 mach_port_t notify_port
;
1425 CFRunLoopSourceRef rls
;
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"));
1435 mp
= _SC_CFMachPortCreateWithPort("Logger/dns_configuration", notify_port
, dnsinfo_notification
, NULL
);
1437 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1438 (void)notify_cancel(notify_token
);
1442 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1444 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1446 (void)notify_cancel(notify_token
);
1449 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1458 #pragma mark Network Information Events
1462 nwi_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1464 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1465 CFSTR("%s network_information notification"),
1473 add_nwi_notification()
1477 mach_port_t notify_port
;
1479 CFRunLoopSourceRef rls
;
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"));
1489 mp
= _SC_CFMachPortCreateWithPort("Logger/nwi", notify_port
, nwi_notification
, NULL
);
1491 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1492 (void)notify_cancel(notify_token
);
1496 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1498 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1500 (void)notify_cancel(notify_token
);
1503 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1512 #pragma mark Network Configuration Change Events
1515 #define NETWORKCHANGED_NOTIFY_KEY "com.apple.system.config.network_change"
1518 network_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1520 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1521 CFSTR("%s network_change notification"),
1529 add_network_notification()
1532 mach_port_t notify_port
;
1534 CFRunLoopSourceRef rls
;
1537 status
= notify_register_mach_port(NETWORKCHANGED_NOTIFY_KEY
,
1541 if (status
!= NOTIFY_STATUS_OK
) {
1542 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1546 mp
= _SC_CFMachPortCreateWithPort("Logger/network_change", notify_port
, network_notification
, NULL
);
1548 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1549 (void)notify_cancel(notify_token
);
1553 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1555 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1557 (void)notify_cancel(notify_token
);
1560 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1569 #pragma mark SMB Configuration Events
1572 #define SMBCONFIGURATION_NOTIFY_KEY "com.apple.system.SystemConfiguration.smb_configuration"
1575 #if !TARGET_OS_EMBEDDED
1577 smbconf_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1579 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1580 CFSTR("%s smb.conf notification"),
1588 add_smbconf_notification()
1591 mach_port_t notify_port
;
1593 CFRunLoopSourceRef rls
;
1596 status
= notify_register_mach_port(SMBCONFIGURATION_NOTIFY_KEY
,
1600 if (status
!= NOTIFY_STATUS_OK
) {
1601 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1605 mp
= _SC_CFMachPortCreateWithPort("Logger/smb_configuration", notify_port
, smbconf_notification
, NULL
);
1607 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1608 (void)notify_cancel(notify_token
);
1612 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1614 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1616 (void)notify_cancel(notify_token
);
1619 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1625 #endif // !TARGET_OS_EMBEDDED
1629 #pragma mark pututxline Events
1632 #if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
1634 ut_time(struct utmpx
*utmpx
)
1636 static char str
[16];
1639 (void)localtime_r(&utmpx
->ut_tv
.tv_sec
, &tm
);
1640 snprintf(str
, sizeof(str
), "%2d:%02d:%02d.%03d",
1644 utmpx
->ut_tv
.tv_usec
/ 1000);
1651 ut_id(struct utmpx
*utmpx
)
1654 static char str
[16];
1656 cp
= utmpx
->ut_id
+ sizeof(utmpx
->ut_id
);
1657 while(--cp
>= utmpx
->ut_id
&& isprint(*cp
)) {}
1658 if(cp
< utmpx
->ut_id
) {
1659 snprintf(str
, sizeof(str
), "%-4.4s", utmpx
->ut_id
);
1661 snprintf(str
, sizeof(str
),
1662 "0x%2.2x%2.2x%2.2x%2.2x",
1674 ut_pid(struct utmpx
*utmpx
)
1676 static char pid
[16];
1678 snprintf(pid
, sizeof(pid
), "%d", utmpx
->ut_pid
);
1685 pututxline_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1687 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1688 struct utmpx
*utmpx
;
1691 CFStringAppendFormat(str
,
1693 CFSTR("%s pututxline notification"),
1696 utx
= _openutx(NULL
);
1697 while ((utmpx
= _getutxent(utx
)) != NULL
) {
1698 const char * entry_id
= NULL
;
1699 const char * entry_line
= NULL
;
1700 const char * entry_pid
= NULL
;
1701 const char * entry_tv
= NULL
;
1702 const char * entry_type
;
1703 const char * entry_user
= NULL
;
1707 switch (utmpx
->ut_type
) {
1708 case BOOT_TIME
: // Time of a system boot.
1709 entry_type
= "Boot";
1710 entry_tv
= ut_time(utmpx
);
1712 case DEAD_PROCESS
: // A session leader exited.
1713 entry_type
= "Dead process";
1714 entry_id
= ut_id (utmpx
);
1715 entry_pid
= ut_pid (utmpx
);
1716 entry_tv
= ut_time(utmpx
);
1718 case EMPTY
: // No valid user accounting information.
1720 case INIT_PROCESS
: // A process spawned by init(8).
1721 entry_type
= "Init process";
1722 entry_id
= ut_id (utmpx
);
1723 entry_pid
= ut_pid (utmpx
);
1724 entry_tv
= ut_time(utmpx
);
1726 case LOGIN_PROCESS
: // The session leader of a logged-in user.
1727 entry_type
= "Login";
1728 entry_id
= ut_id (utmpx
);
1729 entry_user
= utmpx
->ut_user
;
1730 entry_pid
= ut_pid (utmpx
);
1731 entry_tv
= ut_time(utmpx
);
1733 case NEW_TIME
: // Time after system clock change.
1734 entry_type
= "New time";
1735 entry_tv
= ut_time(utmpx
);
1737 case OLD_TIME
: // Time before system clock change.
1738 entry_type
= "Old time";
1739 entry_tv
= ut_time(utmpx
);
1741 case RUN_LVL
: // Run level. Provided for compatibility, not used.
1742 entry_type
= "Run level";
1744 case USER_PROCESS
: // A user process.
1745 entry_type
= "User Process";
1746 entry_id
= ut_id (utmpx
);
1747 entry_user
= utmpx
->ut_user
;
1748 entry_line
= utmpx
->ut_line
;
1749 entry_pid
= ut_pid (utmpx
);
1750 entry_tv
= ut_time(utmpx
);
1752 case SHUTDOWN_TIME
: // Time of system shutdown
1753 entry_type
= "Shutdown time";
1754 entry_tv
= ut_time(utmpx
);
1757 entry_type
= "Unknown";
1761 snprintf(line
, sizeof(line
),
1762 // type time id=0x12345678 pid=12345 user=abcdefgh line
1763 "\n%-13s %2s%12s %3s%-10s %4s%-5s %5s%-8s %5s%s",
1765 entry_tv
!= NULL
? "@ " : "",
1766 entry_tv
!= NULL
? entry_tv
: "", // hh:mm:ss.ddd
1767 entry_id
!= NULL
? "id=" : "",
1768 entry_id
!= NULL
? entry_id
: "", // 0x12345678
1769 entry_pid
!= NULL
? "pid=" : "",
1770 entry_pid
!= NULL
? entry_pid
: "", // #####
1771 entry_user
!= NULL
? "user=" : "",
1772 entry_user
!= NULL
? entry_user
: "", // <=256 chars
1773 entry_line
!= NULL
? "line=" : "",
1774 entry_line
!= NULL
? entry_line
: "" // <= 32 chars
1777 n
= strlen(line
) - 1;
1778 while ((n
> 0) && (line
[n
] == ' ')) {
1783 CFStringAppendFormat(str
, NULL
, CFSTR("%s"), line
);
1787 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1794 add_pututxline_notification()
1797 mach_port_t notify_port
;
1799 CFRunLoopSourceRef rls
;
1802 status
= notify_register_mach_port(UTMPX_CHANGE_NOTIFICATION
, ¬ify_port
, 0, ¬ify_token
);
1803 if (status
!= NOTIFY_STATUS_OK
) {
1804 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1808 mp
= _SC_CFMachPortCreateWithPort("Logger/utmpx", notify_port
, pututxline_notification
, NULL
);
1810 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1811 (void)notify_cancel(notify_token
);
1815 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1817 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1819 (void)notify_cancel(notify_token
);
1822 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1828 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
1832 #pragma mark BackToMyMac Status Events
1835 #ifndef kDSStdNotifyBTMMStatusChanged
1836 #define kDSStdNotifyBTMMStatusChanged "State:/Network/BackToMyMac"
1840 #if !TARGET_OS_EMBEDDED
1842 BTMM_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1846 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1848 CFStringAppendFormat(str
,
1850 CFSTR("%s SCDynamicStore Back to My Mac notification"),
1853 n
= CFArrayGetCount(changedKeys
);
1854 for (i
= 0; i
< n
; i
++) {
1856 CFDictionaryRef dict
;
1858 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
1859 dict
= SCDynamicStoreCopyValue(store
, key
);
1863 val
= _SCCopyDescription(dict
, NULL
);
1864 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : %@"), key
, val
);
1868 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : removed"), key
);
1872 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1879 add_BTMM_notification()
1882 CFMutableArrayRef keys
;
1884 SCDynamicStoreRef store
;
1885 CFRunLoopSourceRef rls
;
1887 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-BackToMyMac"), BTMM_notification
, NULL
);
1888 if (store
== NULL
) {
1889 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
1893 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1895 key
= CFSTR(kDSStdNotifyBTMMStatusChanged
);
1896 CFArrayAppendValue(keys
, key
);
1898 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1901 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1906 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1908 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1912 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1918 #endif // !TARGET_OS_EMBEDDED
1924 static __inline__ Boolean
1925 bValFromDictionary(CFDictionaryRef dict
, CFStringRef key
)
1928 Boolean result
= FALSE
;
1930 if ((dict
!= NULL
) &&
1931 CFDictionaryGetValueIfPresent(dict
, key
, (const void **)&bVal
) &&
1932 isA_CFBoolean(bVal
)) {
1933 result
= CFBooleanGetValue(bVal
);
1941 load(CFBundleRef bundle
, Boolean bundleVerbose
)
1943 CFDictionaryRef config
;
1946 verbose
= bundleVerbose
;
1948 log_msg
= asl_new(ASL_TYPE_MSG
);
1949 asl_set(log_msg
, ASL_KEY_FACILITY
, MY_ASL_FACILITY
);
1953 config
= CFBundleGetInfoDictionary(bundle
);
1954 config
= isA_CFDictionary(config
);
1955 log_all
= bValFromDictionary(config
, CFSTR("LOG_ALL"));
1957 #ifdef kIOPMMessageSleepWakeUUIDChange
1958 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_IO_WAKEUUID_EVENTS"))) {
1959 add_wake_uuid_notification();
1961 #endif // kIOPMMessageSleepWakeUUIDChange
1963 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_IO_SYSTEMPOWER_EVENTS"))) {
1964 add_power_notification();
1967 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NETWORK_KERNEL_EVENTS"))) {
1968 add_KernelEvent_notification();
1971 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NETWORK_INFORMATION"))) {
1972 add_nwi_notification();
1975 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_DNS_CONFIGURATION"))) {
1976 add_dnsinfo_notification();
1979 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_NETWORK_CHANGE"))) {
1980 add_network_notification();
1983 #if !TARGET_OS_EMBEDDED
1984 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_SMB_CONFIGURATION"))) {
1985 add_smbconf_notification();
1987 #endif // !TARGET_OS_EMBEDDED
1989 #if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
1990 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_UTMPX_CHANGE"))) {
1991 add_pututxline_notification();
1993 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
1995 #if !TARGET_OS_EMBEDDED
1996 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_BTMM_CONFIGURATION"))) {
1997 add_BTMM_notification();
1999 #endif // !TARGET_OS_EMBEDDED
2001 #if !TARGET_OS_EMBEDDED
2002 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_CONSOLEUSER"))) {
2003 add_console_notification();
2005 #endif // !TARGET_OS_EMBEDDED
2007 #if !TARGET_OS_EMBEDDED
2008 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_DIRECTORYSERVICES_SEARCHPOLICY"))) {
2009 add_DirectoryServices_notification();
2011 #endif // !TARGET_OS_EMBEDDED
2013 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_NETWORKCHANGE"))) {
2014 add_NetworkChange_notification();
2017 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_PRIMARYSERVICE"))) {
2018 add_PrimaryService_notification();
2021 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_REACHABILITY"))) {
2022 CFArrayRef hosts
= NULL
;
2024 if ((config
== NULL
) ||
2025 !CFDictionaryGetValueIfPresent(config
, CFSTR("LOG_SC_REACHABILITY_HOSTS"), (const void **)&hosts
) ||
2026 !isA_CFArray(hosts
) ||
2027 (CFArrayGetCount(hosts
) == 0)) {
2035 add_reachability_notification(hosts
);
2044 main(int argc
, char **argv
)
2047 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
2050 load(CFBundleGetMainBundle(), (argc
> 1) ? TRUE
: FALSE
);