]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCDPrivate.c
configd-596.12.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCDPrivate.c
1 /*
2 * Copyright (c) 2000-2013 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 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
34 //#define DO_NOT_CRASH
35 //#define DO_NOT_INFORM
36
37 #include <SystemConfiguration/SystemConfiguration.h>
38 #include <SystemConfiguration/SCValidation.h>
39 #include <SystemConfiguration/SCPrivate.h>
40
41 #include <sys/param.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/ioctl.h>
45 #include <net/if.h>
46 #include <net/if_dl.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49
50 #include <mach/mach.h>
51 #include <mach/notify.h>
52 #include <mach/mach_error.h>
53 #include <pthread.h>
54
55 #include <execinfo.h>
56 #include <unistd.h>
57 #include <dlfcn.h>
58
59
60 #if TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
61 #include <CoreFoundation/CFUserNotification.h>
62 #endif // TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
63
64 #define N_QUICK 32
65
66
67 #pragma mark -
68 #pragma mark Miscellaneous
69
70
71 char *
72 _SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, CFIndex bufLen, CFStringEncoding encoding)
73 {
74 CFIndex converted;
75 CFIndex last = 0;
76 CFIndex len;
77
78 if (cfstr == NULL) {
79 cfstr = CFSTR("");
80 }
81 len = CFStringGetLength(cfstr);
82
83 /* how much buffer space will we really need? */
84 converted = CFStringGetBytes(cfstr,
85 CFRangeMake(0, len),
86 encoding,
87 0,
88 FALSE,
89 NULL,
90 0,
91 &last);
92 if (converted < len) {
93 /* if full string could not be converted */
94 if (buf != NULL) {
95 buf[0] = '\0';
96 }
97 return NULL;
98 }
99
100 if (buf != NULL) {
101 if (bufLen < (last + 1)) {
102 /* if the size of the provided buffer is too small */
103 buf[0] = '\0';
104 return NULL;
105 }
106 } else {
107 /* allocate a buffer */
108 bufLen = last + 1;
109 buf = CFAllocatorAllocate(NULL, bufLen, 0);
110 if (buf == NULL) {
111 return NULL;
112 }
113 }
114
115 (void)CFStringGetBytes(cfstr,
116 CFRangeMake(0, len),
117 encoding,
118 0,
119 FALSE,
120 (UInt8 *)buf,
121 bufLen,
122 &last);
123 buf[last] = '\0';
124
125 return buf;
126 }
127
128
129 void
130 _SC_sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen)
131 {
132 union {
133 const struct sockaddr *sa;
134 const struct sockaddr_in *sin;
135 const struct sockaddr_in6 *sin6;
136 const struct sockaddr_dl *sdl;
137 } addr;
138
139 addr.sa = address;
140
141 bzero(buf, bufLen);
142 switch (address->sa_family) {
143 case AF_INET :
144 (void)inet_ntop(addr.sin->sin_family,
145 &addr.sin->sin_addr,
146 buf,
147 bufLen);
148 break;
149 case AF_INET6 : {
150 (void)inet_ntop(addr.sin6->sin6_family,
151 &addr.sin6->sin6_addr,
152 buf,
153 bufLen);
154 if (addr.sin6->sin6_scope_id != 0) {
155 int n;
156
157 n = strlen(buf);
158 if ((n+IF_NAMESIZE+1) <= (int)bufLen) {
159 buf[n++] = '%';
160 if_indextoname(addr.sin6->sin6_scope_id, &buf[n]);
161 }
162 }
163 break;
164 }
165 default :
166 snprintf(buf, bufLen, "unexpected address family %d", address->sa_family);
167 break;
168 }
169
170 return;
171 }
172
173
174 struct sockaddr *
175 _SC_string_to_sockaddr(const char *str, sa_family_t af, void *buf, size_t bufLen)
176 {
177 union {
178 void *buf;
179 struct sockaddr *sa;
180 struct sockaddr_in *sin;
181 struct sockaddr_in6 *sin6;
182 } addr;
183
184 if (buf == NULL) {
185 bufLen = sizeof(struct sockaddr_storage);
186 addr.buf = CFAllocatorAllocate(NULL, bufLen, 0);
187 } else {
188 addr.buf = buf;
189 }
190
191 bzero(addr.buf, bufLen);
192 if (((af == AF_UNSPEC) || (af == AF_INET)) &&
193 (bufLen >= sizeof(struct sockaddr_in)) &&
194 inet_aton(str, &addr.sin->sin_addr) == 1) {
195 // if IPv4 address
196 addr.sin->sin_len = sizeof(struct sockaddr_in);
197 addr.sin->sin_family = AF_INET;
198 } else if (((af == AF_UNSPEC) || (af == AF_INET6)) &&
199 (bufLen >= sizeof(struct sockaddr_in6)) &&
200 inet_pton(AF_INET6, str, &addr.sin6->sin6_addr) == 1) {
201 // if IPv6 address
202 char *p;
203
204 addr.sin6->sin6_len = sizeof(struct sockaddr_in6);
205 addr.sin6->sin6_family = AF_INET6;
206
207 p = strchr(buf, '%');
208 if (p != NULL) {
209 addr.sin6->sin6_scope_id = if_nametoindex(p + 1);
210 }
211
212 if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6->sin6_addr) ||
213 IN6_IS_ADDR_MC_LINKLOCAL(&addr.sin6->sin6_addr)) {
214 uint16_t if_index;
215
216 if_index = ntohs(addr.sin6->sin6_addr.__u6_addr.__u6_addr16[1]);
217 addr.sin6->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
218 if (addr.sin6->sin6_scope_id == 0) {
219 // use the scope id that was embedded in the [link local] IPv6 address
220 addr.sin6->sin6_scope_id = if_index;
221 }
222 }
223 } else {
224 if (addr.buf != buf) {
225 CFAllocatorDeallocate(NULL, addr.buf);
226 }
227 addr.buf = NULL;
228 }
229
230 return addr.sa;
231 }
232
233
234 void
235 _SC_sendMachMessage(mach_port_t port, mach_msg_id_t msg_id)
236 {
237 mach_msg_empty_send_t msg;
238 mach_msg_option_t options;
239 kern_return_t status;
240
241 msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
242 msg.header.msgh_size = sizeof(msg);
243 msg.header.msgh_remote_port = port;
244 msg.header.msgh_local_port = MACH_PORT_NULL;
245 msg.header.msgh_id = msg_id;
246 options = MACH_SEND_TIMEOUT;
247 status = mach_msg(&msg.header, /* msg */
248 MACH_SEND_MSG|options, /* options */
249 msg.header.msgh_size, /* send_size */
250 0, /* rcv_size */
251 MACH_PORT_NULL, /* rcv_name */
252 0, /* timeout */
253 MACH_PORT_NULL); /* notify */
254 if (status != MACH_MSG_SUCCESS) {
255 mach_msg_destroy(&msg.header);
256 }
257
258 return;
259 }
260
261
262 CFStringRef
263 _SC_trimDomain(CFStringRef domain)
264 {
265 CFIndex length;
266
267 if (!isA_CFString(domain)) {
268 return NULL;
269 }
270
271 // remove any leading/trailing dots
272 length = CFStringGetLength(domain);
273 if ((length > 0) &&
274 (CFStringFindWithOptions(domain,
275 CFSTR("."),
276 CFRangeMake(0, 1),
277 kCFCompareAnchored,
278 NULL) ||
279 CFStringFindWithOptions(domain,
280 CFSTR("."),
281 CFRangeMake(0, length),
282 kCFCompareAnchored|kCFCompareBackwards,
283 NULL))) {
284 CFMutableStringRef trimmed;
285
286 trimmed = CFStringCreateMutableCopy(NULL, 0, domain);
287 CFStringTrim(trimmed, CFSTR("."));
288 domain = (CFStringRef)trimmed;
289 length = CFStringGetLength(domain);
290 } else {
291 CFRetain(domain);
292 }
293
294 if (length == 0) {
295 CFRelease(domain);
296 domain = NULL;
297 }
298
299 return domain;
300 }
301
302
303 #pragma mark -
304 #pragma mark Serialization
305
306
307 Boolean
308 _SCSerialize(CFPropertyListRef obj, CFDataRef *xml, void **dataRef, CFIndex *dataLen)
309 {
310 CFDataRef myXml;
311
312 if ((xml == NULL) && ((dataRef == NULL) || (dataLen == NULL))) {
313 /* if not keeping track of allocated space */
314 return FALSE;
315 }
316
317 myXml = CFPropertyListCreateData(NULL,
318 obj,
319 kCFPropertyListBinaryFormat_v1_0,
320 0,
321 NULL);
322 if (myXml == NULL) {
323 SCLog(TRUE, LOG_ERR, CFSTR("_SCSerialize() failed"));
324 if (xml != NULL) {
325 *xml = NULL;
326 }
327 if ((dataRef != NULL) && (dataLen != NULL)) {
328 *dataLen = 0;
329 *dataRef = NULL;
330 }
331 return FALSE;
332 }
333
334 if (xml != NULL) {
335 *xml = myXml;
336 if ((dataRef != NULL) && (dataLen != NULL)) {
337 *dataRef = (void *)CFDataGetBytePtr(myXml);
338 *dataLen = CFDataGetLength(myXml);
339 }
340 } else {
341 mach_msg_type_number_t len;
342 kern_return_t status;
343
344 status = vm_read(mach_task_self(),
345 (vm_address_t)CFDataGetBytePtr(myXml), // address
346 (vm_size_t) CFDataGetLength(myXml), // size
347 (void *)dataRef,
348 &len);
349 if (status != KERN_SUCCESS) {
350 SCLog(TRUE, LOG_ERR, CFSTR("_SCSerialize(): %s"), mach_error_string(status));
351 CFRelease(myXml);
352 *dataRef = NULL;
353 *dataLen = 0;
354 return FALSE;
355 }
356
357 *dataLen = len;
358 CFRelease(myXml);
359 }
360
361 return TRUE;
362 }
363
364
365 Boolean
366 _SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dataLen)
367 {
368 CFErrorRef error = NULL;
369
370 if (xml == NULL) {
371 kern_return_t status;
372
373 xml = CFDataCreateWithBytesNoCopy(NULL, (void *)dataRef, dataLen, kCFAllocatorNull);
374 *obj = CFPropertyListCreateWithData(NULL, xml, kCFPropertyListImmutable, NULL, &error);
375 CFRelease(xml);
376
377 status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
378 if (status != KERN_SUCCESS) {
379 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserialize(): %s"), mach_error_string(status));
380 /* non-fatal???, proceed */
381 }
382 } else {
383 *obj = CFPropertyListCreateWithData(NULL, xml, kCFPropertyListImmutable, NULL, &error);
384 }
385
386 if (*obj == NULL) {
387 if (error != NULL) {
388 SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserialize(): %@"), error);
389 CFRelease(error);
390 }
391 _SCErrorSet(kSCStatusFailed);
392 return FALSE;
393 }
394
395 return TRUE;
396 }
397
398
399 Boolean
400 _SCSerializeString(CFStringRef str, CFDataRef *data, void **dataRef, CFIndex *dataLen)
401 {
402 CFDataRef myData;
403
404 if (!isA_CFString(str)) {
405 /* if not a CFString */
406 return FALSE;
407 }
408
409 if ((data == NULL) && ((dataRef == NULL) || (dataLen == NULL))) {
410 /* if not keeping track of allocated space */
411 return FALSE;
412 }
413
414 myData = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
415 if (myData == NULL) {
416 SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeString() failed"));
417 if (data != NULL) {
418 *data = NULL;
419 }
420 if ((dataRef != NULL) && (dataLen != NULL)) {
421 *dataRef = NULL;
422 *dataLen = 0;
423 }
424 return FALSE;
425 }
426
427 if (data != NULL) {
428 *data = myData;
429 if ((dataRef != NULL) && (dataLen != NULL)) {
430 *dataRef = (void *)CFDataGetBytePtr(myData);
431 *dataLen = CFDataGetLength(myData);
432 }
433 } else {
434 mach_msg_type_number_t len;
435 kern_return_t status;
436
437 *dataLen = CFDataGetLength(myData);
438 status = vm_read(mach_task_self(),
439 (vm_address_t)CFDataGetBytePtr(myData), // address
440 *dataLen, // size
441 (void *)dataRef,
442 &len);
443 if (status != KERN_SUCCESS) {
444 SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeString(): %s"), mach_error_string(status));
445 CFRelease(myData);
446 *dataRef = NULL;
447 *dataLen = 0;
448 return FALSE;
449 }
450
451 *dataLen = len;
452 CFRelease(myData);
453 }
454
455 return TRUE;
456 }
457
458
459 Boolean
460 _SCUnserializeString(CFStringRef *str, CFDataRef utf8, void *dataRef, CFIndex dataLen)
461 {
462 if (utf8 == NULL) {
463 kern_return_t status;
464
465 utf8 = CFDataCreateWithBytesNoCopy(NULL, dataRef, dataLen, kCFAllocatorNull);
466 *str = CFStringCreateFromExternalRepresentation(NULL, utf8, kCFStringEncodingUTF8);
467 CFRelease(utf8);
468
469 status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
470 if (status != KERN_SUCCESS) {
471 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserializeString(): %s"), mach_error_string(status));
472 /* non-fatal???, proceed */
473 }
474 } else {
475 *str = CFStringCreateFromExternalRepresentation(NULL, utf8, kCFStringEncodingUTF8);
476 }
477
478 if (*str == NULL) {
479 SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserializeString() failed"));
480 return FALSE;
481 }
482
483 return TRUE;
484 }
485
486
487 Boolean
488 _SCSerializeData(CFDataRef data, void **dataRef, CFIndex *dataLen)
489 {
490 mach_msg_type_number_t len;
491 kern_return_t status;
492
493 if (!isA_CFData(data)) {
494 /* if not a CFData */
495 return FALSE;
496 }
497
498 *dataLen = CFDataGetLength(data);
499 status = vm_read(mach_task_self(),
500 (vm_address_t)CFDataGetBytePtr(data), // address
501 *dataLen, // size
502 (void *)dataRef,
503 &len);
504 if (status != KERN_SUCCESS) {
505 SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeData(): %s"), mach_error_string(status));
506 *dataRef = NULL;
507 *dataLen = 0;
508 return FALSE;
509 }
510
511 *dataLen = len;
512
513 return TRUE;
514 }
515
516
517 Boolean
518 _SCUnserializeData(CFDataRef *data, void *dataRef, CFIndex dataLen)
519 {
520 kern_return_t status;
521
522 *data = CFDataCreate(NULL, dataRef, dataLen);
523 status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
524 if (status != KERN_SUCCESS) {
525 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserializeData(): %s"), mach_error_string(status));
526 _SCErrorSet(kSCStatusFailed);
527 return FALSE;
528 }
529
530 return TRUE;
531 }
532
533
534 CF_RETURNS_RETAINED CFDictionaryRef
535 _SCSerializeMultiple(CFDictionaryRef dict)
536 {
537 CFIndex i;
538 const void * keys_q[N_QUICK];
539 const void ** keys = keys_q;
540 CFIndex nElements;
541 CFDictionaryRef newDict = NULL;
542 const void * pLists_q[N_QUICK];
543 const void ** pLists = pLists_q;
544 const void * values_q[N_QUICK];
545 const void ** values = values_q;
546
547 nElements = CFDictionaryGetCount(dict);
548 if (nElements > 0) {
549 if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
550 keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
551 values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
552 pLists = CFAllocatorAllocate(NULL, nElements * sizeof(CFDataRef), 0);
553 }
554 bzero(pLists, nElements * sizeof(CFDataRef));
555
556 CFDictionaryGetKeysAndValues(dict, keys, values);
557 for (i = 0; i < nElements; i++) {
558 pLists[i] = NULL;
559 if (!_SCSerialize((CFPropertyListRef)values[i], (CFDataRef *)&pLists[i], NULL, NULL)) {
560 goto done;
561 }
562 }
563 }
564
565 newDict = CFDictionaryCreate(NULL,
566 keys,
567 pLists,
568 nElements,
569 &kCFTypeDictionaryKeyCallBacks,
570 &kCFTypeDictionaryValueCallBacks);
571
572 done :
573
574 if (nElements > 0) {
575 for (i = 0; i < nElements; i++) {
576 if (pLists[i] != NULL) CFRelease((CFDataRef)pLists[i]);
577 }
578
579 if (keys != keys_q) {
580 CFAllocatorDeallocate(NULL, keys);
581 CFAllocatorDeallocate(NULL, values);
582 CFAllocatorDeallocate(NULL, pLists);
583 }
584 }
585
586 return newDict;
587 }
588
589
590 CF_RETURNS_RETAINED
591 CFDictionaryRef
592 _SCUnserializeMultiple(CFDictionaryRef dict)
593 {
594 const void * keys_q[N_QUICK];
595 const void ** keys = keys_q;
596 CFIndex nElements;
597 CFDictionaryRef newDict = NULL;
598 const void * pLists_q[N_QUICK];
599 const void ** pLists = pLists_q;
600 const void * values_q[N_QUICK];
601 const void ** values = values_q;
602
603 nElements = CFDictionaryGetCount(dict);
604 if (nElements > 0) {
605 CFIndex i;
606
607 if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
608 keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
609 values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
610 pLists = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
611 }
612 bzero(pLists, nElements * sizeof(CFTypeRef));
613
614 CFDictionaryGetKeysAndValues(dict, keys, values);
615 for (i = 0; i < nElements; i++) {
616 if (!_SCUnserialize((CFPropertyListRef *)&pLists[i], values[i], NULL, 0)) {
617 goto done;
618 }
619 }
620 }
621
622 newDict = CFDictionaryCreate(NULL,
623 keys,
624 pLists,
625 nElements,
626 &kCFTypeDictionaryKeyCallBacks,
627 &kCFTypeDictionaryValueCallBacks);
628
629 done :
630
631 if (nElements > 0) {
632 CFIndex i;
633
634 for (i = 0; i < nElements; i++) {
635 if (pLists[i]) CFRelease(pLists[i]);
636 }
637
638 if (keys != keys_q) {
639 CFAllocatorDeallocate(NULL, keys);
640 CFAllocatorDeallocate(NULL, values);
641 CFAllocatorDeallocate(NULL, pLists);
642 }
643 }
644
645 return newDict;
646 }
647
648
649 #pragma mark -
650 #pragma mark CFRunLoop scheduling
651
652
653 __private_extern__ void
654 _SC_signalRunLoop(CFTypeRef obj, CFRunLoopSourceRef rls, CFArrayRef rlList)
655 {
656 CFRunLoopRef rl = NULL;
657 CFRunLoopRef rl1 = NULL;
658 CFIndex i;
659 CFIndex n = CFArrayGetCount(rlList);
660
661 if (n == 0) {
662 return;
663 }
664
665 /* get first runLoop for this object */
666 for (i = 0; i < n; i += 3) {
667 if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
668 continue;
669 }
670
671 rl1 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
672 break;
673 }
674
675 if (rl1 == NULL) {
676 /* if not scheduled */
677 return;
678 }
679
680 /* check if we have another runLoop for this object */
681 rl = rl1;
682 for (i = i+3; i < n; i += 3) {
683 CFRunLoopRef rl2;
684
685 if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
686 continue;
687 }
688
689 rl2 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
690 if (!CFEqual(rl1, rl2)) {
691 /* we've got more than one runLoop */
692 rl = NULL;
693 break;
694 }
695 }
696
697 if (rl != NULL) {
698 /* if we only have one runLoop */
699 CFRunLoopWakeUp(rl);
700 return;
701 }
702
703 /* more than one different runLoop, so we must pick one */
704 for (i = 0; i < n; i+=3) {
705 CFStringRef rlMode;
706
707 if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
708 continue;
709 }
710
711 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
712 rlMode = CFRunLoopCopyCurrentMode(rl);
713 if (rlMode != NULL) {
714 Boolean waiting;
715
716 waiting = (CFRunLoopIsWaiting(rl) && CFRunLoopContainsSource(rl, rls, rlMode));
717 CFRelease(rlMode);
718 if (waiting) {
719 /* we've found a runLoop that's "ready" */
720 CFRunLoopWakeUp(rl);
721 return;
722 }
723 }
724 }
725
726 /* didn't choose one above, so choose first */
727 CFRunLoopWakeUp(rl1);
728 return;
729 }
730
731
732 __private_extern__ Boolean
733 _SC_isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
734 {
735 CFIndex i;
736 CFIndex n = CFArrayGetCount(rlList);
737
738 for (i = 0; i < n; i += 3) {
739 if ((obj != NULL) && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
740 continue;
741 }
742 if ((runLoop != NULL) && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) {
743 continue;
744 }
745 if ((runLoopMode != NULL) && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
746 continue;
747 }
748 return TRUE;
749 }
750
751 return FALSE;
752 }
753
754
755 __private_extern__ void
756 _SC_schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
757 {
758 CFArrayAppendValue(rlList, obj);
759 CFArrayAppendValue(rlList, runLoop);
760 CFArrayAppendValue(rlList, runLoopMode);
761
762 return;
763 }
764
765
766 __private_extern__ Boolean
767 _SC_unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all)
768 {
769 CFIndex i = 0;
770 Boolean found = FALSE;
771 CFIndex n = CFArrayGetCount(rlList);
772
773 while (i < n) {
774 if ((obj != NULL) && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
775 i += 3;
776 continue;
777 }
778 if ((runLoop != NULL) && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) {
779 i += 3;
780 continue;
781 }
782 if ((runLoopMode != NULL) && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
783 i += 3;
784 continue;
785 }
786
787 found = TRUE;
788
789 CFArrayRemoveValueAtIndex(rlList, i + 2);
790 CFArrayRemoveValueAtIndex(rlList, i + 1);
791 CFArrayRemoveValueAtIndex(rlList, i);
792
793 if (!all) {
794 return found;
795 }
796
797 n -= 3;
798 }
799
800 return found;
801 }
802
803
804 #pragma mark -
805 #pragma mark Bundle
806
807
808 #define SYSTEMCONFIGURATION_BUNDLE_ID CFSTR("com.apple.SystemConfiguration")
809 #define SYSTEMCONFIGURATION_FRAMEWORK_PATH "/System/Library/Frameworks/SystemConfiguration.framework"
810 #define SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN (sizeof(SYSTEMCONFIGURATION_FRAMEWORK_PATH) - 1)
811
812 #define SUFFIX_SYM "~sym"
813 #define SUFFIX_SYM_LEN (sizeof(SUFFIX_SYM) - 1)
814
815 #define SUFFIX_DST "~dst"
816
817
818 CFBundleRef
819 _SC_CFBundleGet(void)
820 {
821 static CFBundleRef bundle = NULL;
822 char *env;
823 size_t len;
824
825 if (bundle != NULL) {
826 return bundle;
827 }
828
829 bundle = CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID);
830 if (bundle != NULL) {
831 CFRetain(bundle); // we want to hold a reference to the bundle
832 return bundle;
833 }
834
835 // if appropriate (e.g. when debugging), try a bit harder
836
837 env = getenv("DYLD_FRAMEWORK_PATH");
838 len = (env != NULL) ? strlen(env) : 0;
839
840 // trim any trailing slashes
841 while (len > 1) {
842 if (env[len - 1] != '/') {
843 break;
844 }
845 len--;
846 }
847
848 // if DYLD_FRAMEWORK_PATH is ".../xxx~sym" than try ".../xxx~dst"
849 if ((len > SUFFIX_SYM_LEN) &&
850 (strncmp(&env[len - SUFFIX_SYM_LEN], SUFFIX_SYM, SUFFIX_SYM_LEN) == 0) &&
851 ((len + SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN) < MAXPATHLEN)) {
852 char path[MAXPATHLEN];
853 CFURLRef url;
854
855 strlcpy(path, env, sizeof(path));
856 strlcpy(&path[len - SUFFIX_SYM_LEN], SUFFIX_DST, sizeof(path) - (len - SUFFIX_SYM_LEN));
857 strlcat(&path[len], SYSTEMCONFIGURATION_FRAMEWORK_PATH, sizeof(path) - len);
858
859 url = CFURLCreateFromFileSystemRepresentation(NULL,
860 (UInt8 *)path,
861 len + SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN,
862 TRUE);
863 bundle = CFBundleCreate(NULL, url);
864 CFRelease(url);
865 }
866
867 if (bundle == NULL) {
868 static Boolean warned = FALSE;
869
870 SCLog(!warned, LOG_WARNING,
871 CFSTR("_SC_CFBundleGet(), could not get CFBundle for \"%@\""),
872 SYSTEMCONFIGURATION_BUNDLE_ID);
873 warned = TRUE;
874 }
875
876 return bundle;
877 }
878
879
880 CFStringRef
881 _SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName)
882 {
883 CFDataRef data = NULL;
884 SInt32 errCode = 0;
885 Boolean ok;
886 CFURLRef resourcesURL;
887 CFStringRef str = NULL;
888 CFURLRef url;
889
890 if ((tableName == NULL) || CFEqual(tableName, CFSTR(""))) tableName = CFSTR("Localizable");
891
892 /*
893 * First, try getting the requested string using a manually constructed
894 * URL to <bundle>/Resources/English.lproj/<tableName>.strings. Do this
895 * because CFBundleCopyResourceURLForLocalization() uses CFPreferences
896 * to get the preferred localizations, CFPreferences talks to
897 * OpenDirectory, and OpenDirectory tries to obtain the platform UUID.
898 * On machines where the platform UUID is set by InterfaceNamer, a
899 * deadlock can occur if InterfaceNamer calls
900 * CFBundleCopyResourceURLForLocalization() before setting the
901 * platform UUID in the kernel.
902 */
903 resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
904 if (resourcesURL != NULL) {
905 CFStringRef fileName = CFStringCreateWithFormat(
906 NULL, NULL, CFSTR("%@.strings"), tableName);
907 CFURLRef enlproj = CFURLCreateCopyAppendingPathComponent(
908 NULL, resourcesURL, CFSTR("English.lproj"), true);
909 url = CFURLCreateCopyAppendingPathComponent(
910 NULL, enlproj, fileName, false);
911 CFRelease(enlproj);
912 CFRelease(fileName);
913 CFRelease(resourcesURL);
914
915 #pragma GCC diagnostic push
916 #pragma GCC diagnostic ignored "-Wdeprecated"
917 ok = CFURLCreateDataAndPropertiesFromResource(NULL,
918 url,
919 &data,
920 NULL,
921 NULL,
922 &errCode);
923 #pragma GCC diagnostic pop
924 if (!ok) {
925 /*
926 * Failed to get the data using a manually-constructed URL
927 * for the given strings table. Fall back to using
928 * CFBundleCopyResourceURLForLocalization() below.
929 */
930 data = NULL;
931 }
932 CFRelease(url);
933 }
934
935 if (data == NULL) {
936 url = CFBundleCopyResourceURLForLocalization(bundle,
937 tableName,
938 CFSTR("strings"),
939 NULL,
940 CFSTR("English"));
941 if (url != NULL) {
942 #pragma GCC diagnostic push
943 #pragma GCC diagnostic ignored "-Wdeprecated"
944 ok = CFURLCreateDataAndPropertiesFromResource(NULL,
945 url,
946 &data,
947 NULL,
948 NULL,
949 &errCode);
950 #pragma GCC diagnostic pop
951 if (!ok) {
952 data = NULL;
953 }
954 CFRelease(url);
955 }
956 }
957
958 if (data != NULL) {
959 CFDictionaryRef table;
960
961 table = CFPropertyListCreateWithData(NULL,
962 data,
963 kCFPropertyListImmutable,
964 NULL,
965 NULL);
966 if (table != NULL) {
967 if (isA_CFDictionary(table)) {
968 str = CFDictionaryGetValue(table, key);
969 if (str != NULL) {
970 CFRetain(str);
971 }
972 }
973
974 CFRelease(table);
975 }
976
977 CFRelease(data);
978 }
979
980 if (str == NULL) {
981 str = CFRetain(value);
982 }
983
984 return str;
985 }
986
987
988 #pragma mark -
989 #pragma mark Mach port / CFMachPort management
990
991
992 CFMachPortRef
993 _SC_CFMachPortCreateWithPort(const char *portDescription,
994 mach_port_t portNum,
995 CFMachPortCallBack callout,
996 CFMachPortContext *context)
997 {
998 CFMachPortRef port;
999 Boolean shouldFree = FALSE;
1000
1001 port = CFMachPortCreateWithPort(NULL, portNum, callout, context, &shouldFree);
1002 if ((port == NULL) || shouldFree) {
1003 CFStringRef err;
1004 char *crash_info = NULL;
1005
1006 SCLog(TRUE, LOG_ERR,
1007 CFSTR("%s: CFMachPortCreateWithPort() failed , port = %p"),
1008 portDescription,
1009 portNum);
1010 if (port != NULL) {
1011 err = CFStringCreateWithFormat(NULL, NULL,
1012 CFSTR("%s: CFMachPortCreateWithPort recycled, [old] port = %@"),
1013 portDescription, port);
1014 } else {
1015 err = CFStringCreateWithFormat(NULL, NULL,
1016 CFSTR("%s: CFMachPortCreateWithPort returned NULL"),
1017 portDescription);
1018 }
1019 crash_info = _SC_cfstring_to_cstring(err, NULL, 0, kCFStringEncodingASCII);
1020 if (err != NULL) CFRelease(err);
1021
1022
1023 err = CFStringCreateWithFormat(NULL,
1024 NULL,
1025 CFSTR("A recycled mach_port has been detected by \"%s\"."),
1026 getprogname());
1027 _SC_crash(crash_info, CFSTR("CFMachPort error"), err);
1028 CFAllocatorDeallocate(NULL, crash_info);
1029 CFRelease(err);
1030 }
1031
1032 return port;
1033 }
1034
1035
1036 #pragma mark -
1037 #pragma mark DOS encoding/codepage
1038
1039
1040 #if !TARGET_OS_IPHONE
1041 void
1042 _SC_dos_encoding_and_codepage(CFStringEncoding macEncoding,
1043 UInt32 macRegion,
1044 CFStringEncoding *dosEncoding,
1045 UInt32 *dosCodepage)
1046 {
1047 switch (macEncoding) {
1048 case kCFStringEncodingMacRoman:
1049 if (macRegion != 0) /* anything non-zero is not US */
1050 *dosEncoding = kCFStringEncodingDOSLatin1;
1051 else /* US region */
1052 *dosEncoding = kCFStringEncodingDOSLatinUS;
1053 break;
1054
1055 case kCFStringEncodingMacJapanese:
1056 *dosEncoding = kCFStringEncodingDOSJapanese;
1057 break;
1058
1059 case kCFStringEncodingMacChineseTrad:
1060 *dosEncoding = kCFStringEncodingDOSChineseTrad;
1061 break;
1062
1063 case kCFStringEncodingMacKorean:
1064 *dosEncoding = kCFStringEncodingDOSKorean;
1065 break;
1066
1067 case kCFStringEncodingMacArabic:
1068 *dosEncoding = kCFStringEncodingDOSArabic;
1069 break;
1070
1071 case kCFStringEncodingMacHebrew:
1072 *dosEncoding = kCFStringEncodingDOSHebrew;
1073 break;
1074
1075 case kCFStringEncodingMacGreek:
1076 *dosEncoding = kCFStringEncodingDOSGreek;
1077 break;
1078
1079 case kCFStringEncodingMacCyrillic:
1080 *dosEncoding = kCFStringEncodingDOSCyrillic;
1081 break;
1082
1083 case kCFStringEncodingMacThai:
1084 *dosEncoding = kCFStringEncodingDOSThai;
1085 break;
1086
1087 case kCFStringEncodingMacChineseSimp:
1088 *dosEncoding = kCFStringEncodingDOSChineseSimplif;
1089 break;
1090
1091 case kCFStringEncodingMacCentralEurRoman:
1092 *dosEncoding = kCFStringEncodingDOSLatin2;
1093 break;
1094
1095 case kCFStringEncodingMacTurkish:
1096 *dosEncoding = kCFStringEncodingDOSTurkish;
1097 break;
1098
1099 case kCFStringEncodingMacCroatian:
1100 *dosEncoding = kCFStringEncodingDOSLatin2;
1101 break;
1102
1103 case kCFStringEncodingMacIcelandic:
1104 *dosEncoding = kCFStringEncodingDOSIcelandic;
1105 break;
1106
1107 case kCFStringEncodingMacRomanian:
1108 *dosEncoding = kCFStringEncodingDOSLatin2;
1109 break;
1110
1111 case kCFStringEncodingMacFarsi:
1112 *dosEncoding = kCFStringEncodingDOSArabic;
1113 break;
1114
1115 case kCFStringEncodingMacUkrainian:
1116 *dosEncoding = kCFStringEncodingDOSCyrillic;
1117 break;
1118
1119 default:
1120 *dosEncoding = kCFStringEncodingDOSLatin1;
1121 break;
1122 }
1123
1124 *dosCodepage = CFStringConvertEncodingToWindowsCodepage(*dosEncoding);
1125 return;
1126 }
1127 #endif // !TARGET_OS_IPHONE
1128
1129
1130 #pragma mark -
1131 #pragma mark Debugging
1132
1133
1134 /*
1135 * print status of in-use mach ports
1136 */
1137 void
1138 _SC_logMachPortStatus(void)
1139 {
1140 kern_return_t status;
1141 mach_port_name_array_t ports;
1142 mach_port_type_array_t types;
1143 mach_msg_type_number_t pi, pn, tn;
1144 CFMutableStringRef str;
1145
1146 SCLog(TRUE, LOG_NOTICE, CFSTR("----------"));
1147
1148 /* report on ALL mach ports associated with this task */
1149 status = mach_port_names(mach_task_self(), &ports, &pn, &types, &tn);
1150 if (status == MACH_MSG_SUCCESS) {
1151 str = CFStringCreateMutable(NULL, 0);
1152 for (pi = 0; pi < pn; pi++) {
1153 char rights[16], *rp = &rights[0];
1154
1155 if (types[pi] != MACH_PORT_TYPE_NONE) {
1156 *rp++ = ' ';
1157 *rp++ = '(';
1158 if (types[pi] & MACH_PORT_TYPE_SEND)
1159 *rp++ = 'S';
1160 if (types[pi] & MACH_PORT_TYPE_RECEIVE)
1161 *rp++ = 'R';
1162 if (types[pi] & MACH_PORT_TYPE_SEND_ONCE)
1163 *rp++ = 'O';
1164 if (types[pi] & MACH_PORT_TYPE_PORT_SET)
1165 *rp++ = 'P';
1166 if (types[pi] & MACH_PORT_TYPE_DEAD_NAME)
1167 *rp++ = 'D';
1168 *rp++ = ')';
1169 }
1170 *rp = '\0';
1171 CFStringAppendFormat(str, NULL, CFSTR(" %d%s"), ports[pi], rights);
1172 }
1173 SCLog(TRUE, LOG_NOTICE, CFSTR("Task ports (n=%d):%@"), pn, str);
1174 CFRelease(str);
1175 }
1176
1177 return;
1178 }
1179
1180
1181 void
1182 _SC_logMachPortReferences(const char *str, mach_port_t port)
1183 {
1184 const char *blanks = " ";
1185 char buf[60];
1186 mach_port_type_t pt;
1187 mach_port_status_t recv_status = { 0 };
1188 mach_port_urefs_t refs_send = 0;
1189 mach_port_urefs_t refs_recv = 0;
1190 mach_port_urefs_t refs_once = 0;
1191 mach_port_urefs_t refs_pset = 0;
1192 mach_port_urefs_t refs_dead = 0;
1193 kern_return_t status;
1194
1195 buf[0] = '\0';
1196 if (str != NULL) {
1197 static int is_configd = -1;
1198
1199 if (is_configd == -1) {
1200 is_configd = (strcmp(getprogname(), _SC_SERVER_PROG) == 0);
1201 }
1202 if (is_configd == 1) {
1203 // if "configd", add indication if this is the M[ain] or [P]lugin thread
1204 strlcpy(buf,
1205 (CFRunLoopGetMain() == CFRunLoopGetCurrent()) ? "M " : "P ",
1206 sizeof(buf));
1207 }
1208
1209 // add provided string
1210 strlcat(buf, str, sizeof(buf));
1211
1212 // fill
1213 strlcat(buf, blanks, sizeof(buf));
1214 if (strcmp(&buf[sizeof(buf) - 3], " ") == 0) {
1215 buf[sizeof(buf) - 3] = ':';
1216 }
1217 }
1218
1219 status = mach_port_type(mach_task_self(), port, &pt);
1220 if (status != KERN_SUCCESS) {
1221 SCLog(TRUE, LOG_NOTICE,
1222 CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND): %s"),
1223 buf,
1224 port,
1225 mach_error_string(status));
1226 return;
1227 }
1228
1229 if ((pt & MACH_PORT_TYPE_SEND) != 0) {
1230 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, &refs_send);
1231 if (status != KERN_SUCCESS) {
1232 SCLog(TRUE, LOG_NOTICE,
1233 CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND): %s"),
1234 buf,
1235 port,
1236 mach_error_string(status));
1237 return;
1238 }
1239 }
1240
1241 if ((pt & MACH_PORT_TYPE_RECEIVE) != 0) {
1242 mach_msg_type_number_t count;
1243
1244 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, &refs_recv);
1245 if (status != KERN_SUCCESS) {
1246 SCLog(TRUE, LOG_NOTICE,
1247 CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_RECEIVE): %s"),
1248 buf,
1249 port,
1250 mach_error_string(status));
1251 return;
1252 }
1253
1254 count = MACH_PORT_RECEIVE_STATUS_COUNT;
1255 status = mach_port_get_attributes(mach_task_self(),
1256 port,
1257 MACH_PORT_RECEIVE_STATUS,
1258 (mach_port_info_t)&recv_status,
1259 &count);
1260 if (status != KERN_SUCCESS) {
1261 SCLog(TRUE, LOG_NOTICE,
1262 CFSTR("%smach_port_get_attributes(..., 0x%x, MACH_PORT_RECEIVE_STATUS): %s"),
1263 buf,
1264 port,
1265 mach_error_string(status));
1266 return;
1267 }
1268 }
1269
1270 if ((pt & MACH_PORT_TYPE_SEND_ONCE) != 0) {
1271 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND_ONCE, &refs_once);
1272 if (status != KERN_SUCCESS) {
1273 SCLog(TRUE, LOG_NOTICE,
1274 CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND_ONCE): %s"),
1275 buf,
1276 port,
1277 mach_error_string(status));
1278 return;
1279 }
1280 }
1281
1282 if ((pt & MACH_PORT_TYPE_PORT_SET) != 0) {
1283 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_PORT_SET, &refs_pset);
1284 if (status != KERN_SUCCESS) {
1285 SCLog(TRUE, LOG_NOTICE,
1286 CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_PORT_SET): %s"),
1287 buf,
1288 port,
1289 mach_error_string(status));
1290 return;
1291 }
1292 }
1293
1294 if ((pt & MACH_PORT_TYPE_DEAD_NAME) != 0) {
1295 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_DEAD_NAME, &refs_dead);
1296 if (status != KERN_SUCCESS) {
1297 SCLog(TRUE, LOG_NOTICE,
1298 CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_DEAD_NAME): %s"),
1299 buf,
1300 port,
1301 mach_error_string(status));
1302 return;
1303 }
1304 }
1305
1306 SCLog(TRUE, LOG_NOTICE,
1307 CFSTR("%smach port 0x%x (%d): send=%d, receive=%d, send once=%d, port set=%d, dead name=%d%s%s"),
1308 buf,
1309 port,
1310 port,
1311 refs_send,
1312 refs_recv,
1313 refs_once,
1314 refs_pset,
1315 refs_dead,
1316 recv_status.mps_nsrequest ? ", no more senders" : "",
1317 ((pt & MACH_PORT_TYPE_DEAD_NAME) != 0) ? ", dead name request" : "");
1318
1319 return;
1320 }
1321
1322
1323 CFStringRef
1324 _SC_copyBacktrace()
1325 {
1326 int n;
1327 void *stack[64];
1328 char **symbols;
1329 CFMutableStringRef trace;
1330
1331 n = backtrace(stack, sizeof(stack)/sizeof(stack[0]));
1332 if (n == -1) {
1333 SCLog(TRUE, LOG_ERR, CFSTR("backtrace() failed: %s"), strerror(errno));
1334 return NULL;
1335 }
1336
1337 trace = CFStringCreateMutable(NULL, 0);
1338
1339 symbols = backtrace_symbols(stack, n);
1340 if (symbols != NULL) {
1341 int i;
1342
1343 for (i = 0; i < n; i++) {
1344 CFStringAppendFormat(trace, NULL, CFSTR("%s\n"), symbols[i]);
1345 }
1346
1347 free(symbols);
1348 }
1349
1350 return trace;
1351 }
1352
1353
1354 /* CrashReporter info */
1355 const char *__crashreporter_info__ = NULL;
1356 asm(".desc ___crashreporter_info__, 0x10");
1357
1358
1359 static Boolean
1360 _SC_SimulateCrash(const char *crash_info, CFStringRef notifyHeader, CFStringRef notifyMessage)
1361 {
1362 Boolean ok = FALSE;
1363
1364 #if ! TARGET_IPHONE_SIMULATOR
1365 static bool (*dyfunc_SimulateCrash)(pid_t, mach_exception_data_type_t, CFStringRef) = NULL;
1366 static void *image = NULL;
1367
1368 if ((dyfunc_SimulateCrash == NULL) && (image == NULL)) {
1369 const char *framework = "/System/Library/PrivateFrameworks/CrashReporterSupport.framework/CrashReporterSupport";
1370 struct stat statbuf;
1371 const char *suffix = getenv("DYLD_IMAGE_SUFFIX");
1372 char path[MAXPATHLEN];
1373
1374 strlcpy(path, framework, sizeof(path));
1375 if (suffix) strlcat(path, suffix, sizeof(path));
1376 if (0 <= stat(path, &statbuf)) {
1377 image = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
1378 } else {
1379 image = dlopen(framework, RTLD_LAZY | RTLD_LOCAL);
1380 }
1381
1382 if (image != NULL) {
1383 dyfunc_SimulateCrash = dlsym(image, "SimulateCrash");
1384 } else {
1385 image = (void *)0x1; // to ensure that we only dlopen() once
1386 }
1387 }
1388
1389 if (dyfunc_SimulateCrash != NULL) {
1390 CFStringRef str;
1391
1392 str = CFStringCreateWithCString(NULL, crash_info, kCFStringEncodingUTF8);
1393 ok = dyfunc_SimulateCrash(getpid(), 0xbad0005cull, str);
1394 CFRelease(str);
1395 }
1396
1397 #if TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
1398 if (ok && (notifyHeader != NULL) && (notifyMessage != NULL)) {
1399 static Boolean warned = FALSE;
1400
1401 if (!warned) {
1402 CFStringRef displayMessage;
1403
1404 displayMessage = CFStringCreateWithFormat(NULL,
1405 NULL,
1406 CFSTR("%@\n\nPlease collect the crash report and file a Radar."),
1407 notifyMessage);
1408 CFUserNotificationDisplayNotice(0,
1409 kCFUserNotificationStopAlertLevel,
1410 NULL,
1411 NULL,
1412 NULL,
1413 notifyHeader,
1414 displayMessage,
1415 NULL);
1416 CFRelease(displayMessage);
1417 warned = TRUE;
1418 }
1419 }
1420 #endif // TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
1421 #endif /* ! TARGET_IPHONE_SIMULATOR */
1422
1423 return ok;
1424 }
1425
1426
1427 void
1428 _SC_crash(const char *crash_info, CFStringRef notifyHeader, CFStringRef notifyMessage)
1429 {
1430 Boolean ok = FALSE;
1431
1432 if (crash_info != NULL) {
1433 __crashreporter_info__ = crash_info;
1434
1435 SCLog(TRUE, LOG_ERR, CFSTR("%s"), crash_info);
1436 }
1437
1438 if (_SC_isAppleInternal()) {
1439 // simulate a crash report
1440 ok = _SC_SimulateCrash(crash_info, notifyHeader, notifyMessage);
1441 #ifndef DO_NOT_CRASH
1442 if (!ok) {
1443 // if we could not simulate a crash report, crash for real
1444 __builtin_trap();
1445 }
1446 #endif // DO_NOT_CRASH
1447 }
1448
1449 __crashreporter_info__ = NULL;
1450 return;
1451 }
1452
1453
1454 Boolean
1455 _SC_getconninfo(int socket, struct sockaddr_storage *src_addr, struct sockaddr_storage *dest_addr, int *if_index, uint32_t *flags)
1456 {
1457 struct so_cinforeq request;
1458
1459 memset(&request, 0, sizeof(request));
1460
1461 if (src_addr != NULL) {
1462 memset(src_addr, 0, sizeof(*src_addr));
1463 request.scir_src = (struct sockaddr *)src_addr;
1464 request.scir_src_len = sizeof(*src_addr);
1465 }
1466
1467 if (dest_addr != NULL) {
1468 memset(dest_addr, 0, sizeof(*dest_addr));
1469 request.scir_dst = (struct sockaddr *)dest_addr;
1470 request.scir_dst_len = sizeof(*dest_addr);
1471 }
1472
1473 if (ioctl(socket, SIOCGCONNINFO, &request) != 0) {
1474 SCLog(TRUE, LOG_WARNING, CFSTR("SIOCGCONNINFO failed: %s"), strerror(errno));
1475 return FALSE;
1476 }
1477
1478 if (if_index != NULL) {
1479 *if_index = 0;
1480 *if_index = request.scir_ifindex;
1481 }
1482
1483 if (flags != NULL) {
1484 *flags = 0;
1485 *flags = request.scir_flags;
1486 }
1487
1488 return TRUE;
1489 }