]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkSignature.c
configd-395.6.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkSignature.c
1 /*
2 * Copyright (c) 2006, 2011 Apple Computer, 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 * SCNetworkSignature.c
26 * - implementation of SCNetworkSignatureRef API that allows access to
27 network identification information
28 *
29 */
30 /*
31 * Modification History
32 *
33 * November 6, 2006 Dieter Siegmund (dieter@apple.com)
34 * - initial revision
35 */
36
37
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>
49
50 const char * kSCNetworkSignatureActiveChangedNotifyName = NETWORK_ID_KEY ".active";
51
52
53 #pragma mark SCNetworkSignature support routines
54
55 static __inline__ SCDynamicStoreRef
56 store_create(CFAllocatorRef alloc)
57 {
58 return (SCDynamicStoreCreate(alloc, CFSTR("SCNetworkSignature"),
59 NULL, NULL));
60 }
61
62 static CFDictionaryRef
63 store_copy_id_dict(CFAllocatorRef alloc, SCDynamicStoreRef store)
64 {
65 CFDictionaryRef id_dict = NULL;
66 Boolean release_store = FALSE;
67
68 if (store == NULL) {
69 store = store_create(alloc);
70 if (store == NULL) {
71 goto done;
72 }
73 release_store = TRUE;
74 }
75 id_dict = SCDynamicStoreCopyValue(store,
76 kSCNetworkIdentificationStoreKey);
77 if (isA_CFDictionary(id_dict) == NULL) {
78 if (id_dict != NULL) {
79 CFRelease(id_dict);
80 id_dict = NULL;
81 }
82 goto done;
83 }
84 done:
85 if (release_store) {
86 CFRelease(store);
87 }
88 return (id_dict);
89 }
90
91 #pragma -
92
93 #pragma mark SCNetworkSignature APIs
94
95 CFStringRef
96 SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc,
97 const struct sockaddr * addr)
98 {
99 CFDictionaryRef id_dict = NULL;
100 CFStringRef ident = NULL;
101 struct sockaddr_in * sin_p;
102
103
104 /* only accept 0.0.0.0 (i.e. default) for now */
105 sin_p = (struct sockaddr_in *)addr;
106 if (addr == NULL
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);
111 goto done;
112 }
113 id_dict = store_copy_id_dict(alloc, NULL);
114 if (id_dict == NULL) {
115 _SCErrorSet(kSCStatusFailed);
116 goto done;
117 }
118 ident = CFDictionaryGetValue(id_dict, kStoreKeyPrimaryIPv4Identifier);
119 if (isA_CFString(ident) != NULL) {
120 CFRetain(ident);
121 }
122 else {
123 _SCErrorSet(kSCStatusFailed);
124 }
125 done:
126 if (id_dict != NULL) {
127 CFRelease(id_dict);
128 }
129 return (ident);
130 }
131
132 CFArrayRef /* of CFStringRef's */
133 SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc)
134 {
135 CFArrayRef active = NULL;
136 int i;
137 int count = 0;
138 CFDictionaryRef id_dict = NULL;
139
140 id_dict = store_copy_id_dict(alloc, NULL);
141 if (id_dict == NULL) {
142 goto done;
143 }
144 active = CFDictionaryGetValue(id_dict, kStoreKeyActiveIdentifiers);
145 if (isA_CFArray(active) != NULL) {
146 count = CFArrayGetCount(active);
147 }
148 if (count == 0) {
149 active = NULL;
150 goto done;
151 }
152 for (i = 0; i < count; i++) {
153 CFStringRef ident = CFArrayGetValueAtIndex(active, i);
154
155 if (isA_CFString(ident) == NULL) {
156 active = NULL;
157 goto done;
158 }
159 }
160 CFRetain(active);
161
162 done:
163 if (id_dict != NULL) {
164 CFRelease(id_dict);
165 }
166 if (active == NULL) {
167 _SCErrorSet(kSCStatusFailed);
168 }
169 return (active);
170 }
171
172 static CFDictionaryRef
173 copy_services_for_address_family(CFAllocatorRef alloc,
174 SCDynamicStoreRef store, int af)
175 {
176 CFDictionaryRef info;
177 CFArrayRef patterns;
178 CFStringRef pattern;
179 CFStringRef prop;
180 Boolean release_store = FALSE;
181
182 if (store == NULL) {
183 store = store_create(alloc);
184 if (store == NULL) {
185 return (NULL);
186 }
187 release_store = TRUE;
188 }
189 prop = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6;
190 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
191 kSCDynamicStoreDomainState,
192 kSCCompAnyRegex,
193 prop);
194 patterns = CFArrayCreate(NULL,
195 (const void * *)&pattern, 1,
196 &kCFTypeArrayCallBacks);
197 CFRelease(pattern);
198 info = SCDynamicStoreCopyMultiple(store, NULL, patterns);
199 CFRelease(patterns);
200 if (release_store) {
201 CFRelease(store);
202 }
203 return (info);
204 }
205
206 static CFStringRef
207 my_IPAddressToCFString(int af, const void * src_p)
208 {
209 char ntopbuf[INET6_ADDRSTRLEN];
210
211 if (inet_ntop(af, src_p, ntopbuf, sizeof(ntopbuf)) != NULL) {
212 return (CFStringCreateWithCString(NULL, ntopbuf,
213 kCFStringEncodingASCII));
214 }
215 return (NULL);
216 }
217
218 CFStringRef
219 SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc,
220 int sock_fd)
221 {
222 CFStringRef addresses_key;
223 int af;
224 int count;
225 int i;
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;
233 union {
234 struct sockaddr_in inet;
235 struct sockaddr_in6 inet6;
236 struct sockaddr sa;
237 } ss;
238 socklen_t ss_len = sizeof(ss);
239 int status = kSCStatusFailed;
240
241 if (getsockname(sock_fd, &ss.sa, &ss_len) != 0) {
242 status = kSCStatusInvalidArgument;
243 goto done;
244 }
245 af = ss.inet.sin_family;
246 switch (af) {
247 case AF_INET:
248 addresses_key = kSCPropNetIPv4Addresses;
249 local_ip_p = &ss.inet.sin_addr;
250 break;
251 case AF_INET6:
252 addresses_key = kSCPropNetIPv6Addresses;
253 local_ip_p = &ss.inet6.sin6_addr;
254 break;
255 default:
256 status = kSCStatusInvalidArgument;
257 goto done;
258 }
259
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) {
263 goto done;
264 }
265 local_ip_str = my_IPAddressToCFString(af, local_ip_p);
266 if (local_ip_str == NULL) {
267 goto done;
268 }
269 count = CFDictionaryGetCount(service_info);
270 if (count > KEYS_STATIC_COUNT) {
271 keys = (const void * *)malloc(sizeof(*keys) * count);
272 }
273 else {
274 keys = keys_static;
275 }
276 CFDictionaryGetKeysAndValues(service_info, keys, NULL);
277 for (i = 0; i < count; i++) {
278 CFArrayRef addrs;
279 CFRange range;
280 CFStringRef signature;
281 CFDictionaryRef value;
282
283 value = CFDictionaryGetValue(service_info, keys[i]);
284 if (isA_CFDictionary(value) == NULL) {
285 continue;
286 }
287 signature = CFDictionaryGetValue(value,
288 kStoreKeyNetworkSignature);
289 if (isA_CFString(signature) == NULL) {
290 /* no signature */
291 continue;
292 }
293 addrs = CFDictionaryGetValue(value, addresses_key);
294 if (isA_CFArray(addrs) == NULL) {
295 continue;
296 }
297 range = CFRangeMake(0, CFArrayGetCount(addrs));
298 if (CFArrayContainsValue(addrs, range, local_ip_str)) {
299 ret_signature = CFRetain(signature);
300 status = kSCStatusOK;
301 break;
302 }
303 }
304
305 done:
306 if (local_ip_str != NULL) {
307 CFRelease(local_ip_str);
308 }
309 if (keys != NULL && keys != keys_static) {
310 free(keys);
311 }
312 if (service_info != NULL) {
313 CFRelease(service_info);
314 }
315 if (status != kSCStatusOK) {
316 _SCErrorSet(status);
317 }
318 return (ret_signature);
319 }
320
321 #pragma mark -