2  * Copyright (c) 2000-2019 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 #define SC_LOG_HANDLE   _SC_LOG_DEFAULT 
  35 #include <SystemConfiguration/SystemConfiguration.h> 
  36 #include <SystemConfiguration/SCValidation.h> 
  37 #include <SystemConfiguration/SCPrivate.h> 
  39 #include <sys/param.h> 
  40 #include <sys/types.h> 
  41 #include <sys/socket.h> 
  42 #include <sys/ioctl.h> 
  44 #include <net/if_dl.h> 
  45 #include <netinet/in.h> 
  46 #include <arpa/inet.h> 
  48 #include <dispatch/dispatch.h> 
  50 #include <mach/mach.h> 
  51 #include <mach/notify.h> 
  52 #include <mach/mach_error.h> 
  58 #if     TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 
  59 #include <CoreFoundation/CFUserNotification.h> 
  60 #endif  // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 
  62 /* CrashReporter "Application Specific Information" */ 
  63 #include <CrashReporterClient.h> 
  69 #pragma mark Miscellaneous 
  72 __private_extern__ 
char * 
  73 _SC_cfstring_to_cstring_ext(CFStringRef cfstr
, char *buf
, CFIndex bufLen
, CFStringEncoding encoding
, UInt8 lossByte
, CFIndex 
*usedBufLen
) 
  82         len 
= CFStringGetLength(cfstr
); 
  84         /* how much buffer space will we really need? */ 
  85         converted 
= CFStringGetBytes(cfstr
, 
  93         if (converted 
< len
) { 
  94                 /* if full string could not be converted */ 
 102                 if (bufLen 
< (last 
+ 1)) { 
 103                         /* if the size of the provided buffer is too small */ 
 108                 /* allocate a buffer */ 
 110                 buf 
= CFAllocatorAllocate(NULL
, bufLen
, 0); 
 116         (void)CFStringGetBytes(cfstr
, 
 126         if (usedBufLen 
!= NULL
) { 
 135 _SC_cfstring_to_cstring(CFStringRef cfstr
, char *buf
, CFIndex bufLen
, CFStringEncoding encoding
) 
 137         return _SC_cfstring_to_cstring_ext(cfstr
, buf
, bufLen
, encoding
, 0, NULL
); 
 143 _SC_sockaddr_to_string(const struct sockaddr 
*address
, char *buf
, size_t bufLen
) 
 146                 const struct sockaddr           
*sa
; 
 147                 const struct sockaddr_in        
*sin
; 
 148                 const struct sockaddr_in6       
*sin6
; 
 149                 const struct sockaddr_dl        
*sdl
; 
 154         memset(buf
, 0, bufLen
); 
 155         switch (address
->sa_family
) { 
 157                         (void)inet_ntop(addr
.sin
->sin_family
, 
 163                         (void)inet_ntop(addr
.sin6
->sin6_family
, 
 164                                         &addr
.sin6
->sin6_addr
, 
 167                         if (addr
.sin6
->sin6_scope_id 
!= 0) { 
 171                                 if ((n
+IF_NAMESIZE
+1) <= bufLen
) { 
 173                                         if_indextoname(addr
.sin6
->sin6_scope_id
, &buf
[n
]); 
 179                         snprintf(buf
, bufLen
, "unexpected address family %d", address
->sa_family
); 
 188 _SC_string_to_sockaddr(const char *str
, sa_family_t af
, void *buf
, size_t bufLen
) 
 193                 struct sockaddr_in      
*sin
; 
 194                 struct sockaddr_in6     
*sin6
; 
 198                 bufLen 
= sizeof(struct sockaddr_storage
); 
 199                 addr
.buf 
= CFAllocatorAllocate(NULL
, bufLen
, 0); 
 204         memset(addr
.buf
, 0, bufLen
); 
 205         if (((af 
== AF_UNSPEC
) || (af 
== AF_INET
)) && 
 206             (bufLen 
>= sizeof(struct sockaddr_in
)) && 
 207             inet_aton(str
, &addr
.sin
->sin_addr
) == 1) { 
 209                 addr
.sin
->sin_len    
= sizeof(struct sockaddr_in
); 
 210                 addr
.sin
->sin_family 
= AF_INET
; 
 211         } else if (((af 
== AF_UNSPEC
) || (af 
== AF_INET6
)) && 
 212                    (bufLen 
>= sizeof(struct sockaddr_in6
)) && 
 213                    inet_pton(AF_INET6
, str
, &addr
.sin6
->sin6_addr
) == 1) { 
 217                 addr
.sin6
->sin6_len    
= sizeof(struct sockaddr_in6
); 
 218                 addr
.sin6
->sin6_family 
= AF_INET6
; 
 220                 p 
= strchr(str
, '%'); 
 222                         addr
.sin6
->sin6_scope_id 
= if_nametoindex(p 
+ 1); 
 225                 if (IN6_IS_ADDR_LINKLOCAL(&addr
.sin6
->sin6_addr
) || 
 226                     IN6_IS_ADDR_MC_LINKLOCAL(&addr
.sin6
->sin6_addr
)) { 
 229                         if_index 
= ntohs(addr
.sin6
->sin6_addr
.__u6_addr
.__u6_addr16
[1]); 
 230                         addr
.sin6
->sin6_addr
.__u6_addr
.__u6_addr16
[1] = 0; 
 231                         if (addr
.sin6
->sin6_scope_id 
== 0) { 
 232                                 // use the scope id that was embedded in the [link local] IPv6 address 
 233                                 addr
.sin6
->sin6_scope_id 
= if_index
; 
 237                 if (addr
.buf 
!= buf
) { 
 238                         CFAllocatorDeallocate(NULL
, addr
.buf
); 
 248 _SC_sendMachMessage(mach_port_t port
, mach_msg_id_t msg_id
) 
 250         mach_msg_empty_send_t   msg
; 
 251         mach_msg_option_t       options
; 
 252         kern_return_t           status
; 
 254         memset(&msg
, 0, sizeof(msg
)); 
 255         msg
.header
.msgh_bits 
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0); 
 256         msg
.header
.msgh_size 
= sizeof(msg
); 
 257         msg
.header
.msgh_remote_port 
= port
; 
 258         msg
.header
.msgh_local_port 
= MACH_PORT_NULL
; 
 259         msg
.header
.msgh_id 
= msg_id
; 
 260         options 
= MACH_SEND_TIMEOUT
; 
 261         status 
= mach_msg(&msg
.header
,                  /* msg */ 
 262                           MACH_SEND_MSG
|options
,        /* options */ 
 263                           msg
.header
.msgh_size
,         /* send_size */ 
 265                           MACH_PORT_NULL
,               /* rcv_name */ 
 267                           MACH_PORT_NULL
);              /* notify */ 
 268         if ((status 
== MACH_SEND_INVALID_DEST
) || (status 
== MACH_SEND_TIMED_OUT
)) { 
 269                 mach_msg_destroy(&msg
.header
); 
 277 _SC_trimDomain(CFStringRef domain
) 
 281         if (!isA_CFString(domain
)) { 
 285         // remove any leading/trailing dots 
 286         length 
= CFStringGetLength(domain
); 
 288             (CFStringFindWithOptions(domain
, 
 293              CFStringFindWithOptions(domain
, 
 295                                      CFRangeMake(0, length
), 
 296                                      kCFCompareAnchored
|kCFCompareBackwards
, 
 299              CFMutableStringRef trimmed
; 
 301              trimmed 
= CFStringCreateMutableCopy(NULL
, 0, domain
); 
 302              CFStringTrim(trimmed
, CFSTR(".")); 
 303              domain 
= (CFStringRef
)trimmed
; 
 304              length 
= CFStringGetLength(domain
); 
 319 _SC_hw_model(Boolean trim
) 
 321         static CFStringRef      model           
= NULL
; 
 322         static CFStringRef      model_trimmed   
= NULL
; 
 323         static dispatch_once_t  once
; 
 325         dispatch_once(&once
, ^{ 
 328                 int     mib
[]           = { CTL_HW
, HW_MODEL 
}; 
 329                 size_t  n               
= sizeof(hwModel
); 
 333                 memset(&hwModel
, 0, sizeof(hwModel
)); 
 334                 ret 
= sysctl(mib
, sizeof(mib
) / sizeof(mib
[0]), &hwModel
, &n
, NULL
, 0); 
 336                         SC_log(LOG_NOTICE
, "sysctl() CTL_HW/HW_MODEL failed: %s", strerror(errno
)); 
 339                 hwModel
[sizeof(hwModel
) - 1] = '\0'; 
 340                 model 
= CFStringCreateWithCString(NULL
, hwModel
, kCFStringEncodingASCII
); 
 342                 // and the "trimmed" name 
 343                 // ... remove everything after (and including) a comma 
 344                 // ... and then any trailing digits 
 345                 cp 
= index(hwModel
, ','); 
 349                 n 
= strlen(hwModel
) - 1; 
 351                         if (!isdigit(hwModel
[n
])) { 
 356                 model_trimmed 
= CFStringCreateWithCString(NULL
, hwModel
, kCFStringEncodingASCII
); 
 359         return trim 
? model_trimmed 
: model
; 
 364 #pragma mark Serialization 
 368 __CFDataCopyVMData(CFDataRef data
, void **dataRef
, CFIndex 
*dataLen
) 
 372         vm_address_t    vm_address
; 
 375         vm_address 
= (vm_address_t
)CFDataGetBytePtr(data
); 
 376         vm_size    
= (vm_size_t
)CFDataGetLength(data
); 
 377         kr 
= vm_allocate(mach_task_self(), &vm_address
, vm_size
, VM_FLAGS_ANYWHERE
); 
 378         if (kr 
!= KERN_SUCCESS
) { 
 384         memcpy((void *)vm_address
, (char *)CFDataGetBytePtr(data
), vm_size
); 
 385         *dataRef 
= (void *)vm_address
; 
 393 _SCSerialize(CFPropertyListRef obj
, CFDataRef 
*xml
, void **dataRef
, CFIndex 
*dataLen
) 
 397         if ((xml 
== NULL
) && ((dataRef 
== NULL
) || (dataLen 
== NULL
))) { 
 398                 /* if not keeping track of allocated space */ 
 402         myXml 
= CFPropertyListCreateData(NULL
, 
 404                                          kCFPropertyListBinaryFormat_v1_0
, 
 408                 SC_log(LOG_NOTICE
, "CFPropertyListCreateData() failed"); 
 412                 if ((dataRef 
!= NULL
) && (dataLen 
!= NULL
)) { 
 421                 if ((dataRef 
!= NULL
) && (dataLen 
!= NULL
)) { 
 422                         *dataRef 
= (void *)CFDataGetBytePtr(myXml
); 
 423                         *dataLen 
= CFDataGetLength(myXml
); 
 428                 kr 
= __CFDataCopyVMData(myXml
, dataRef
, dataLen
); 
 430                 if (kr 
!= KERN_SUCCESS
) { 
 431                         SC_log(LOG_NOTICE
, "__CFDataCreateVMData() failed: %s", mach_error_string(kr
)); 
 441 _SCUnserialize(CFPropertyListRef 
*obj
, CFDataRef xml
, void *dataRef
, CFIndex dataLen
) 
 443         CFErrorRef      error   
= NULL
; 
 446                 kern_return_t   status
; 
 448                 xml 
= CFDataCreateWithBytesNoCopy(NULL
, (void *)dataRef
, dataLen
, kCFAllocatorNull
); 
 449                 *obj 
= CFPropertyListCreateWithData(NULL
, xml
, kCFPropertyListImmutable
, NULL
, &error
); 
 452                 status 
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
); 
 453                 if (status 
!= KERN_SUCCESS
) { 
 454                         SC_log(LOG_NOTICE
, "vm_deallocate() failed: %s", mach_error_string(status
)); 
 455                         /* non-fatal???, proceed */ 
 458                 *obj 
= CFPropertyListCreateWithData(NULL
, xml
, kCFPropertyListImmutable
, NULL
, &error
); 
 463                         SC_log(LOG_NOTICE
, "CFPropertyListCreateWithData() failed: %@", error
); 
 466                 _SCErrorSet(kSCStatusFailed
); 
 475 _SCSerializeString(CFStringRef str
, CFDataRef 
*data
, void **dataRef
, CFIndex 
*dataLen
) 
 479         if (!isA_CFString(str
)) { 
 480                 /* if not a CFString */ 
 484         if ((data 
== NULL
) && ((dataRef 
== NULL
) || (dataLen 
== NULL
))) { 
 485                 /* if not keeping track of allocated space */ 
 489         myData 
= CFStringCreateExternalRepresentation(NULL
, str
, kCFStringEncodingUTF8
, 0); 
 490         if (myData 
== NULL
) { 
 491                 SC_log(LOG_NOTICE
, "CFStringCreateExternalRepresentation() failed"); 
 495                 if ((dataRef 
!= NULL
) && (dataLen 
!= NULL
)) { 
 504                 if ((dataRef 
!= NULL
) && (dataLen 
!= NULL
)) { 
 505                         *dataRef 
= (void *)CFDataGetBytePtr(myData
); 
 506                         *dataLen 
= CFDataGetLength(myData
); 
 511                 kr 
= __CFDataCopyVMData(myData
, dataRef
, dataLen
); 
 513                 if (kr 
!= KERN_SUCCESS
) { 
 514                         SC_log(LOG_NOTICE
, "__CFDataCreateVMData() failed: %s", mach_error_string(kr
)); 
 524 _SCUnserializeString(CFStringRef 
*str
, CFDataRef utf8
, void *dataRef
, CFIndex dataLen
) 
 527                 kern_return_t   status
; 
 529                 utf8 
= CFDataCreateWithBytesNoCopy(NULL
, dataRef
, dataLen
, kCFAllocatorNull
); 
 530                 *str 
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
); 
 533                 status 
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
); 
 534                 if (status 
!= KERN_SUCCESS
) { 
 535                         SC_log(LOG_NOTICE
, "vm_deallocate() failed: %s", mach_error_string(status
)); 
 536                         /* non-fatal???, proceed */ 
 539                 *str 
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
); 
 543                 SC_log(LOG_NOTICE
, "CFStringCreateFromExternalRepresentation() failed"); 
 552 _SCSerializeData(CFDataRef data
, void **dataRef
, CFIndex 
*dataLen
) 
 556         if (!isA_CFData(data
)) { 
 557                 /* if not a CFData */ 
 561         kr 
= __CFDataCopyVMData(data
, dataRef
, dataLen
); 
 562         if (kr 
!= KERN_SUCCESS
) { 
 563                 SC_log(LOG_NOTICE
, "__CFDataCreateVMData() failed: %s", mach_error_string(kr
)); 
 572 _SCUnserializeData(CFDataRef 
*data
, void *dataRef
, CFIndex dataLen
) 
 574         kern_return_t           status
; 
 576         *data 
= CFDataCreate(NULL
, dataRef
, dataLen
); 
 577         status 
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
); 
 578         if (status 
!= KERN_SUCCESS
) { 
 579                 SC_log(LOG_NOTICE
, "vm_deallocate() failed: %s", mach_error_string(status
)); 
 580                 _SCErrorSet(kSCStatusFailed
); 
 588 CF_RETURNS_RETAINED CFDictionaryRef
 
 589 _SCSerializeMultiple(CFDictionaryRef dict
) 
 592         const void *            keys_q
[N_QUICK
]; 
 593         const void **           keys            
= keys_q
; 
 595         CFDictionaryRef         newDict         
= NULL
; 
 596         const void *            pLists_q
[N_QUICK
]; 
 597         const void **           pLists          
= pLists_q
; 
 598         const void *            values_q
[N_QUICK
]; 
 599         const void **           values          
= values_q
; 
 601         nElements 
= CFDictionaryGetCount(dict
); 
 603                 if (nElements 
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) { 
 604                         keys   
= CFAllocatorAllocate(NULL
, nElements 
* sizeof(CFTypeRef
), 0); 
 605                         values 
= CFAllocatorAllocate(NULL
, nElements 
* sizeof(CFTypeRef
), 0); 
 606                         pLists 
= CFAllocatorAllocate(NULL
, nElements 
* sizeof(CFDataRef
), 0); 
 608                 memset(pLists
, 0, nElements 
* sizeof(CFDataRef
)); 
 610                 CFDictionaryGetKeysAndValues(dict
, keys
, values
); 
 611                 for (i 
= 0; i 
< nElements
; i
++) { 
 613                         if (!_SCSerialize((CFPropertyListRef
)values
[i
], (CFDataRef 
*)&pLists
[i
], NULL
, NULL
)) { 
 619         newDict 
= CFDictionaryCreate(NULL
, 
 623                                      &kCFTypeDictionaryKeyCallBacks
, 
 624                                      &kCFTypeDictionaryValueCallBacks
); 
 629                 for (i 
= 0; i 
< nElements
; i
++) { 
 630                         if (pLists
[i
] != NULL
)  CFRelease((CFDataRef
)pLists
[i
]); 
 633                 if (keys 
!= keys_q
) { 
 634                         CFAllocatorDeallocate(NULL
, keys
); 
 635                         CFAllocatorDeallocate(NULL
, values
); 
 636                         CFAllocatorDeallocate(NULL
, pLists
); 
 646 _SCUnserializeMultiple(CFDictionaryRef dict
) 
 648         const void *            keys_q
[N_QUICK
]; 
 649         const void **           keys            
= keys_q
; 
 651         CFDictionaryRef         newDict         
= NULL
; 
 652         const void *            pLists_q
[N_QUICK
]; 
 653         const void **           pLists          
= pLists_q
; 
 654         const void *            values_q
[N_QUICK
]; 
 655         const void **           values          
= values_q
; 
 657         nElements 
= CFDictionaryGetCount(dict
); 
 661                 if (nElements 
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) { 
 662                         keys   
= CFAllocatorAllocate(NULL
, nElements 
* sizeof(CFTypeRef
), 0); 
 663                         values 
= CFAllocatorAllocate(NULL
, nElements 
* sizeof(CFTypeRef
), 0); 
 664                         pLists 
= CFAllocatorAllocate(NULL
, nElements 
* sizeof(CFTypeRef
), 0); 
 666                 memset(pLists
, 0, nElements 
* sizeof(CFTypeRef
)); 
 668                 CFDictionaryGetKeysAndValues(dict
, keys
, values
); 
 669                 for (i 
= 0; i 
< nElements
; i
++) { 
 670                         if (!_SCUnserialize((CFPropertyListRef 
*)&pLists
[i
], values
[i
], NULL
, 0)) { 
 676         newDict 
= CFDictionaryCreate(NULL
, 
 680                                      &kCFTypeDictionaryKeyCallBacks
, 
 681                                      &kCFTypeDictionaryValueCallBacks
); 
 688                 for (i 
= 0; i 
< nElements
; i
++) { 
 689                         if (pLists
[i
])  CFRelease(pLists
[i
]); 
 692                 if (keys 
!= keys_q
) { 
 693                         CFAllocatorDeallocate(NULL
, keys
); 
 694                         CFAllocatorDeallocate(NULL
, values
); 
 695                         CFAllocatorDeallocate(NULL
, pLists
); 
 707 _SCCreatePropertyListFromResource(CFURLRef url
) 
 709         CFDictionaryRef dict            
= NULL
; 
 712         CFReadStreamRef readStream
; 
 713         CFNumberRef     val             
= NULL
; 
 715         if (!CFURLCopyResourcePropertyForKey(url
, kCFURLFileSizeKey
, &val
, NULL
) || 
 717                 // if size not available 
 718                 SC_log(LOG_NOTICE
, "CFURLCopyResourcePropertyForKey() size not available: %@", url
); 
 722         ok 
= CFNumberGetValue(val
, kCFNumberSInt64Type
, &fileLen
); 
 724         if (!ok 
|| (fileLen 
== 0)) { 
 725                 // if empty or size too large 
 726                 SC_log(LOG_INFO
, "_SCCreatePropertyListFromResource() improper size: %@", url
); 
 730         readStream 
= CFReadStreamCreateWithFile(NULL
, url
); 
 731         if (readStream 
!= NULL
) { 
 732                 if (CFReadStreamOpen(readStream
)) { 
 736                         buffer 
= CFAllocatorAllocate(NULL
, (CFIndex
)fileLen
, 0); 
 737                         dataLen 
= CFReadStreamRead(readStream
, buffer
, (CFIndex
)fileLen
); 
 738                         if (dataLen 
== (CFIndex
)fileLen
) { 
 741                                 data 
= CFDataCreateWithBytesNoCopy(NULL
, buffer
, (CFIndex
)fileLen
, kCFAllocatorNull
); 
 743                                         dict 
= CFPropertyListCreateWithData(NULL
, 
 745                                                                             kCFPropertyListImmutable
, 
 751                         CFAllocatorDeallocate(NULL
, buffer
); 
 752                         CFReadStreamClose(readStream
); 
 754                 CFRelease(readStream
); 
 762 #pragma mark CFRunLoop scheduling 
 765 __private_extern__ 
void 
 766 _SC_signalRunLoop(CFTypeRef obj
, CFRunLoopSourceRef rls
, CFArrayRef rlList
) 
 768         CFRunLoopRef    rl      
= NULL
; 
 769         CFRunLoopRef    rl1     
= NULL
; 
 771         CFIndex         n       
= CFArrayGetCount(rlList
); 
 777         /* get first runLoop for this object */ 
 778         for (i 
= 0; i 
< n
; i 
+= 3) { 
 779                 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) { 
 783                 rl1 
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1); 
 788                 /* if not scheduled */ 
 792         /* check if we have another runLoop for this object */ 
 794         for (i 
= i
+3; i 
< n
; i 
+= 3) { 
 797                 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) { 
 801                 rl2 
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1); 
 802                 if (!CFEqual(rl1
, rl2
)) { 
 803                         /* we've got more than one runLoop */ 
 810                 /* if we only have one runLoop */ 
 815         /* more than one different runLoop, so we must pick one */ 
 816         for (i 
= 0; i 
< n
; i
+=3) { 
 819                 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) { 
 823                 rl     
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1); 
 824                 rlMode 
= CFRunLoopCopyCurrentMode(rl
); 
 825                 if (rlMode 
!= NULL
) { 
 828                         waiting 
= (CFRunLoopIsWaiting(rl
) && CFRunLoopContainsSource(rl
, rls
, rlMode
)); 
 831                                 /* we've found a runLoop that's "ready" */ 
 838         /* didn't choose one above, so choose first */ 
 839         CFRunLoopWakeUp(rl1
); 
 844 __private_extern__ Boolean
 
 845 _SC_isScheduled(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
) 
 848         CFIndex n       
= CFArrayGetCount(rlList
); 
 850         for (i 
= 0; i 
< n
; i 
+= 3) { 
 851                 if ((obj 
!= NULL
)         && !CFEqual(obj
,         CFArrayGetValueAtIndex(rlList
, i
))) { 
 854                 if ((runLoop 
!= NULL
)     && !CFEqual(runLoop
,     CFArrayGetValueAtIndex(rlList
, i
+1))) { 
 857                 if ((runLoopMode 
!= NULL
) && !CFEqual(runLoopMode
, CFArrayGetValueAtIndex(rlList
, i
+2))) { 
 867 __private_extern__ 
void 
 868 _SC_schedule(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
) 
 870         CFArrayAppendValue(rlList
, obj
); 
 871         CFArrayAppendValue(rlList
, runLoop
); 
 872         CFArrayAppendValue(rlList
, runLoopMode
); 
 878 __private_extern__ Boolean
 
 879 _SC_unschedule(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
, Boolean all
) 
 882         Boolean found   
= FALSE
; 
 883         CFIndex n       
= CFArrayGetCount(rlList
); 
 886                 if ((obj 
!= NULL
)         && !CFEqual(obj
,         CFArrayGetValueAtIndex(rlList
, i
))) { 
 890                 if ((runLoop 
!= NULL
)     && !CFEqual(runLoop
,     CFArrayGetValueAtIndex(rlList
, i
+1))) { 
 894                 if ((runLoopMode 
!= NULL
) && !CFEqual(runLoopMode
, CFArrayGetValueAtIndex(rlList
, i
+2))) { 
 901                 CFArrayRemoveValueAtIndex(rlList
, i 
+ 2); 
 902                 CFArrayRemoveValueAtIndex(rlList
, i 
+ 1); 
 903                 CFArrayRemoveValueAtIndex(rlList
, i
); 
 920 #define SYSTEMCONFIGURATION_BUNDLE_ID           CFSTR("com.apple.SystemConfiguration") 
 921 #define SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN  (sizeof(SYSTEMCONFIGURATION_FRAMEWORK_PATH) - 1) 
 923 #define SUFFIX_SYM                              "~sym" 
 924 #define SUFFIX_SYM_LEN                          (sizeof(SUFFIX_SYM) - 1) 
 926 #define SUFFIX_DST                              "~dst" 
 930 _SC_CFBundleGet(void) 
 932         static CFBundleRef      bundle  
= NULL
; 
 937         if (bundle 
!= NULL
) { 
 941         bundle 
= CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID
); 
 942         if (bundle 
!= NULL
) { 
 943                 CFRetain(bundle
);       // we want to hold a reference to the bundle 
 946                 SC_log(LOG_NOTICE
, "could not get CFBundle for \"%@\". Trying harder...", 
 947                        SYSTEMCONFIGURATION_BUNDLE_ID
); 
 950         // if appropriate (e.g. when debugging), try a bit harder 
 952         env 
= getenv("DYLD_FRAMEWORK_PATH"); 
 953         len 
= (env 
!= NULL
) ? strlen(env
) : 0; 
 955         if (len 
> 0) {  /* We are debugging */ 
 957                 // trim any trailing slashes 
 959                         if (env
[len 
- 1] != '/') { 
 965                 // if DYLD_FRAMEWORK_PATH is ".../xxx~sym" than try ".../xxx~dst" 
 966                 if ((len 
> SUFFIX_SYM_LEN
) && 
 967                     (strncmp(&env
[len 
- SUFFIX_SYM_LEN
], SUFFIX_SYM
, SUFFIX_SYM_LEN
) == 0) && 
 968                     ((len 
+ SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN
) < MAXPATHLEN
)) { 
 969                         char            path
[MAXPATHLEN
]; 
 971                         strlcpy(path
, env
, sizeof(path
)); 
 972                         strlcpy(&path
[len 
- SUFFIX_SYM_LEN
], SUFFIX_DST
, sizeof(path
) - (len 
- SUFFIX_SYM_LEN
)); 
 973                         strlcat(&path
[len
], SYSTEMCONFIGURATION_FRAMEWORK_PATH
, sizeof(path
) - len
); 
 975                         url 
= CFURLCreateFromFileSystemRepresentation(NULL
, 
 977                                                                       len 
+ SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN
, 
 979                         bundle 
= CFBundleCreate(NULL
, url
); 
 984         if (bundle 
== NULL
) { /* Try a more "direct" route to get the bundle */ 
 986                 url 
= CFURLCreateWithFileSystemPath(NULL
, 
 987                                                     CFSTR(SYSTEMCONFIGURATION_FRAMEWORK_PATH
), 
 988                                                     kCFURLPOSIXPathStyle
, 
 991                 bundle 
= CFBundleCreate(NULL
, url
); 
 995         if (bundle 
== NULL
) { 
 996                 SC_log(LOG_ERR
, "could not get CFBundle for \"%@\"", SYSTEMCONFIGURATION_BUNDLE_ID
); 
1007  *      <key>bundleID-tableName</key> 
1009  *        ... property list from non-localized bundle URL 
1013 static CFMutableDictionaryRef   cachedInfo      
= NULL
; 
1016 static dispatch_queue_t
 
1017 _SC_CFBundleCachedInfoQueue() 
1019         static dispatch_once_t  once
; 
1020         static dispatch_queue_t q
; 
1022         dispatch_once(&once
, ^{ 
1023                 q 
= dispatch_queue_create("_SC_CFBundleCachedInfo", NULL
); 
1031 _SC_CFBundleCachedInfoCopyTableKey(CFBundleRef bundle
, CFStringRef tableName
) 
1033         CFStringRef     bundleID
; 
1034         CFStringRef     tableKey
; 
1036         bundleID 
= CFBundleGetIdentifier(bundle
); 
1037         tableKey 
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@: %@"), bundleID
, tableName
); 
1042 static CFDictionaryRef
 
1043 _SC_CFBundleCachedInfoCopyTable(CFBundleRef bundle
, CFStringRef tableName
) 
1045         __block CFDictionaryRef         dict    
= NULL
; 
1047         dispatch_sync(_SC_CFBundleCachedInfoQueue(), ^{ 
1048                 if (cachedInfo 
!= NULL
) { 
1049                         CFStringRef     tableKey
; 
1051                         tableKey 
= _SC_CFBundleCachedInfoCopyTableKey(bundle
, tableName
); 
1052                         dict 
= CFDictionaryGetValue(cachedInfo
, tableKey
); 
1056                         CFRelease(tableKey
); 
1065 _SC_CFBundleCachedInfoSaveTable(CFBundleRef bundle
, CFStringRef tableName
, CFDictionaryRef table
) 
1068         dispatch_sync(_SC_CFBundleCachedInfoQueue(), ^{ 
1069                 CFStringRef     tableKey
; 
1071                 tableKey 
= _SC_CFBundleCachedInfoCopyTableKey(bundle
, tableName
); 
1072                 SC_log(LOG_DEBUG
, "Caching %@", tableKey
); 
1074                 if (cachedInfo 
== NULL
) { 
1075                         cachedInfo 
= CFDictionaryCreateMutable(NULL
, 
1077                                                                &kCFTypeDictionaryKeyCallBacks
, 
1078                                                                &kCFTypeDictionaryValueCallBacks
); 
1080                 CFDictionarySetValue(cachedInfo
, tableKey
, table
); 
1081                 CFRelease(tableKey
); 
1089 _SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle
, CFStringRef key
, CFStringRef value
, CFStringRef tableName
) 
1091         CFStringRef     str     
= NULL
; 
1092         CFDictionaryRef table   
= NULL
; 
1095         if ((tableName 
== NULL
) || CFEqual(tableName
, CFSTR(""))) { 
1096                 tableName 
= CFSTR("Localizable"); 
1099         table 
= _SC_CFBundleCachedInfoCopyTable(bundle
, tableName
); 
1100         if (table 
== NULL
) { 
1101                 url 
= CFBundleCopyResourceURLForLocalization(bundle
, 
1107                         table 
= _SCCreatePropertyListFromResource(url
); 
1109                         if (table 
!= NULL
) { 
1110                                 _SC_CFBundleCachedInfoSaveTable(bundle
, tableName
, table
); 
1113                         SC_log(LOG_ERR
, "failed to get resource url: {bundle:%@, table: %@}", bundle
, tableName
); 
1117         if (table 
!= NULL
) { 
1118                 if (isA_CFDictionary(table
)) { 
1119                         str 
= CFDictionaryGetValue(table
, key
); 
1129                 str 
= CFRetain(value
); 
1137 #pragma mark Mach port / CFMachPort management 
1141 _SC_CFMachPortCreateWithPort(const char         *portDescription
, 
1142                              mach_port_t        portNum
, 
1143                              CFMachPortCallBack callout
, 
1144                              CFMachPortContext  
*context
) 
1147         Boolean         shouldFree      
= FALSE
; 
1149         port 
= CFMachPortCreateWithPort(NULL
, portNum
, callout
, context
, &shouldFree
); 
1150         if ((port 
== NULL
) || shouldFree
) { 
1154                 SC_log(LOG_NOTICE
, "%s: CFMachPortCreateWithPort() failed , port = %p", 
1156                        (void *)(uintptr_t)portNum
); 
1158                         err 
= CFStringCreateWithFormat(NULL
, NULL
, 
1159                                                        CFSTR("%s: CFMachPortCreateWithPort recycled, [old] port = %@"), 
1160                                                        portDescription
, port
); 
1162                         err 
= CFStringCreateWithFormat(NULL
, NULL
, 
1163                                                        CFSTR("%s: CFMachPortCreateWithPort returned NULL"), 
1166                 crash_info 
= _SC_cfstring_to_cstring(err
, NULL
, 0, kCFStringEncodingASCII
); 
1169                 err 
= CFStringCreateWithFormat(NULL
, 
1171                                                CFSTR("A recycled mach_port has been detected by \"%s\"."), 
1173                 _SC_crash(crash_info
, CFSTR("CFMachPort error"), err
); 
1174                 CFAllocatorDeallocate(NULL
, crash_info
); 
1183 #pragma mark DOS encoding/codepage 
1186 #if     !TARGET_OS_IPHONE 
1188 _SC_dos_encoding_and_codepage(CFStringEncoding  macEncoding
, 
1190                               CFStringEncoding  
*dosEncoding
, 
1191                               UInt32            
*dosCodepage
) 
1193         switch (macEncoding
) { 
1194         case kCFStringEncodingMacRoman
: 
1195                 if (macRegion 
!= 0) /* anything non-zero is not US */ 
1196                 *dosEncoding 
= kCFStringEncodingDOSLatin1
; 
1197                 else /* US region */ 
1198                 *dosEncoding 
= kCFStringEncodingDOSLatinUS
; 
1201         case kCFStringEncodingMacJapanese
: 
1202                 *dosEncoding 
= kCFStringEncodingDOSJapanese
; 
1205         case kCFStringEncodingMacChineseTrad
: 
1206                 *dosEncoding 
= kCFStringEncodingDOSChineseTrad
; 
1209         case kCFStringEncodingMacKorean
: 
1210                 *dosEncoding 
= kCFStringEncodingDOSKorean
; 
1213         case kCFStringEncodingMacArabic
: 
1214                 *dosEncoding 
= kCFStringEncodingDOSArabic
; 
1217         case kCFStringEncodingMacHebrew
: 
1218                 *dosEncoding 
= kCFStringEncodingDOSHebrew
; 
1221         case kCFStringEncodingMacGreek
: 
1222                 *dosEncoding 
= kCFStringEncodingDOSGreek
; 
1225         case kCFStringEncodingMacCyrillic
: 
1226                 *dosEncoding 
= kCFStringEncodingDOSCyrillic
; 
1229         case kCFStringEncodingMacThai
: 
1230                 *dosEncoding 
= kCFStringEncodingDOSThai
; 
1233         case kCFStringEncodingMacChineseSimp
: 
1234                 *dosEncoding 
= kCFStringEncodingDOSChineseSimplif
; 
1237         case kCFStringEncodingMacCentralEurRoman
: 
1238                 *dosEncoding 
= kCFStringEncodingDOSLatin2
; 
1241         case kCFStringEncodingMacTurkish
: 
1242                 *dosEncoding 
= kCFStringEncodingDOSTurkish
; 
1245         case kCFStringEncodingMacCroatian
: 
1246                 *dosEncoding 
= kCFStringEncodingDOSLatin2
; 
1249         case kCFStringEncodingMacIcelandic
: 
1250                 *dosEncoding 
= kCFStringEncodingDOSIcelandic
; 
1253         case kCFStringEncodingMacRomanian
: 
1254                 *dosEncoding 
= kCFStringEncodingDOSLatin2
; 
1257         case kCFStringEncodingMacFarsi
: 
1258                 *dosEncoding 
= kCFStringEncodingDOSArabic
; 
1261         case kCFStringEncodingMacUkrainian
: 
1262                 *dosEncoding 
= kCFStringEncodingDOSCyrillic
; 
1266                 *dosEncoding 
= kCFStringEncodingDOSLatin1
; 
1270         *dosCodepage 
= CFStringConvertEncodingToWindowsCodepage(*dosEncoding
); 
1273 #endif  // !TARGET_OS_IPHONE 
1277 #pragma mark Debugging 
1281  * print status of in-use mach ports 
1284 _SC_logMachPortStatus(void) 
1286         kern_return_t           status
; 
1287         mach_port_name_array_t  ports
; 
1288         mach_port_type_array_t  types
; 
1289         mach_msg_type_number_t  pi
, pn
, tn
; 
1290         CFMutableStringRef      str
; 
1292         SC_log(LOG_DEBUG
, "----------"); 
1294         /* report on ALL mach ports associated with this task */ 
1295         status 
= mach_port_names(mach_task_self(), &ports
, &pn
, &types
, &tn
); 
1296         if (status 
== MACH_MSG_SUCCESS
) { 
1297                 str 
= CFStringCreateMutable(NULL
, 0); 
1298                 for (pi 
= 0; pi 
< pn
; pi
++) { 
1299                         char    rights
[16], *rp 
= &rights
[0]; 
1301                         if (types
[pi
] != MACH_PORT_TYPE_NONE
) { 
1304                                 if (types
[pi
] & MACH_PORT_TYPE_SEND
) 
1306                                 if (types
[pi
] & MACH_PORT_TYPE_RECEIVE
) 
1308                                 if (types
[pi
] & MACH_PORT_TYPE_SEND_ONCE
) 
1310                                 if (types
[pi
] & MACH_PORT_TYPE_PORT_SET
) 
1312                                 if (types
[pi
] & MACH_PORT_TYPE_DEAD_NAME
) 
1317                         CFStringAppendFormat(str
, NULL
, CFSTR(" %d%s"), ports
[pi
], rights
); 
1319                 SC_log(LOG_DEBUG
, "Task ports (n=%d):%@", pn
, str
); 
1329 _SC_getMachPortReferences(mach_port_t           port
, 
1330                           mach_port_type_t      
*pt
, 
1331                           mach_port_urefs_t     
*refs_send
, 
1332                           mach_port_urefs_t     
*refs_recv
, 
1333                           mach_port_status_t    
*recv_status
, 
1334                           mach_port_urefs_t     
*refs_once
, 
1335                           mach_port_urefs_t     
*refs_pset
, 
1336                           mach_port_urefs_t     
*refs_dead
, 
1337                           const char            *err_prefix
) 
1339         kern_return_t           status
; 
1341         status 
= mach_port_type(mach_task_self(), port
, pt
); 
1342         if (status 
!= KERN_SUCCESS
) { 
1343                 SC_log(LOG_DEBUG
, "%smach_port_type(..., 0x%x): %s", 
1346                        mach_error_string(status
)); 
1350         if ((refs_send 
!= NULL
) && ((*pt 
& MACH_PORT_TYPE_SEND
) != 0)) { 
1351                 status 
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND
, refs_send
); 
1352                 if (status 
!= KERN_SUCCESS
) { 
1353                         SC_log(LOG_DEBUG
, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND): %s", 
1356                                mach_error_string(status
)); 
1361         if ((refs_recv 
!= NULL
) && (recv_status 
!= NULL
) && ((*pt 
& MACH_PORT_TYPE_RECEIVE
) != 0)) { 
1362                 mach_msg_type_number_t  count
; 
1364                 status 
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_RECEIVE
, refs_recv
); 
1365                 if (status 
!= KERN_SUCCESS
) { 
1366                         SC_log(LOG_DEBUG
, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_RECEIVE): %s", 
1369                                mach_error_string(status
)); 
1373                 count 
= MACH_PORT_RECEIVE_STATUS_COUNT
; 
1374                 status 
= mach_port_get_attributes(mach_task_self(), 
1376                                                   MACH_PORT_RECEIVE_STATUS
, 
1377                                                   (mach_port_info_t
)recv_status
, 
1379                 if (status 
!= KERN_SUCCESS
) { 
1380                         SC_log(LOG_DEBUG
, "%smach_port_get_attributes(..., 0x%x, MACH_PORT_RECEIVE_STATUS): %s", 
1383                                mach_error_string(status
)); 
1388         if ((refs_once 
!= NULL
) && ((*pt 
& MACH_PORT_TYPE_SEND_ONCE
) != 0)) { 
1389                 status 
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND_ONCE
, refs_once
); 
1390                 if (status 
!= KERN_SUCCESS
) { 
1391                         SC_log(LOG_DEBUG
, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND_ONCE): %s", 
1394                                mach_error_string(status
)); 
1399         if ((refs_pset 
!= NULL
) && ((*pt 
& MACH_PORT_TYPE_PORT_SET
) != 0)) { 
1400                 status 
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_PORT_SET
, refs_pset
); 
1401                 if (status 
!= KERN_SUCCESS
) { 
1402                         SC_log(LOG_DEBUG
, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_PORT_SET): %s", 
1405                                mach_error_string(status
)); 
1410         if ((refs_dead 
!= NULL
) && ((*pt 
& MACH_PORT_TYPE_DEAD_NAME
) != 0)) { 
1411                 status 
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_DEAD_NAME
, refs_dead
); 
1412                 if (status 
!= KERN_SUCCESS
) { 
1413                         SC_log(LOG_DEBUG
, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_DEAD_NAME): %s", 
1416                                mach_error_string(status
)); 
1421         return KERN_SUCCESS
; 
1426 _SC_logMachPortReferences(const char *str
, mach_port_t port
) 
1428         const char              *blanks         
= "                                                            "; 
1430         mach_port_type_t        pt
; 
1431         mach_port_status_t      recv_status     
= { .mps_nsrequest 
= 0, }; 
1432         mach_port_urefs_t       refs_send       
= 0; 
1433         mach_port_urefs_t       refs_recv       
= 0; 
1434         mach_port_urefs_t       refs_once       
= 0; 
1435         mach_port_urefs_t       refs_pset       
= 0; 
1436         mach_port_urefs_t       refs_dead       
= 0; 
1437         kern_return_t           status
; 
1441                 static int      is_configd      
= -1; 
1443                 if (is_configd 
== -1) { 
1444                         is_configd 
= (strcmp(getprogname(), _SC_SERVER_PROG
) == 0); 
1446                 if (is_configd 
== 1) { 
1447                         // if "configd", add indication if this is the M[ain] or [P]lugin thread 
1449                                 (CFRunLoopGetMain() == CFRunLoopGetCurrent()) ? "M " : "P ", 
1453                 // add provided string 
1454                 strlcat(buf
, str
, sizeof(buf
)); 
1457                 strlcat(buf
, blanks
, sizeof(buf
)); 
1458                 if (strcmp(&buf
[sizeof(buf
) - 3], "  ") == 0) { 
1459                         buf
[sizeof(buf
) - 3] = ':'; 
1463         status 
= _SC_getMachPortReferences(port
, 
1472         if (status 
!= KERN_SUCCESS
) { 
1476         SC_log(LOG_DEBUG
, "%smach port 0x%x (%d): send=%d, receive=%d, send once=%d, port set=%d, dead name=%d%s%s", 
1485                recv_status
.mps_nsrequest 
? ", no more senders"   : "", 
1486                ((pt 
& MACH_PORT_TYPE_DEAD_NAME
) != 0) ? ", dead name request" : ""); 
1498         CFMutableStringRef      trace
; 
1500         n 
= backtrace(stack
, sizeof(stack
)/sizeof(stack
[0])); 
1502                 SC_log(LOG_NOTICE
, "backtrace() failed: %s", strerror(errno
)); 
1506         trace 
= CFStringCreateMutable(NULL
, 0); 
1508         symbols 
= backtrace_symbols(stack
, n
); 
1509         if (symbols 
!= NULL
) { 
1512                 for (i 
= 0; i 
< n
; i
++) { 
1513                         CFStringAppendFormat(trace
, NULL
, CFSTR("%s\n"), symbols
[i
]); 
1524 _SC_ReportCrash(CFStringRef notifyHeader
, CFStringRef notifyMessage
) 
1526 #if     !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 
1527 #pragma unused(notifyHeader) 
1528 #pragma unused(notifyMessage) 
1529 #endif  // !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 
1530         static Boolean  warned  
= FALSE
; 
1533 #if     TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 
1534                 CFStringRef     displayMessage
; 
1536                 displayMessage 
= CFStringCreateWithFormat(NULL
, 
1538                                                           CFSTR("%@\n\nPlease collect the crash report and file a Radar."), 
1540                 CFUserNotificationDisplayNotice(0, 
1541                                                 kCFUserNotificationStopAlertLevel
, 
1548                 CFRelease(displayMessage
); 
1549 #endif  // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 
1558 _SC_crash(const char *crash_info
, CFStringRef notifyHeader
, CFStringRef notifyMessage
) 
1560         if (_SC_isAppleInternal()) { 
1561                 if (crash_info 
!= NULL
) { 
1562                         CRSetCrashLogMessage(crash_info
); 
1563                         SC_log(LOG_NOTICE
, "%s", crash_info
); 
1566                 // simulate a crash report 
1567                 os_log_with_type(SC_LOG_HANDLE(), OS_LOG_TYPE_FAULT
, "%s", crash_info
); 
1569                 // report the crash to the user 
1570                 if ((notifyHeader 
!= NULL
) && (notifyMessage 
!= NULL
)) { 
1571                         _SC_ReportCrash(notifyHeader
, notifyMessage
); 
1574                 if (crash_info 
!= NULL
) { 
1575                         CRSetCrashLogMessage(NULL
); 
1584 _SC_getconninfo(int socket
, struct sockaddr_storage 
*src_addr
, struct sockaddr_storage 
*dest_addr
, int *if_index
, uint32_t *flags
) 
1586         struct so_cinforeq      request
; 
1588         memset(&request
, 0, sizeof(request
)); 
1590         if (src_addr 
!= NULL
) { 
1591                 memset(src_addr
, 0, sizeof(*src_addr
)); 
1592                 request
.scir_src 
= (struct sockaddr 
*)src_addr
; 
1593                 request
.scir_src_len 
= sizeof(*src_addr
); 
1596         if (dest_addr 
!= NULL
) { 
1597                 memset(dest_addr
, 0, sizeof(*dest_addr
)); 
1598                 request
.scir_dst 
= (struct sockaddr 
*)dest_addr
; 
1599                 request
.scir_dst_len 
= sizeof(*dest_addr
); 
1602         if (ioctl(socket
, SIOCGCONNINFO
, &request
) != 0) { 
1603                 SC_log(LOG_NOTICE
, "SIOCGCONNINFO failed: %s", strerror(errno
)); 
1607         if (if_index 
!= NULL
) { 
1609                 *if_index 
= request
.scir_ifindex
; 
1612         if (flags 
!= NULL
) { 
1614                 *flags 
= request
.scir_flags
;