2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
34 #include <SystemConfiguration/SystemConfiguration.h>
35 #include <SystemConfiguration/SCValidation.h>
36 #include <SystemConfiguration/SCPrivate.h>
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
42 #include <net/if_dl.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
46 #include <mach/mach.h>
47 #include <mach/notify.h>
48 #include <mach/mach_error.h>
59 #pragma mark Miscellaneous
63 _SC_cfstring_to_cstring(CFStringRef cfstr
, char *buf
, CFIndex bufLen
, CFStringEncoding encoding
)
72 len
= CFStringGetLength(cfstr
);
74 /* how much buffer space will we really need? */
75 converted
= CFStringGetBytes(cfstr
,
83 if (converted
< len
) {
84 /* if full string could not be converted */
92 if (bufLen
< (last
+ 1)) {
93 /* if the size of the provided buffer is too small */
98 /* allocate a buffer */
100 buf
= CFAllocatorAllocate(NULL
, bufLen
, 0);
106 (void)CFStringGetBytes(cfstr
,
121 _SC_sockaddr_to_string(const struct sockaddr
*address
, char *buf
, size_t bufLen
)
124 switch (address
->sa_family
) {
126 (void)inet_ntop(((struct sockaddr_in
*)address
)->sin_family
,
127 &((struct sockaddr_in
*)address
)->sin_addr
,
132 (void)inet_ntop(((struct sockaddr_in6
*)address
)->sin6_family
,
133 &((struct sockaddr_in6
*)address
)->sin6_addr
,
136 if (((struct sockaddr_in6
*)address
)->sin6_scope_id
!= 0) {
140 if ((n
+IF_NAMESIZE
+1) <= (int)bufLen
) {
142 if_indextoname(((struct sockaddr_in6
*)address
)->sin6_scope_id
, &buf
[n
]);
148 if (((struct sockaddr_dl
*)address
)->sdl_len
< bufLen
) {
149 bufLen
= ((struct sockaddr_dl
*)address
)->sdl_len
;
154 bcopy(((struct sockaddr_dl
*)address
)->sdl_data
, buf
, bufLen
);
157 snprintf(buf
, bufLen
, "unexpected address family %d", address
->sa_family
);
166 _SC_sendMachMessage(mach_port_t port
, mach_msg_id_t msg_id
)
168 mach_msg_empty_send_t msg
;
169 mach_msg_option_t options
;
170 kern_return_t status
;
172 msg
.header
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0);
173 msg
.header
.msgh_size
= sizeof(msg
);
174 msg
.header
.msgh_remote_port
= port
;
175 msg
.header
.msgh_local_port
= MACH_PORT_NULL
;
176 msg
.header
.msgh_id
= msg_id
;
177 options
= MACH_SEND_TIMEOUT
;
178 status
= mach_msg(&msg
.header
, /* msg */
179 MACH_SEND_MSG
|options
, /* options */
180 msg
.header
.msgh_size
, /* send_size */
182 MACH_PORT_NULL
, /* rcv_name */
184 MACH_PORT_NULL
); /* notify */
185 if (status
== MACH_SEND_TIMED_OUT
) {
186 mach_msg_destroy(&msg
.header
);
194 #pragma mark Serialization
198 _SCSerialize(CFPropertyListRef obj
, CFDataRef
*xml
, void **dataRef
, CFIndex
*dataLen
)
201 CFWriteStreamRef stream
;
203 if ((xml
== NULL
) && ((dataRef
== NULL
) || (dataLen
== NULL
))) {
204 /* if not keeping track of allocated space */
208 stream
= CFWriteStreamCreateWithAllocatedBuffers(NULL
, NULL
);
209 CFWriteStreamOpen(stream
);
210 CFPropertyListWriteToStream(obj
, stream
, kCFPropertyListBinaryFormat_v1_0
, NULL
);
211 CFWriteStreamClose(stream
);
212 myXml
= CFWriteStreamCopyProperty(stream
, kCFStreamPropertyDataWritten
);
215 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerialize() failed"));
219 if ((dataRef
!= NULL
) && (dataLen
!= NULL
)) {
228 if ((dataRef
!= NULL
) && (dataLen
!= NULL
)) {
229 *dataRef
= (void *)CFDataGetBytePtr(myXml
);
230 *dataLen
= CFDataGetLength(myXml
);
233 mach_msg_type_number_t len
;
234 kern_return_t status
;
236 status
= vm_read(mach_task_self(),
237 (vm_address_t
)CFDataGetBytePtr(myXml
), // address
238 (vm_size_t
) CFDataGetLength(myXml
), // size
241 if (status
!= KERN_SUCCESS
) {
242 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerialize(): %s"), mach_error_string(status
));
258 _SCUnserialize(CFPropertyListRef
*obj
, CFDataRef xml
, void *dataRef
, CFIndex dataLen
)
260 CFStringRef xmlError
;
263 kern_return_t status
;
265 xml
= CFDataCreateWithBytesNoCopy(NULL
, (void *)dataRef
, dataLen
, kCFAllocatorNull
);
266 *obj
= CFPropertyListCreateFromXMLData(NULL
,
268 kCFPropertyListImmutable
,
272 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
273 if (status
!= KERN_SUCCESS
) {
274 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCUnserialize(): %s"), mach_error_string(status
));
275 /* non-fatal???, proceed */
278 *obj
= CFPropertyListCreateFromXMLData(NULL
,
280 kCFPropertyListImmutable
,
285 if (xmlError
!= NULL
) {
286 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCUnserialize(): %@"), xmlError
);
289 _SCErrorSet(kSCStatusFailed
);
298 _SCSerializeString(CFStringRef str
, CFDataRef
*data
, void **dataRef
, CFIndex
*dataLen
)
302 if (!isA_CFString(str
)) {
303 /* if not a CFString */
307 if ((data
== NULL
) && ((dataRef
== NULL
) || (dataLen
== NULL
))) {
308 /* if not keeping track of allocated space */
312 myData
= CFStringCreateExternalRepresentation(NULL
, str
, kCFStringEncodingUTF8
, 0);
313 if (myData
== NULL
) {
314 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerializeString() failed"));
318 if ((dataRef
!= NULL
) && (dataLen
!= NULL
)) {
327 if ((dataRef
!= NULL
) && (dataLen
!= NULL
)) {
328 *dataRef
= (void *)CFDataGetBytePtr(myData
);
329 *dataLen
= CFDataGetLength(myData
);
332 mach_msg_type_number_t len
;
333 kern_return_t status
;
335 *dataLen
= CFDataGetLength(myData
);
336 status
= vm_read(mach_task_self(),
337 (vm_address_t
)CFDataGetBytePtr(myData
), // address
341 if (status
!= KERN_SUCCESS
) {
342 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerializeString(): %s"), mach_error_string(status
));
358 _SCUnserializeString(CFStringRef
*str
, CFDataRef utf8
, void *dataRef
, CFIndex dataLen
)
361 kern_return_t status
;
363 utf8
= CFDataCreateWithBytesNoCopy(NULL
, dataRef
, dataLen
, kCFAllocatorNull
);
364 *str
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
);
367 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
368 if (status
!= KERN_SUCCESS
) {
369 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCUnserializeString(): %s"), mach_error_string(status
));
370 /* non-fatal???, proceed */
373 *str
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
);
377 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCUnserializeString() failed"));
386 _SCSerializeData(CFDataRef data
, void **dataRef
, CFIndex
*dataLen
)
388 mach_msg_type_number_t len
;
389 kern_return_t status
;
391 if (!isA_CFData(data
)) {
392 /* if not a CFData */
396 *dataLen
= CFDataGetLength(data
);
397 status
= vm_read(mach_task_self(),
398 (vm_address_t
)CFDataGetBytePtr(data
), // address
402 if (status
!= KERN_SUCCESS
) {
403 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerializeData(): %s"), mach_error_string(status
));
416 _SCUnserializeData(CFDataRef
*data
, void *dataRef
, CFIndex dataLen
)
418 kern_return_t status
;
420 *data
= CFDataCreate(NULL
, dataRef
, dataLen
);
421 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
422 if (status
!= KERN_SUCCESS
) {
423 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCUnserializeData(): %s"), mach_error_string(status
));
424 _SCErrorSet(kSCStatusFailed
);
433 _SCSerializeMultiple(CFDictionaryRef dict
)
435 const void * keys_q
[N_QUICK
];
436 const void ** keys
= keys_q
;
438 CFDictionaryRef newDict
= NULL
;
439 const void * pLists_q
[N_QUICK
];
440 const void ** pLists
= pLists_q
;
441 const void * values_q
[N_QUICK
];
442 const void ** values
= values_q
;
444 nElements
= CFDictionaryGetCount(dict
);
448 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
449 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
450 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
451 pLists
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
453 bzero(pLists
, nElements
* sizeof(CFTypeRef
));
455 CFDictionaryGetKeysAndValues(dict
, keys
, values
);
456 for (i
= 0; i
< nElements
; i
++) {
457 if (!_SCSerialize((CFPropertyListRef
)values
[i
], (CFDataRef
*)&pLists
[i
], NULL
, NULL
)) {
463 newDict
= CFDictionaryCreate(NULL
,
467 &kCFTypeDictionaryKeyCallBacks
,
468 &kCFTypeDictionaryValueCallBacks
);
475 for (i
= 0; i
< nElements
; i
++) {
476 if (pLists
[i
]) CFRelease(pLists
[i
]);
479 if (keys
!= keys_q
) {
480 CFAllocatorDeallocate(NULL
, keys
);
481 CFAllocatorDeallocate(NULL
, values
);
482 CFAllocatorDeallocate(NULL
, pLists
);
491 _SCUnserializeMultiple(CFDictionaryRef dict
)
493 const void * keys_q
[N_QUICK
];
494 const void ** keys
= keys_q
;
496 CFDictionaryRef newDict
= NULL
;
497 const void * pLists_q
[N_QUICK
];
498 const void ** pLists
= pLists_q
;
499 const void * values_q
[N_QUICK
];
500 const void ** values
= values_q
;
502 nElements
= CFDictionaryGetCount(dict
);
506 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
507 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
508 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
509 pLists
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
511 bzero(pLists
, nElements
* sizeof(CFTypeRef
));
513 CFDictionaryGetKeysAndValues(dict
, keys
, values
);
514 for (i
= 0; i
< nElements
; i
++) {
515 if (!_SCUnserialize((CFPropertyListRef
*)&pLists
[i
], values
[i
], NULL
, 0)) {
521 newDict
= CFDictionaryCreate(NULL
,
525 &kCFTypeDictionaryKeyCallBacks
,
526 &kCFTypeDictionaryValueCallBacks
);
533 for (i
= 0; i
< nElements
; i
++) {
534 if (pLists
[i
]) CFRelease(pLists
[i
]);
537 if (keys
!= keys_q
) {
538 CFAllocatorDeallocate(NULL
, keys
);
539 CFAllocatorDeallocate(NULL
, values
);
540 CFAllocatorDeallocate(NULL
, pLists
);
549 #pragma mark CFRunLoop scheduling
552 __private_extern__
void
553 _SC_signalRunLoop(CFTypeRef obj
, CFRunLoopSourceRef rls
, CFArrayRef rlList
)
555 CFRunLoopRef rl
= NULL
;
556 CFRunLoopRef rl1
= NULL
;
558 CFIndex n
= CFArrayGetCount(rlList
);
564 /* get first runLoop for this object */
565 for (i
= 0; i
< n
; i
+= 3) {
566 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
570 rl1
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1);
575 /* if not scheduled */
579 /* check if we have another runLoop for this object */
581 for (i
= i
+3; i
< n
; i
+= 3) {
584 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
588 rl2
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1);
589 if (!CFEqual(rl1
, rl2
)) {
590 /* we've got more than one runLoop */
597 /* if we only have one runLoop */
602 /* more than one different runLoop, so we must pick one */
603 for (i
= 0; i
< n
; i
+=3) {
606 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
610 rl
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1);
611 rlMode
= CFRunLoopCopyCurrentMode(rl
);
612 if (rlMode
!= NULL
) {
615 waiting
= (CFRunLoopIsWaiting(rl
) && CFRunLoopContainsSource(rl
, rls
, rlMode
));
618 /* we've found a runLoop that's "ready" */
625 /* didn't choose one above, so choose first */
626 CFRunLoopWakeUp(rl1
);
631 __private_extern__ Boolean
632 _SC_isScheduled(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
)
635 CFIndex n
= CFArrayGetCount(rlList
);
637 for (i
= 0; i
< n
; i
+= 3) {
638 if ((obj
!= NULL
) && !CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
641 if ((runLoop
!= NULL
) && !CFEqual(runLoop
, CFArrayGetValueAtIndex(rlList
, i
+1))) {
644 if ((runLoopMode
!= NULL
) && !CFEqual(runLoopMode
, CFArrayGetValueAtIndex(rlList
, i
+2))) {
654 __private_extern__
void
655 _SC_schedule(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
)
657 CFArrayAppendValue(rlList
, obj
);
658 CFArrayAppendValue(rlList
, runLoop
);
659 CFArrayAppendValue(rlList
, runLoopMode
);
665 __private_extern__ Boolean
666 _SC_unschedule(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
, Boolean all
)
669 Boolean found
= FALSE
;
670 CFIndex n
= CFArrayGetCount(rlList
);
673 if ((obj
!= NULL
) && !CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
677 if ((runLoop
!= NULL
) && !CFEqual(runLoop
, CFArrayGetValueAtIndex(rlList
, i
+1))) {
681 if ((runLoopMode
!= NULL
) && !CFEqual(runLoopMode
, CFArrayGetValueAtIndex(rlList
, i
+2))) {
688 CFArrayRemoveValueAtIndex(rlList
, i
+ 2);
689 CFArrayRemoveValueAtIndex(rlList
, i
+ 1);
690 CFArrayRemoveValueAtIndex(rlList
, i
);
707 #define SYSTEMCONFIGURATION_BUNDLE_ID CFSTR("com.apple.SystemConfiguration")
708 #define SYSTEMCONFIGURATION_FRAMEWORK_PATH "/System/Library/Frameworks/SystemConfiguration.framework"
709 #define SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN (sizeof(SYSTEMCONFIGURATION_FRAMEWORK_PATH) - 1)
711 #define SUFFIX_SYM "~sym"
712 #define SUFFIX_SYM_LEN (sizeof(SUFFIX_SYM) - 1)
714 #define SUFFIX_DST "~dst"
718 _SC_CFBundleGet(void)
720 static CFBundleRef bundle
= NULL
;
724 if (bundle
!= NULL
) {
728 bundle
= CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID
);
729 if (bundle
!= NULL
) {
730 CFRetain(bundle
); // we want to hold a reference to the bundle
734 // if appropriate (e.g. when debugging), try a bit harder
736 env
= getenv("DYLD_FRAMEWORK_PATH");
737 len
= (env
!= NULL
) ? strlen(env
) : 0;
739 // trim any trailing slashes
741 if (env
[len
- 1] != '/') {
747 // if DYLD_FRAMEWORK_PATH is ".../xxx~sym" than try ".../xxx~dst"
748 if ((len
> SUFFIX_SYM_LEN
) &&
749 (strncmp(&env
[len
- SUFFIX_SYM_LEN
], SUFFIX_SYM
, SUFFIX_SYM_LEN
) == 0) &&
750 ((len
+ SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN
) < MAXPATHLEN
)) {
751 char path
[MAXPATHLEN
];
754 strlcpy(path
, env
, sizeof(path
));
755 strlcpy(&path
[len
- SUFFIX_SYM_LEN
], SUFFIX_DST
, sizeof(path
) - (len
- SUFFIX_SYM_LEN
));
756 strlcat(&path
[len
], SYSTEMCONFIGURATION_FRAMEWORK_PATH
, sizeof(path
) - len
);
758 url
= CFURLCreateFromFileSystemRepresentation(NULL
,
760 len
+ SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN
,
762 bundle
= CFBundleCreate(NULL
, url
);
766 if (bundle
== NULL
) {
767 static Boolean warned
= FALSE
;
769 SCLog(!warned
, LOG_WARNING
,
770 CFSTR("_SC_CFBundleGet(), could not get CFBundle for \"%@\""),
771 SYSTEMCONFIGURATION_BUNDLE_ID
);
780 _SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle
, CFStringRef key
, CFStringRef value
, CFStringRef tableName
)
782 CFStringRef str
= NULL
;
785 if ((tableName
== NULL
) || CFEqual(tableName
, CFSTR(""))) tableName
= CFSTR("Localizable");
787 url
= CFBundleCopyResourceURLForLocalization(bundle
,
793 CFDataRef data
= NULL
;
796 if (CFURLCreateDataAndPropertiesFromResource(NULL
,
802 CFDictionaryRef table
;
804 table
= (CFDictionaryRef
)CFPropertyListCreateFromXMLData(NULL
,
806 kCFPropertyListImmutable
,
809 if (isA_CFDictionary(table
)) {
810 str
= CFDictionaryGetValue(table
, key
);
826 str
= CFRetain(value
);
834 #pragma mark DOS encoding/codepage
837 #if !TARGET_OS_IPHONE
839 _SC_dos_encoding_and_codepage(CFStringEncoding macEncoding
,
841 CFStringEncoding
*dosEncoding
,
844 switch (macEncoding
) {
845 case kCFStringEncodingMacRoman
:
846 if (macRegion
!= 0) /* anything non-zero is not US */
847 *dosEncoding
= kCFStringEncodingDOSLatin1
;
849 *dosEncoding
= kCFStringEncodingDOSLatinUS
;
852 case kCFStringEncodingMacJapanese
:
853 *dosEncoding
= kCFStringEncodingDOSJapanese
;
856 case kCFStringEncodingMacChineseTrad
:
857 *dosEncoding
= kCFStringEncodingDOSChineseTrad
;
860 case kCFStringEncodingMacKorean
:
861 *dosEncoding
= kCFStringEncodingDOSKorean
;
864 case kCFStringEncodingMacArabic
:
865 *dosEncoding
= kCFStringEncodingDOSArabic
;
868 case kCFStringEncodingMacHebrew
:
869 *dosEncoding
= kCFStringEncodingDOSHebrew
;
872 case kCFStringEncodingMacGreek
:
873 *dosEncoding
= kCFStringEncodingDOSGreek
;
876 case kCFStringEncodingMacCyrillic
:
877 *dosEncoding
= kCFStringEncodingDOSCyrillic
;
880 case kCFStringEncodingMacThai
:
881 *dosEncoding
= kCFStringEncodingDOSThai
;
884 case kCFStringEncodingMacChineseSimp
:
885 *dosEncoding
= kCFStringEncodingDOSChineseSimplif
;
888 case kCFStringEncodingMacCentralEurRoman
:
889 *dosEncoding
= kCFStringEncodingDOSLatin2
;
892 case kCFStringEncodingMacTurkish
:
893 *dosEncoding
= kCFStringEncodingDOSTurkish
;
896 case kCFStringEncodingMacCroatian
:
897 *dosEncoding
= kCFStringEncodingDOSLatin2
;
900 case kCFStringEncodingMacIcelandic
:
901 *dosEncoding
= kCFStringEncodingDOSIcelandic
;
904 case kCFStringEncodingMacRomanian
:
905 *dosEncoding
= kCFStringEncodingDOSLatin2
;
908 case kCFStringEncodingMacFarsi
:
909 *dosEncoding
= kCFStringEncodingDOSArabic
;
912 case kCFStringEncodingMacUkrainian
:
913 *dosEncoding
= kCFStringEncodingDOSCyrillic
;
917 *dosEncoding
= kCFStringEncodingDOSLatin1
;
921 *dosCodepage
= CFStringConvertEncodingToWindowsCodepage(*dosEncoding
);
924 #endif // !TARGET_OS_IPHONE
928 #pragma mark Debugging
932 * print status of in-use mach ports
935 _SC_logMachPortStatus(void)
937 kern_return_t status
;
938 mach_port_name_array_t ports
;
939 mach_port_type_array_t types
;
940 mach_msg_type_number_t pi
, pn
, tn
;
941 CFMutableStringRef str
;
943 SCLog(TRUE
, LOG_DEBUG
, CFSTR("----------"));
945 /* report on ALL mach ports associated with this task */
946 status
= mach_port_names(mach_task_self(), &ports
, &pn
, &types
, &tn
);
947 if (status
== MACH_MSG_SUCCESS
) {
948 str
= CFStringCreateMutable(NULL
, 0);
949 for (pi
= 0; pi
< pn
; pi
++) {
950 char rights
[16], *rp
= &rights
[0];
952 if (types
[pi
] != MACH_PORT_TYPE_NONE
) {
955 if (types
[pi
] & MACH_PORT_TYPE_SEND
)
957 if (types
[pi
] & MACH_PORT_TYPE_RECEIVE
)
959 if (types
[pi
] & MACH_PORT_TYPE_SEND_ONCE
)
961 if (types
[pi
] & MACH_PORT_TYPE_PORT_SET
)
963 if (types
[pi
] & MACH_PORT_TYPE_DEAD_NAME
)
968 CFStringAppendFormat(str
, NULL
, CFSTR(" %d%s"), ports
[pi
], rights
);
970 SCLog(TRUE
, LOG_DEBUG
, CFSTR("Task ports (n=%d):%@"), pn
, str
);
979 _SC_logMachPortReferences(const char *str
, mach_port_t port
)
981 const char *blanks
= " ";
984 mach_port_status_t recv_status
= { 0 };
985 mach_port_urefs_t refs_send
= 0;
986 mach_port_urefs_t refs_recv
= 0;
987 mach_port_urefs_t refs_once
= 0;
988 mach_port_urefs_t refs_pset
= 0;
989 mach_port_urefs_t refs_dead
= 0;
990 kern_return_t status
;
994 static int is_configd
= -1;
996 if (is_configd
== -1) {
999 (void) proc_name(getpid(), name
, sizeof(name
));
1000 is_configd
= (strncmp(name
, "configd", sizeof(name
)) == 0);
1002 if (is_configd
== 1) {
1003 // if "configd", add indication if this is the M[ain] or [P]lugin thread
1005 (CFRunLoopGetMain() == CFRunLoopGetCurrent()) ? "M " : "P ",
1009 // add provided string
1010 strlcat(buf
, str
, sizeof(buf
));
1013 strlcat(buf
, blanks
, sizeof(buf
));
1014 if (strcmp(&buf
[sizeof(buf
) - 3], " ") == 0) {
1015 buf
[sizeof(buf
) - 3] = ':';
1019 status
= mach_port_type(mach_task_self(), port
, &pt
);
1020 if (status
!= KERN_SUCCESS
) {
1021 SCLog(TRUE
, LOG_DEBUG
,
1022 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND): %s"),
1025 mach_error_string(status
));
1028 if ((pt
& MACH_PORT_TYPE_SEND
) != 0) {
1029 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND
, &refs_send
);
1030 if (status
!= KERN_SUCCESS
) {
1031 SCLog(TRUE
, LOG_DEBUG
,
1032 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND): %s"),
1035 mach_error_string(status
));
1039 if ((pt
& MACH_PORT_TYPE_RECEIVE
) != 0) {
1040 mach_msg_type_number_t count
;
1042 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_RECEIVE
, &refs_recv
);
1043 if (status
!= KERN_SUCCESS
) {
1044 SCLog(TRUE
, LOG_DEBUG
,
1045 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_RECEIVE): %s"),
1048 mach_error_string(status
));
1051 count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1052 status
= mach_port_get_attributes(mach_task_self(),
1054 MACH_PORT_RECEIVE_STATUS
,
1055 (mach_port_info_t
)&recv_status
,
1057 if (status
!= KERN_SUCCESS
) {
1058 SCLog(TRUE
, LOG_DEBUG
,
1059 CFSTR("%mach_port_get_attributes(..., %d, MACH_PORT_RECEIVE_STATUS): %s"),
1062 mach_error_string(status
));
1066 if ((pt
& MACH_PORT_TYPE_SEND_ONCE
) != 0) {
1067 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND_ONCE
, &refs_once
);
1068 if (status
!= KERN_SUCCESS
) {
1069 SCLog(TRUE
, LOG_DEBUG
,
1070 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND_ONCE): %s"),
1073 mach_error_string(status
));
1077 if ((pt
& MACH_PORT_TYPE_PORT_SET
) != 0) {
1078 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_PORT_SET
, &refs_pset
);
1079 if (status
!= KERN_SUCCESS
) {
1080 SCLog(TRUE
, LOG_DEBUG
,
1081 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_PORT_SET): %s"),
1084 mach_error_string(status
));
1088 if ((pt
& MACH_PORT_TYPE_DEAD_NAME
) != 0) {
1089 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_DEAD_NAME
, &refs_dead
);
1090 if (status
!= KERN_SUCCESS
) {
1091 SCLog(TRUE
, LOG_DEBUG
,
1092 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_DEAD_NAME): %s"),
1095 mach_error_string(status
));
1099 SCLog(TRUE
, LOG_DEBUG
,
1100 CFSTR("%smach port 0x%x (%d): send=%d, receive=%d, send once=%d, port set=%d, dead name=%d%s%s"),
1109 recv_status
.mps_nsrequest
? ", no more senders" : "",
1110 ((pt
& MACH_PORT_TYPE_DEAD_NAME
) != 0) ? ", dead name request" : "");
1122 CFMutableStringRef trace
;
1124 n
= backtrace(stack
, sizeof(stack
)/sizeof(stack
[0]));
1126 SCLog(TRUE
, LOG_ERR
, CFSTR("backtrace() failed: %s"), strerror(errno
));
1130 trace
= CFStringCreateMutable(NULL
, 0);
1132 symbols
= backtrace_symbols(stack
, n
);
1133 if (symbols
!= NULL
) {
1136 for (i
= 0; i
< n
; i
++) {
1137 CFStringAppendFormat(trace
, NULL
, CFSTR("%s\n"), symbols
[i
]);