2 * Copyright (c) 2006, 2011 Apple Computer, 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 * SCNetworkSignature.c
26 * - implementation of SCNetworkSignatureRef API that allows access to
27 network identification information
31 * Modification History
33 * November 6, 2006 Dieter Siegmund (dieter@apple.com)
38 #include <netinet/in.h>
39 #include <CoreFoundation/CFDictionary.h>
40 #include <CoreFoundation/CFString.h>
41 #include <CoreFoundation/CFArray.h>
42 #include <CoreFoundation/CFRuntime.h>
43 #include <SystemConfiguration/SCDynamicStore.h>
44 #include <SystemConfiguration/SCValidation.h>
45 #include <SystemConfiguration/SCPrivate.h>
46 #include "SCNetworkSignature.h"
47 #include "SCNetworkSignaturePrivate.h"
48 #include <arpa/inet.h>
50 const char * kSCNetworkSignatureActiveChangedNotifyName
= NETWORK_ID_KEY
".active";
53 #pragma mark SCNetworkSignature support routines
55 static __inline__ SCDynamicStoreRef
56 store_create(CFAllocatorRef alloc
)
58 return (SCDynamicStoreCreate(alloc
, CFSTR("SCNetworkSignature"),
62 static CFDictionaryRef
63 store_copy_id_dict(CFAllocatorRef alloc
, SCDynamicStoreRef store
)
65 CFDictionaryRef id_dict
= NULL
;
66 Boolean release_store
= FALSE
;
69 store
= store_create(alloc
);
75 id_dict
= SCDynamicStoreCopyValue(store
,
76 kSCNetworkIdentificationStoreKey
);
77 if (isA_CFDictionary(id_dict
) == NULL
) {
78 if (id_dict
!= NULL
) {
93 #pragma mark SCNetworkSignature APIs
96 SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc
,
97 const struct sockaddr
* addr
)
99 CFDictionaryRef id_dict
= NULL
;
100 CFStringRef ident
= NULL
;
101 struct sockaddr_in
* sin_p
;
104 /* only accept 0.0.0.0 (i.e. default) for now */
105 sin_p
= (struct sockaddr_in
*)addr
;
107 || addr
->sa_family
!= AF_INET
108 || addr
->sa_len
!= sizeof(struct sockaddr_in
)
109 || sin_p
->sin_addr
.s_addr
!= 0) {
110 _SCErrorSet(kSCStatusInvalidArgument
);
113 id_dict
= store_copy_id_dict(alloc
, NULL
);
114 if (id_dict
== NULL
) {
115 _SCErrorSet(kSCStatusFailed
);
118 ident
= CFDictionaryGetValue(id_dict
, kStoreKeyPrimaryIPv4Identifier
);
119 if (isA_CFString(ident
) != NULL
) {
123 _SCErrorSet(kSCStatusFailed
);
126 if (id_dict
!= NULL
) {
132 CFArrayRef
/* of CFStringRef's */
133 SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc
)
135 CFArrayRef active
= NULL
;
138 CFDictionaryRef id_dict
= NULL
;
140 id_dict
= store_copy_id_dict(alloc
, NULL
);
141 if (id_dict
== NULL
) {
144 active
= CFDictionaryGetValue(id_dict
, kStoreKeyActiveIdentifiers
);
145 if (isA_CFArray(active
) != NULL
) {
146 count
= CFArrayGetCount(active
);
152 for (i
= 0; i
< count
; i
++) {
153 CFStringRef ident
= CFArrayGetValueAtIndex(active
, i
);
155 if (isA_CFString(ident
) == NULL
) {
163 if (id_dict
!= NULL
) {
166 if (active
== NULL
) {
167 _SCErrorSet(kSCStatusFailed
);
172 static CFDictionaryRef
173 copy_services_for_address_family(CFAllocatorRef alloc
,
174 SCDynamicStoreRef store
, int af
)
176 CFDictionaryRef info
;
180 Boolean release_store
= FALSE
;
183 store
= store_create(alloc
);
187 release_store
= TRUE
;
189 prop
= (af
== AF_INET
) ? kSCEntNetIPv4
: kSCEntNetIPv6
;
190 pattern
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
191 kSCDynamicStoreDomainState
,
194 patterns
= CFArrayCreate(NULL
,
195 (const void * *)&pattern
, 1,
196 &kCFTypeArrayCallBacks
);
198 info
= SCDynamicStoreCopyMultiple(store
, NULL
, patterns
);
207 my_IPAddressToCFString(int af
, const void * src_p
)
209 char ntopbuf
[INET6_ADDRSTRLEN
];
211 if (inet_ntop(af
, src_p
, ntopbuf
, sizeof(ntopbuf
)) != NULL
) {
212 return (CFStringCreateWithCString(NULL
, ntopbuf
,
213 kCFStringEncodingASCII
));
219 SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc
,
222 CFStringRef addresses_key
;
226 const void * * keys
= NULL
;
227 #define KEYS_STATIC_COUNT 10
228 const void * keys_static
[KEYS_STATIC_COUNT
];
229 static const void * local_ip_p
;
230 CFStringRef local_ip_str
= NULL
;
231 CFStringRef ret_signature
= NULL
;
232 CFDictionaryRef service_info
= NULL
;
234 struct sockaddr_in inet
;
235 struct sockaddr_in6 inet6
;
238 socklen_t ss_len
= sizeof(ss
);
239 int status
= kSCStatusFailed
;
241 if (getsockname(sock_fd
, &ss
.sa
, &ss_len
) != 0) {
242 status
= kSCStatusInvalidArgument
;
245 af
= ss
.inet
.sin_family
;
248 addresses_key
= kSCPropNetIPv4Addresses
;
249 local_ip_p
= &ss
.inet
.sin_addr
;
252 addresses_key
= kSCPropNetIPv6Addresses
;
253 local_ip_p
= &ss
.inet6
.sin6_addr
;
256 status
= kSCStatusInvalidArgument
;
260 /* find a service matching the local IP and get its network signature */
261 service_info
= copy_services_for_address_family(alloc
, NULL
, af
);
262 if (service_info
== NULL
) {
265 local_ip_str
= my_IPAddressToCFString(af
, local_ip_p
);
266 if (local_ip_str
== NULL
) {
269 count
= CFDictionaryGetCount(service_info
);
270 if (count
> KEYS_STATIC_COUNT
) {
271 keys
= (const void * *)malloc(sizeof(*keys
) * count
);
276 CFDictionaryGetKeysAndValues(service_info
, keys
, NULL
);
277 for (i
= 0; i
< count
; i
++) {
280 CFStringRef signature
;
281 CFDictionaryRef value
;
283 value
= CFDictionaryGetValue(service_info
, keys
[i
]);
284 if (isA_CFDictionary(value
) == NULL
) {
287 signature
= CFDictionaryGetValue(value
,
288 kStoreKeyNetworkSignature
);
289 if (isA_CFString(signature
) == NULL
) {
293 addrs
= CFDictionaryGetValue(value
, addresses_key
);
294 if (isA_CFArray(addrs
) == NULL
) {
297 range
= CFRangeMake(0, CFArrayGetCount(addrs
));
298 if (CFArrayContainsValue(addrs
, range
, local_ip_str
)) {
299 ret_signature
= CFRetain(signature
);
300 status
= kSCStatusOK
;
306 if (local_ip_str
!= NULL
) {
307 CFRelease(local_ip_str
);
309 if (keys
!= NULL
&& keys
!= keys_static
) {
312 if (service_info
!= NULL
) {
313 CFRelease(service_info
);
315 if (status
!= kSCStatusOK
) {
318 return (ret_signature
);