2 * Copyright (c) 2005-2010 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>
58 #include <IOKit/pwr_mgt/IOPMLibPrivate.h>
62 #if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
64 #include <utmpx_thread.h>
65 #endif // !(__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
68 /* generic MessageTracer keys */
69 #define MSGTRACER_KEY_DOMAIN "com.apple.message.domain"
70 #define MSGTRACER_KEY_SIG "com.apple.message.signature"
71 #define MSGTRACER_KEY_UUID "com.apple.message.uuid"
72 #define MSGTRACER_KEY_VALUE1 "com.apple.message.value"
75 #define MY_ASL_FACILITY "com.apple.SystemConfiguration.Logger"
76 #define MY_MSGTRACER_DOMAIN "com.apple.network.log"
79 static aslmsg log_msg
= NULL
;
80 static io_connect_t power
= MACH_PORT_NULL
;
81 static Boolean verbose
= FALSE
;
90 struct timeval tv_diff
;
91 struct timeval tv_now
;
92 static struct timeval tv_then
= { 0, 0 };
94 (void)gettimeofday(&tv_now
, NULL
);
96 (void)localtime_r(&tv_now
.tv_sec
, &tm_now
);
98 timersub(&tv_now
, &tv_then
, &tv_diff
);
99 (void)localtime_r(&tv_diff
.tv_sec
, &tm_diff
);
101 sprintf(str
, "%2d:%02d:%02d.%03d (+%ld.%03d)",
105 tv_now
.tv_usec
/ 1000,
107 tv_diff
.tv_usec
/ 1000);
109 sprintf(str
, ".%03d (+%ld.%03d)",
110 tv_now
.tv_usec
/ 1000,
112 tv_diff
.tv_usec
/ 1000);
121 #pragma mark [Network] Kernel Events
125 copyInterfaceFlags(const char *if_name
)
127 const char * iff_up
= "? ";
129 const char *ifm_active
= "? ";
131 CFStringRef str
= NULL
;
133 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
135 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("socket() failed"));
139 bzero((char *)&ifr
, sizeof(ifr
));
140 (void) strlcpy(ifr
.ifr_name
, if_name
, sizeof(ifr
.ifr_name
));
141 if (ioctl(sock
, SIOCGIFFLAGS
, (caddr_t
)&ifr
) == 0) {
142 struct ifmediareq ifm
;
144 iff_up
= (ifr
.ifr_flags
& IFF_UP
) ? "yes" : "no ";
146 bzero((char *)&ifm
, sizeof(ifm
));
147 (void) strncpy(ifm
.ifm_name
, if_name
, sizeof(ifm
.ifm_name
));
148 if ((ioctl(sock
, SIOCGIFMEDIA
, (caddr_t
)&ifm
) == 0) &&
149 (ifm
.ifm_count
> 0) &&
150 (ifm
.ifm_status
& IFM_AVALID
)) {
151 ifm_active
= (ifm
.ifm_status
& IFM_ACTIVE
) ? "yes" : "no ";
154 str
= CFStringCreateWithFormat(NULL
,
156 CFSTR("\n%-5s: IFF_UP = %s IFM_ACTIVE = %s"),
169 prefixLength(struct sockaddr_in6
*sin6
)
171 register u_int8_t
*name
= &sin6
->sin6_addr
.s6_addr
[0];
176 for (byte
= 0; byte
< sizeof(struct in6_addr
); byte
++, plen
+= 8) {
177 if (name
[byte
] != 0xff) {
182 if (byte
== sizeof(struct in6_addr
)) {
186 for (bit
= 7; bit
!= 0; bit
--, plen
++) {
187 if (!(name
[byte
] & (1 << bit
))) {
192 for (; bit
!= 0; bit
--) {
193 if (name
[byte
] & (1 << bit
)) {
199 for (; byte
< sizeof(struct in6_addr
); byte
++) {
210 KernelEvent_notification(CFSocketRef s
, CFSocketCallBackType type
, CFDataRef address
, const void *data
, void *info
)
212 int so
= CFSocketGetNative(s
);
215 struct kern_event_msg
*ev_msg
= (struct kern_event_msg
*)&buf
[0];
218 status
= recv(so
, &buf
, sizeof(buf
), 0);
220 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("recv() failed: %s"), strerror(errno
));
221 CFSocketInvalidate(s
);
225 while (offset
< status
) {
226 if ((offset
+ ev_msg
->total_size
) > status
) {
227 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("missed SYSPROTO_EVENT event, buffer not big enough"));
231 switch (ev_msg
->vendor_code
) {
232 case KEV_VENDOR_APPLE
:
233 switch (ev_msg
->kev_class
) {
234 case KEV_NETWORK_CLASS
: {
235 void *event_data
= &ev_msg
->event_data
[0];
237 switch (ev_msg
->kev_subclass
) {
238 case KEV_DL_SUBCLASS
: {
239 struct net_event_data
*ev
;
240 char if_name
[IFNAMSIZ
];
242 ev
= (struct net_event_data
*)event_data
;
244 snprintf(if_name
, IFNAMSIZ
, "%s%d",
248 switch (ev_msg
->event_code
) {
249 case KEV_DL_IF_ATTACHED
: {
250 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
251 CFSTR("%s kernel event: %s: attached"),
256 case KEV_DL_IF_DETACHING
: {
257 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
258 CFSTR("%s kernel event: %s: detaching"),
263 case KEV_DL_IF_DETACHED
: {
264 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
265 CFSTR("%s kernel event: %s: detached"),
270 case KEV_DL_LINK_OFF
: {
273 str
= verbose
? copyInterfaceFlags(if_name
) : NULL
;
274 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
275 CFSTR("%s kernel event: %s: link down%@"),
278 str
!= NULL
? str
: CFSTR(""));
279 if (str
!= NULL
) CFRelease(str
);
282 case KEV_DL_LINK_ON
: {
285 str
= verbose
? copyInterfaceFlags(if_name
) : NULL
;
286 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
287 CFSTR("%s kernel event: %s: link up%@"),
290 str
!= NULL
? str
: CFSTR(""));
291 if (str
!= NULL
) CFRelease(str
);
299 case KEV_INET_SUBCLASS
: {
301 struct kev_in_data
*ev
;
302 char if_name
[IFNAMSIZ
];
305 ev
= (struct kev_in_data
*)event_data
;
307 snprintf(if_name
, IFNAMSIZ
, "%s%d",
308 ev
->link_data
.if_name
,
309 ev
->link_data
.if_unit
);
311 switch (ev_msg
->event_code
) {
312 case KEV_INET_NEW_ADDR
:
313 case KEV_INET_CHANGED_ADDR
:
314 case KEV_INET_ADDR_DELETED
: {
315 struct sockaddr_in sin
;
317 bzero(&sin
, sizeof(sin
));
318 sin
.sin_len
= sizeof(sin
);
319 sin
.sin_family
= AF_INET
;
320 sin
.sin_addr
= ev
->ia_addr
;
321 _SC_sockaddr_to_string((struct sockaddr
*)&sin
, addr
, sizeof(addr
));
323 bzero(&sin
, sizeof(sin
));
324 sin
.sin_len
= sizeof(sin
);
325 sin
.sin_family
= AF_INET
;
326 sin
.sin_addr
.s_addr
= ntohl(ev
->ia_subnetmask
);
327 _SC_sockaddr_to_string((struct sockaddr
*)&sin
, mask
, sizeof(mask
));
334 switch (ev_msg
->event_code
) {
335 case KEV_INET_NEW_ADDR
: {
336 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
337 CFSTR("%s kernel event: %s: IPv4 address added (%s/%s)"),
344 case KEV_INET_CHANGED_ADDR
: {
345 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
346 CFSTR("%s kernel event: %s: IPv4 address changed (%s/%s)"),
353 case KEV_INET_ADDR_DELETED
: {
354 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
355 CFSTR("%s kernel event: %s: IPv4 address removed (%s/%s)"),
367 case KEV_INET6_SUBCLASS
: {
369 struct kev_in6_data
*ev
;
370 char if_name
[IFNAMSIZ
];
373 ev
= (struct kev_in6_data
*)event_data
;
375 snprintf(if_name
, IFNAMSIZ
, "%s%d",
376 ev
->link_data
.if_name
,
377 ev
->link_data
.if_unit
);
379 switch (ev_msg
->event_code
) {
380 case KEV_INET6_NEW_USER_ADDR
:
381 case KEV_INET6_NEW_LL_ADDR
:
382 case KEV_INET6_CHANGED_ADDR
:
383 case KEV_INET6_ADDR_DELETED
: {
384 _SC_sockaddr_to_string((struct sockaddr
*)&ev
->ia_addr
, addr
, sizeof(addr
));
385 plen
= prefixLength(&ev
->ia_prefixmask
);
392 switch (ev_msg
->event_code
) {
393 case KEV_INET6_NEW_USER_ADDR
:
394 case KEV_INET6_NEW_LL_ADDR
: {
395 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
396 CFSTR("%s kernel event: %s: IPv6 address added (%s/%d)"),
403 case KEV_INET6_CHANGED_ADDR
: {
404 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
405 CFSTR("%s kernel event: %s: IPv6 address changed (%s/%d)"),
412 case KEV_INET6_ADDR_DELETED
: {
413 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
414 CFSTR("%s kernel event: %s: IPv6 address removed"),
434 /* unrecognized vendor code */
437 offset
+= ev_msg
->total_size
;
438 ev_msg
= (struct kern_event_msg
*)&buf
[offset
];
446 add_KernelEvent_notification()
449 CFSocketContext es_context
= { 0, NULL
, NULL
, NULL
, NULL
};
450 struct kev_request kev_req
;
451 CFRunLoopSourceRef rls
;
455 /* Open an event socket */
456 so
= socket(PF_SYSTEM
, SOCK_RAW
, SYSPROTO_EVENT
);
458 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("socket() failed"));
462 /* establish filter to return all events */
463 kev_req
.vendor_code
= KEV_VENDOR_APPLE
;
464 kev_req
.kev_class
= KEV_NETWORK_CLASS
;
465 kev_req
.kev_subclass
= KEV_ANY_SUBCLASS
;
466 if (ioctl(so
, SIOCSKEVFILT
, &kev_req
) == -1) {
467 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("ioctl(, SIOCSKEVFILT, ) failed"));
472 if (ioctl(so
, FIONBIO
, &yes
) == -1) {
473 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("ioctl(, FIONBIO, ) failed"));
478 /* Create a CFSocketRef for the PF_SYSTEM kernel event socket */
479 es
= CFSocketCreateWithNative(NULL
,
481 kCFSocketReadCallBack
,
482 KernelEvent_notification
,
485 /* Create and add a run loop source for the event socket */
486 rls
= CFSocketCreateRunLoopSource(NULL
, es
, -1);
489 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
497 #pragma mark Power Management Events
501 power_notification(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
503 switch (messageType
) {
504 case kIOMessageCanDevicePowerOff
:
505 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
506 CFSTR("%s IORegisterForSystemPower: can device power off?"),
509 case kIOMessageDeviceWillPowerOff
:
510 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
511 CFSTR("%s IORegisterForSystemPower: device will power off"),
514 case kIOMessageDeviceWillNotPowerOff
:
515 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
516 CFSTR("%s IORegisterForSystemPower: device will not power off"),
519 case kIOMessageDeviceHasPoweredOn
:
520 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
521 CFSTR("%s IORegisterForSystemPower: device has powered on"),
524 case kIOMessageCanSystemPowerOff
:
525 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
526 CFSTR("%s IORegisterForSystemPower: can system power off?"),
529 case kIOMessageSystemWillPowerOff
:
530 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
531 CFSTR("%s IORegisterForSystemPower: system will power off"),
534 case kIOMessageSystemWillNotPowerOff
:
535 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
536 CFSTR("%s IORegisterForSystemPower: system will not power off"),
539 case kIOMessageCanSystemSleep
:
540 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
541 CFSTR("%s IORegisterForSystemPower: can system sleep?"),
544 * Idle sleep is about to kick in, but applications have
545 * a chance to allow sleep (by calling IOAllowPowerChange)
546 * or to prevent sleep (by calling IOCancelPowerChange).
548 IOAllowPowerChange(power
, (long)messageArgument
);
550 case kIOMessageSystemWillSleep
:
551 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
552 CFSTR("%s IORegisterForSystemPower: system will sleep"),
554 IOAllowPowerChange(power
, (long)messageArgument
);
556 case kIOMessageSystemWillNotSleep
:
557 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
558 CFSTR("%s IORegisterForSystemPower: system will not sleep"),
561 case kIOMessageSystemHasPoweredOn
:
562 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
563 CFSTR("%s IORegisterForSystemPower: system has powered on"),
566 case kIOMessageSystemWillRestart
:
567 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
568 CFSTR("%s IORegisterForSystemPower: system will restart"),
571 case kIOMessageSystemWillPowerOn
:
572 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
573 CFSTR("%s IORegisterForSystemPower: system will power on"),
577 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
578 CFSTR("%s IORegisterForSystemPower: message=%08lx"),
580 (long unsigned int)messageType
);
589 add_power_notification()
591 io_object_t iterator
;
592 IONotificationPortRef notify
;
594 power
= IORegisterForSystemPower(0, ¬ify
, power_notification
, &iterator
);
595 if (power
== MACH_PORT_NULL
) {
596 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("IORegisterForSystemPower() failed"));
600 CFRunLoopAddSource(CFRunLoopGetCurrent(),
601 IONotificationPortGetRunLoopSource(notify
),
602 kCFRunLoopCommonModes
);
608 #ifdef kIOPMMessageSleepWakeUUIDChange
610 wake_uuid_notification(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
612 CFStringRef wake_uuid
= NULL
;
614 if (messageType
== kIOPMMessageSleepWakeUUIDChange
) {
615 if (messageArgument
== kIOPMMessageSleepWakeUUIDSet
) {
616 wake_uuid
= IORegistryEntryCreateCFProperty(service
, CFSTR(kIOPMSleepWakeUUIDKey
), NULL
, 0);
619 if (wake_uuid
!= NULL
) {
622 _SC_cfstring_to_cstring(wake_uuid
, uuid
, sizeof(uuid
), kCFStringEncodingUTF8
);
623 asl_set(log_msg
, MSGTRACER_KEY_DOMAIN
, MY_MSGTRACER_DOMAIN
);
624 asl_set(log_msg
, MSGTRACER_KEY_UUID
, uuid
);
626 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
627 CFSTR("%s wake UUID notification: UUID set (%@)"),
631 CFRelease(wake_uuid
);
633 asl_unset(log_msg
, MSGTRACER_KEY_DOMAIN
);
634 asl_unset(log_msg
, MSGTRACER_KEY_UUID
);
636 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
637 CFSTR("%s wake UUID notification: UUID not set"),
647 add_wake_uuid_notification()
650 io_object_t notification
= IO_OBJECT_NULL
;
651 IONotificationPortRef notifyPort
;
652 io_service_t service
;
654 notifyPort
= IONotificationPortCreate(kIOMasterPortDefault
);
655 service
= IORegistryEntryFromPath(kIOMasterPortDefault
,
656 kIOPowerPlane
":/IOPowerConnection/IOPMrootDomain");
657 kr
= IOServiceAddInterestNotification(notifyPort
,
660 wake_uuid_notification
,
663 if (kr
!= KERN_SUCCESS
) {
664 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
,
665 CFSTR("IOServiceAddInterestNotification() failed, kr=0x%x"),
670 CFRunLoopAddSource(CFRunLoopGetCurrent(),
671 IONotificationPortGetRunLoopSource(notifyPort
),
672 kCFRunLoopDefaultMode
);
674 wake_uuid_notification(NULL
,
676 kIOPMMessageSleepWakeUUIDChange
,
677 kIOPMMessageSleepWakeUUIDSet
);
681 #endif // kIOPMMessageSleepWakeUUIDChange
685 #pragma mark SCDynamicStore "network" Events
689 NetworkChange_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
693 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
695 CFStringAppendFormat(str
,
697 CFSTR("%s SCDynamicStore \"network\" notification"),
700 n
= CFArrayGetCount(changedKeys
);
701 for (i
= 0; i
< n
; i
++) {
704 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
705 if (CFStringHasSuffix(key
, kSCEntNetLink
)) {
706 CFDictionaryRef dict
;
707 const char *val
= "?";
709 dict
= SCDynamicStoreCopyValue(store
, key
);
713 link
= CFDictionaryGetValue(dict
, kSCPropNetLinkActive
);
715 val
= CFBooleanGetValue(link
) ? "up" : "down";
720 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ (%s)"), key
, val
);
721 } else if (CFStringHasSuffix(key
, kSCEntNetIPv4
) ||
722 CFStringHasSuffix(key
, kSCEntNetIPv6
) ||
723 CFStringHasSuffix(key
, kSCEntNetDNS
)) {
724 CFDictionaryRef dict
;
726 dict
= SCDynamicStoreCopyValue(store
, key
);
730 val
= _SCCopyDescription(dict
, NULL
);
731 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : %@"), key
, val
);
735 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : removed"), key
);
737 } else if (CFStringHasSuffix(key
, CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix
))) {
740 num
= SCDynamicStoreCopyValue(store
, key
);
742 IOPMSystemPowerStateCapabilities capabilities
;
744 if (isA_CFNumber(num
) &&
745 CFNumberGetValue(num
, kCFNumberSInt32Type
, &capabilities
)) {
746 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ (0x%x)"), key
, capabilities
);
752 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
756 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
763 add_NetworkChange_notification()
767 CFMutableArrayRef keys
;
770 CFMutableArrayRef patterns
;
771 SCDynamicStoreRef store
;
772 CFRunLoopSourceRef rls
;
774 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-NetworkChange"), NetworkChange_notification
, NULL
);
776 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
780 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
781 patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
785 key
= SCDynamicStoreKeyCreateNetworkInterface(NULL
, kSCDynamicStoreDomainState
);
786 CFArrayAppendValue(keys
, key
);
791 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
792 CFArrayAppendValue(keys
, key
);
795 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv4
);
796 CFArrayAppendValue(patterns
, pattern
);
799 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv4
);
800 CFArrayAppendValue(patterns
, pattern
);
805 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv6
);
806 CFArrayAppendValue(keys
, key
);
809 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv6
);
810 CFArrayAppendValue(patterns
, pattern
);
813 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv6
);
814 CFArrayAppendValue(patterns
, pattern
);
819 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetPPP
);
820 CFArrayAppendValue(patterns
, pattern
);
823 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetPPP
);
824 CFArrayAppendValue(patterns
, pattern
);
827 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetVPN
);
828 CFArrayAppendValue(patterns
, pattern
);
831 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetVPN
);
832 CFArrayAppendValue(patterns
, pattern
);
837 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetLink
);
838 CFArrayAppendValue(patterns
, pattern
);
841 // AirPort (e.g. BSSID)
843 pattern
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetAirPort
);
844 CFArrayAppendValue(patterns
, pattern
);
849 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
850 CFArrayAppendValue(keys
, key
);
853 dns_key
= CFStringCreateWithCString(NULL
,
854 dns_configuration_notify_key(),
855 kCFStringEncodingASCII
);
856 key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("Notify:%@"), dns_key
);
858 CFArrayAppendValue(keys
, key
);
863 key
= SCDynamicStoreKeyCreateProxies(NULL
);
864 CFArrayAppendValue(keys
, key
);
867 // ComputerName, LocalHostName
869 key
= SCDynamicStoreKeyCreateComputerName(NULL
);
870 CFArrayAppendValue(keys
, key
);
873 key
= SCDynamicStoreKeyCreateHostNames(NULL
);
874 CFArrayAppendValue(keys
, key
);
877 key
= SCDynamicStoreKeyCreate(NULL
, CFSTR("%@%@"),
878 kSCDynamicStoreDomainState
,
879 CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix
));
880 CFArrayAppendValue(keys
, key
);
883 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
);
887 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
892 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
894 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
898 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
907 PrimaryService_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
909 CFDictionaryRef entity
;
911 static CFStringRef oldPrimary
= NULL
;
912 CFStringRef newPrimary
= NULL
;
914 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
915 entity
= SCDynamicStoreCopyValue(store
, key
);
917 if (isA_CFDictionary(entity
) &&
918 CFDictionaryGetValueIfPresent(entity
,
919 kSCDynamicStorePropNetPrimaryService
,
920 (const void **)&newPrimary
) &&
921 isA_CFString(newPrimary
)) {
922 CFRetain(newPrimary
);
927 if (!_SC_CFEqual(oldPrimary
, newPrimary
)) {
928 if (newPrimary
!= NULL
) {
929 CFStringRef newInterface
;
931 newInterface
= CFDictionaryGetValue(entity
, kSCDynamicStorePropNetPrimaryInterface
);
932 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
933 CFSTR("%s Primary service: %@ (%@)"),
936 newInterface
!= NULL
? newInterface
: CFSTR("?"));
938 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
939 CFSTR("%s Primary service: removed"),
944 if (oldPrimary
!= NULL
) CFRelease(oldPrimary
);
945 oldPrimary
= newPrimary
;
947 if (entity
!= NULL
) CFRelease(entity
);
953 add_PrimaryService_notification()
956 CFMutableArrayRef keys
;
958 SCDynamicStoreRef store
;
959 CFRunLoopSourceRef rls
;
961 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-PrimaryService"), PrimaryService_notification
, NULL
);
963 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
967 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
968 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
969 CFArrayAppendValue(keys
, key
);
972 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
975 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
980 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
982 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
986 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
995 #pragma mark Reachability Events
999 reachability_notification(SCNetworkReachabilityRef ref
, SCNetworkReachabilityFlags flags
, void *info
)
1001 CFStringRef hostname
= (CFStringRef
)info
;
1003 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1004 CFSTR("%s reachability changed: %@: flags=0x%08x"),
1013 add_reachability_notification(CFArrayRef hosts
)
1015 SCNetworkReachabilityContext context
= { 0, NULL
, CFRetain
, CFRelease
, CFCopyDescription
};
1018 SCNetworkReachabilityRef target
;
1023 } watchAddresses
[] = { { 0, CFSTR("0.0.0.0") },
1024 { IN_LINKLOCALNETNUM
, CFSTR("169.254.0.0") },
1025 { (u_int32_t
)0xe00000fb, CFSTR("224.0.0.251") },
1028 for (i
= 0; i
< sizeof(watchAddresses
)/sizeof(watchAddresses
[0]); i
++) {
1029 struct sockaddr_in sin
;
1031 bzero(&sin
, sizeof(sin
));
1032 sin
.sin_len
= sizeof(sin
);
1033 sin
.sin_family
= AF_INET
;
1034 sin
.sin_addr
.s_addr
= htonl(watchAddresses
[i
].addr
);
1036 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin
);
1037 if (target
== NULL
) {
1038 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityCreateWithAddress() failed"));
1042 context
.info
= (void *)watchAddresses
[i
].name
;
1043 if (!SCNetworkReachabilitySetCallback(target
, reachability_notification
, &context
)) {
1044 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilitySetCallback() failed"));
1049 if (!SCNetworkReachabilityScheduleWithRunLoop(target
, CFRunLoopGetCurrent(), kCFRunLoopCommonModes
)) {
1050 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityScheduleWithRunLoop() failed"));
1058 n
= (hosts
!= NULL
) ? CFArrayGetCount(hosts
) : 0;
1059 for (i
= 0; i
< n
; i
++) {
1063 host
= CFArrayGetValueAtIndex(hosts
, i
);
1064 if (!isA_CFString(host
) || (CFStringGetLength(host
) == 0)) {
1068 nodename
= _SC_cfstring_to_cstring(host
, NULL
, 0, kCFStringEncodingUTF8
);
1069 target
= SCNetworkReachabilityCreateWithName(NULL
, nodename
);
1070 CFAllocatorDeallocate(NULL
, nodename
);
1071 if (target
== NULL
) {
1072 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityCreateWithName() failed"));
1076 context
.info
= (void *)host
;
1077 if (!SCNetworkReachabilitySetCallback(target
, reachability_notification
, &context
)) {
1078 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilitySetCallback() failed"));
1083 if (!SCNetworkReachabilityScheduleWithRunLoop(target
, CFRunLoopGetCurrent(), kCFRunLoopCommonModes
)) {
1084 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCNetworkReachabilityScheduleWithRunLoop() failed"));
1097 #pragma mark Console User/Information Events
1100 #if !TARGET_OS_EMBEDDED
1102 console_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1106 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1110 CFStringAppendFormat(str
,
1112 CFSTR("%s SCDynamicStore console notification"),
1115 user
= SCDynamicStoreCopyConsoleUser(store
, &uid
, &gid
);
1117 CFStringAppendFormat(str
, NULL
, CFSTR("\nconsole user = %@"), user
);
1120 CFStringAppendFormat(str
, NULL
, CFSTR("\nno console user"));
1123 info
= SCDynamicStoreCopyConsoleInformation(store
);
1128 n
= CFArrayGetCount(info
);
1129 for (i
= 0; i
< n
; i
++) {
1130 CFDictionaryRef session
;
1131 CFNumberRef sessionID
;
1132 CFStringRef sessionUserName
;
1133 CFBooleanRef sessionOnConsole
;
1135 session
= CFArrayGetValueAtIndex(info
, i
);
1136 sessionID
= CFDictionaryGetValue(session
, kSCConsoleSessionID
);
1137 sessionUserName
= CFDictionaryGetValue(session
, kSCConsoleSessionUserName
);
1138 sessionOnConsole
= CFDictionaryGetValue(session
, kSCConsoleSessionOnConsole
);
1140 CFStringAppendFormat(str
, NULL
, CFSTR("\n%d : id=%@, user=%@, console=%s"),
1143 sessionUserName
!= NULL
? sessionUserName
: CFSTR("?"),
1144 sessionOnConsole
!= NULL
? CFBooleanGetValue(sessionOnConsole
) ? "yes" : "no" : "?");
1150 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1157 add_console_notification()
1160 CFMutableArrayRef keys
;
1162 SCDynamicStoreRef store
;
1163 CFRunLoopSourceRef rls
;
1165 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-console"), console_notification
, NULL
);
1166 if (store
== NULL
) {
1167 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
1171 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1173 key
= SCDynamicStoreKeyCreateConsoleUser(NULL
);
1174 CFArrayAppendValue(keys
, key
);
1177 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1180 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1185 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1187 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1191 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1197 #endif // !TARGET_OS_EMBEDDED
1201 #pragma mark Directory Services Events
1204 //#include <DirectoryServices/DirServicesPriv.h>
1205 #ifndef kDSStdNotifySearchPolicyChanged
1206 #define kDSStdNotifySearchPolicyChanged "com.apple.DirectoryService.NotifyTypeStandard:SearchPolicyChanged"
1210 #if !TARGET_OS_EMBEDDED
1212 directoryServices_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1216 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1218 CFStringAppendFormat(str
,
1220 CFSTR("%s SCDynamicStore DirectoryServices notification"),
1223 n
= CFArrayGetCount(changedKeys
);
1224 for (i
= 0; i
< n
; i
++) {
1227 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
1228 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@"), key
);
1231 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1238 add_DirectoryServices_notification()
1241 CFMutableArrayRef keys
;
1243 SCDynamicStoreRef store
;
1244 CFRunLoopSourceRef rls
;
1246 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-directoryServices"), directoryServices_notification
, NULL
);
1247 if (store
== NULL
) {
1248 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
1252 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1254 key
= CFSTR(kDSStdNotifySearchPolicyChanged
);
1255 CFArrayAppendValue(keys
, key
);
1258 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1261 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1266 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1268 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1272 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1278 #endif // !TARGET_OS_EMBEDDED
1282 #pragma mark DNS Configuration Events
1286 dnsinfo_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1288 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1289 CFSTR("%s dnsinfo notification"),
1297 add_dnsinfo_notification()
1301 mach_port_t notify_port
;
1303 CFRunLoopSourceRef rls
;
1306 key
= dns_configuration_notify_key();
1307 status
= notify_register_mach_port(key
, ¬ify_port
, 0, ¬ify_token
);
1308 if (status
!= NOTIFY_STATUS_OK
) {
1309 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1313 mp
= _SC_CFMachPortCreateWithPort("Logger/dns_configuration", notify_port
, dnsinfo_notification
, NULL
);
1315 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1316 (void)notify_cancel(notify_token
);
1320 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1322 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1324 (void)notify_cancel(notify_token
);
1327 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1336 #pragma mark Network Configuration Change Events
1339 #define NETWORKCHANGED_NOTIFY_KEY "com.apple.system.config.network_change"
1342 network_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1344 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1345 CFSTR("%s network_change notification"),
1353 add_network_notification()
1356 mach_port_t notify_port
;
1358 CFRunLoopSourceRef rls
;
1361 status
= notify_register_mach_port(NETWORKCHANGED_NOTIFY_KEY
,
1365 if (status
!= NOTIFY_STATUS_OK
) {
1366 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1370 mp
= _SC_CFMachPortCreateWithPort("Logger/network_change", notify_port
, network_notification
, NULL
);
1372 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1373 (void)notify_cancel(notify_token
);
1377 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1379 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1381 (void)notify_cancel(notify_token
);
1384 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1393 #pragma mark SMB Configuration Events
1396 #define SMBCONFIGURATION_NOTIFY_KEY "com.apple.system.SystemConfiguration.smb_configuration"
1399 #if !TARGET_OS_EMBEDDED
1401 smbconf_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1403 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
,
1404 CFSTR("%s smb.conf notification"),
1412 add_smbconf_notification()
1415 mach_port_t notify_port
;
1417 CFRunLoopSourceRef rls
;
1420 status
= notify_register_mach_port(SMBCONFIGURATION_NOTIFY_KEY
,
1424 if (status
!= NOTIFY_STATUS_OK
) {
1425 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1429 mp
= _SC_CFMachPortCreateWithPort("Logger/smb_configuration", notify_port
, smbconf_notification
, NULL
);
1431 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1432 (void)notify_cancel(notify_token
);
1436 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1438 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1440 (void)notify_cancel(notify_token
);
1443 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1449 #endif // !TARGET_OS_EMBEDDED
1453 #pragma mark pututxline Events
1456 #if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
1458 ut_time(struct utmpx
*utmpx
)
1460 static char str
[16];
1463 (void)localtime_r(&utmpx
->ut_tv
.tv_sec
, &tm
);
1464 snprintf(str
, sizeof(str
), "%2d:%02d:%02d.%03d",
1468 utmpx
->ut_tv
.tv_usec
/ 1000);
1475 ut_id(struct utmpx
*utmpx
)
1478 static char str
[16];
1480 cp
= utmpx
->ut_id
+ sizeof(utmpx
->ut_id
);
1481 while(--cp
>= utmpx
->ut_id
&& isprint(*cp
)) {}
1482 if(cp
< utmpx
->ut_id
) {
1483 snprintf(str
, sizeof(str
), "%-4.4s", utmpx
->ut_id
);
1485 snprintf(str
, sizeof(str
),
1486 "0x%2.2x%2.2x%2.2x%2.2x",
1498 ut_pid(struct utmpx
*utmpx
)
1500 static char pid
[16];
1502 snprintf(pid
, sizeof(pid
), "%d", utmpx
->ut_pid
);
1509 pututxline_notification(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
)
1511 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1512 struct utmpx
*utmpx
;
1515 CFStringAppendFormat(str
,
1517 CFSTR("%s pututxline notification"),
1520 utx
= _openutx(NULL
);
1521 while ((utmpx
= _getutxent(utx
)) != NULL
) {
1522 const char * entry_id
= NULL
;
1523 const char * entry_line
= NULL
;
1524 const char * entry_pid
= NULL
;
1525 const char * entry_tv
= NULL
;
1526 const char * entry_type
;
1527 const char * entry_user
= NULL
;
1531 switch (utmpx
->ut_type
) {
1532 case BOOT_TIME
: // Time of a system boot.
1533 entry_type
= "Boot";
1534 entry_tv
= ut_time(utmpx
);
1536 case DEAD_PROCESS
: // A session leader exited.
1537 entry_type
= "Dead process";
1538 entry_id
= ut_id (utmpx
);
1539 entry_pid
= ut_pid (utmpx
);
1540 entry_tv
= ut_time(utmpx
);
1542 case EMPTY
: // No valid user accounting information.
1544 case INIT_PROCESS
: // A process spawned by init(8).
1545 entry_type
= "Init process";
1546 entry_id
= ut_id (utmpx
);
1547 entry_pid
= ut_pid (utmpx
);
1548 entry_tv
= ut_time(utmpx
);
1550 case LOGIN_PROCESS
: // The session leader of a logged-in user.
1551 entry_type
= "Login";
1552 entry_id
= ut_id (utmpx
);
1553 entry_user
= utmpx
->ut_user
;
1554 entry_pid
= ut_pid (utmpx
);
1555 entry_tv
= ut_time(utmpx
);
1557 case NEW_TIME
: // Time after system clock change.
1558 entry_type
= "New time";
1559 entry_tv
= ut_time(utmpx
);
1561 case OLD_TIME
: // Time before system clock change.
1562 entry_type
= "Old time";
1563 entry_tv
= ut_time(utmpx
);
1565 case RUN_LVL
: // Run level. Provided for compatibility, not used.
1566 entry_type
= "Run level";
1568 case USER_PROCESS
: // A user process.
1569 entry_type
= "User Process";
1570 entry_id
= ut_id (utmpx
);
1571 entry_user
= utmpx
->ut_user
;
1572 entry_line
= utmpx
->ut_line
;
1573 entry_pid
= ut_pid (utmpx
);
1574 entry_tv
= ut_time(utmpx
);
1576 case SHUTDOWN_TIME
: // Time of system shutdown
1577 entry_type
= "Shutdown time";
1578 entry_tv
= ut_time(utmpx
);
1581 entry_type
= "Unknown";
1585 snprintf(line
, sizeof(line
),
1586 // type time id=0x12345678 pid=12345 user=abcdefgh line
1587 "\n%-13s %2s%12s %3s%-10s %4s%-5s %5s%-8s %5s%s",
1589 entry_tv
!= NULL
? "@ " : "",
1590 entry_tv
!= NULL
? entry_tv
: "", // hh:mm:ss.ddd
1591 entry_id
!= NULL
? "id=" : "",
1592 entry_id
!= NULL
? entry_id
: "", // 0x12345678
1593 entry_pid
!= NULL
? "pid=" : "",
1594 entry_pid
!= NULL
? entry_pid
: "", // #####
1595 entry_user
!= NULL
? "user=" : "",
1596 entry_user
!= NULL
? entry_user
: "", // <=256 chars
1597 entry_line
!= NULL
? "line=" : "",
1598 entry_line
!= NULL
? entry_line
: "" // <= 32 chars
1601 n
= strlen(line
) - 1;
1602 while ((n
> 0) && (line
[n
] == ' ')) {
1607 CFStringAppendFormat(str
, NULL
, CFSTR("%s"), line
);
1611 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1618 add_pututxline_notification()
1621 mach_port_t notify_port
;
1623 CFRunLoopSourceRef rls
;
1626 status
= notify_register_mach_port(UTMPX_CHANGE_NOTIFICATION
, ¬ify_port
, 0, ¬ify_token
);
1627 if (status
!= NOTIFY_STATUS_OK
) {
1628 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("notify_register_mach_port() failed"));
1632 mp
= _SC_CFMachPortCreateWithPort("Logger/utmpx", notify_port
, pututxline_notification
, NULL
);
1634 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("CFMachPortCreateWithPort() failed"));
1635 (void)notify_cancel(notify_token
);
1639 rls
= CFMachPortCreateRunLoopSource(NULL
, mp
, -1);
1641 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1643 (void)notify_cancel(notify_token
);
1646 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1652 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
1656 #pragma mark BackToMyMac Status Events
1659 #ifndef kDSStdNotifyBTMMStatusChanged
1660 #define kDSStdNotifyBTMMStatusChanged "State:/Network/BackToMyMac"
1664 #if !TARGET_OS_EMBEDDED
1666 BTMM_notification(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
1670 CFMutableStringRef str
= CFStringCreateMutable(NULL
, 0);
1672 CFStringAppendFormat(str
,
1674 CFSTR("%s SCDynamicStore Back to My Mac notification"),
1677 n
= CFArrayGetCount(changedKeys
);
1678 for (i
= 0; i
< n
; i
++) {
1680 CFDictionaryRef dict
;
1682 key
= CFArrayGetValueAtIndex(changedKeys
, i
);
1683 dict
= SCDynamicStoreCopyValue(store
, key
);
1687 val
= _SCCopyDescription(dict
, NULL
);
1688 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : %@"), key
, val
);
1692 CFStringAppendFormat(str
, NULL
, CFSTR("\n%@ : removed"), key
);
1696 SCLOG(NULL
, log_msg
, ~ASL_LEVEL_INFO
, CFSTR("%@"), str
);
1703 add_BTMM_notification()
1706 CFMutableArrayRef keys
;
1708 SCDynamicStoreRef store
;
1709 CFRunLoopSourceRef rls
;
1711 store
= SCDynamicStoreCreate(NULL
, CFSTR("Logger.bundle-BackToMyMac"), BTMM_notification
, NULL
);
1712 if (store
== NULL
) {
1713 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreate() failed"));
1717 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1719 key
= CFSTR(kDSStdNotifyBTMMStatusChanged
);
1720 CFArrayAppendValue(keys
, key
);
1722 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
1725 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreSetNotificationKeys() failed"));
1730 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, -1);
1732 SCLOG(NULL
, NULL
, ASL_LEVEL_ERR
, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
1736 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1742 #endif // !TARGET_OS_EMBEDDED
1748 static __inline__ Boolean
1749 bValFromDictionary(CFDictionaryRef dict
, CFStringRef key
)
1752 Boolean result
= FALSE
;
1754 if ((dict
!= NULL
) &&
1755 CFDictionaryGetValueIfPresent(dict
, key
, (const void **)&bVal
) &&
1756 isA_CFBoolean(bVal
)) {
1757 result
= CFBooleanGetValue(bVal
);
1765 load(CFBundleRef bundle
, Boolean bundleVerbose
)
1767 CFDictionaryRef config
;
1770 verbose
= bundleVerbose
;
1772 log_msg
= asl_new(ASL_TYPE_MSG
);
1773 asl_set(log_msg
, ASL_KEY_FACILITY
, MY_ASL_FACILITY
);
1777 config
= CFBundleGetInfoDictionary(bundle
);
1778 config
= isA_CFDictionary(config
);
1779 log_all
= bValFromDictionary(config
, CFSTR("LOG_ALL"));
1781 #ifdef kIOPMMessageSleepWakeUUIDChange
1782 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_IO_WAKEUUID_EVENTS"))) {
1783 add_wake_uuid_notification();
1785 #endif // kIOPMMessageSleepWakeUUIDChange
1787 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_IO_SYSTEMPOWER_EVENTS"))) {
1788 add_power_notification();
1791 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NETWORK_KERNEL_EVENTS"))) {
1792 add_KernelEvent_notification();
1795 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_DNS_CONFIGURATION"))) {
1796 add_dnsinfo_notification();
1799 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_NETWORK_CHANGE"))) {
1800 add_network_notification();
1803 #if !TARGET_OS_EMBEDDED
1804 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_SMB_CONFIGURATION"))) {
1805 add_smbconf_notification();
1807 #endif // !TARGET_OS_EMBEDDED
1809 #if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
1810 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_NOTIFY_UTMPX_CHANGE"))) {
1811 add_pututxline_notification();
1813 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
1815 #if !TARGET_OS_EMBEDDED
1816 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_BTMM_CONFIGURATION"))) {
1817 add_BTMM_notification();
1819 #endif // !TARGET_OS_EMBEDDED
1821 #if !TARGET_OS_EMBEDDED
1822 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_CONSOLEUSER"))) {
1823 add_console_notification();
1825 #endif // !TARGET_OS_EMBEDDED
1827 #if !TARGET_OS_EMBEDDED
1828 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_DIRECTORYSERVICES_SEARCHPOLICY"))) {
1829 add_DirectoryServices_notification();
1831 #endif // !TARGET_OS_EMBEDDED
1833 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_NETWORKCHANGE"))) {
1834 add_NetworkChange_notification();
1837 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_PRIMARYSERVICE"))) {
1838 add_PrimaryService_notification();
1841 if (log_all
|| bValFromDictionary(config
, CFSTR("LOG_SC_REACHABILITY"))) {
1842 CFArrayRef hosts
= NULL
;
1844 if ((config
== NULL
) ||
1845 !CFDictionaryGetValueIfPresent(config
, CFSTR("LOG_SC_REACHABILITY_HOSTS"), (const void **)&hosts
) ||
1846 !isA_CFArray(hosts
) ||
1847 (CFArrayGetCount(hosts
) == 0)) {
1855 add_reachability_notification(hosts
);
1864 main(int argc
, char **argv
)
1867 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
1870 load(CFBundleGetMainBundle(), (argc
> 1) ? TRUE
: FALSE
);