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