]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkInterface.c
configd-289.2.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkInterface.c
1 /*
2 * Copyright (c) 2004-2009 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 * May 13, 2004 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 * which includes code originally authored by
30 * Robert Ulrich <rulrich@apple.com>
31 * Elizabeth Douglas <elizabeth@apple.com>
32 * Quinn <eskimo1@apple.com>
33 */
34
35
36 #include <Availability.h>
37 #include <TargetConditionals.h>
38 #include <CoreFoundation/CoreFoundation.h>
39 #include <CoreFoundation/CFRuntime.h>
40 #include <SystemConfiguration/SystemConfiguration.h>
41 #include "SCNetworkConfigurationInternal.h"
42 #include <SystemConfiguration/SCValidation.h>
43 #include <SystemConfiguration/SCPrivate.h>
44 #include "SCPreferencesInternal.h"
45 #include "SCHelper_client.h"
46
47 #if !TARGET_OS_IPHONE
48 #include <EAP8021X/EAPClientProperties.h>
49 #else // !TARGET_OS_IPHONE
50 #ifndef kEAPClientPropUserName
51 #define kEAPClientPropUserName CFSTR("UserName")
52 #endif
53 #ifndef kEAPClientPropUserPasswordKeychainItemID
54 #define kEAPClientPropUserPasswordKeychainItemID CFSTR("UserPasswordKeychainItemID")
55 #endif
56 #endif // !TARGET_OS_IPHONE
57
58 #include <IOKit/IOKitLib.h>
59 #include <IOKit/IOCFBundle.h>
60 #include <IOKit/IOBSD.h>
61 #include <IOKit/network/IONetworkController.h>
62 #include <IOKit/network/IONetworkInterface.h>
63 #include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass
64 #include <IOKit/serial/IOSerialKeys.h>
65 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
66 #include <IOKit/usb/USB.h>
67
68 #include "dy_framework.h"
69
70 #ifndef kIODeviceSupportsHoldKey
71 #define kIODeviceSupportsHoldKey "V92Modem"
72 #endif
73
74 #ifndef kUSBProductString
75 #define kUSBProductString "USB Product Name"
76 #endif
77
78 #include <string.h>
79 #include <mach/mach.h>
80 #include <net/if.h>
81 #include <net/if_types.h>
82 #include <net/route.h>
83 #include <sys/param.h>
84 #include <sys/types.h>
85 #include <sys/socket.h>
86 #include <sys/stat.h>
87 #include <sys/sysctl.h>
88 #include <pthread.h>
89 #include <NSSystemDirectories.h>
90
91
92 static CFStringRef copy_interface_string (CFBundleRef bundle, CFStringRef key, Boolean localized);
93 static CFStringRef __SCNetworkInterfaceCopyDescription (CFTypeRef cf);
94 static void __SCNetworkInterfaceDeallocate (CFTypeRef cf);
95 static Boolean __SCNetworkInterfaceEqual (CFTypeRef cf1, CFTypeRef cf2);
96 static CFHashCode __SCNetworkInterfaceHash (CFTypeRef cf);
97
98
99 enum {
100 kSortInternalModem,
101 kSortUSBModem,
102 kSortModem,
103 kSortBluetooth,
104 kSortIrDA,
105 kSortSerialPort,
106 kSortWWAN,
107 kSortEthernetPPP,
108 kSortAirportPPP,
109 kSortEthernet,
110 kSortFireWire,
111 kSortAirPort,
112 kSortOtherWireless,
113 kSortTethered,
114 kSortWWANEthernet,
115 kSortBluetoothPAN,
116 #if !TARGET_OS_IPHONE
117 kSortBond,
118 kSortVLAN,
119 #endif // !TARGET_OS_IPHONE
120 kSortUnknown
121 };
122
123
124 const CFStringRef kSCNetworkInterfaceType6to4 = CFSTR("6to4");
125 const CFStringRef kSCNetworkInterfaceTypeBluetooth = CFSTR("Bluetooth");
126 #if !TARGET_OS_IPHONE
127 const CFStringRef kSCNetworkInterfaceTypeBond = CFSTR("Bond");
128 #endif // !TARGET_OS_IPHONE
129 const CFStringRef kSCNetworkInterfaceTypeEthernet = CFSTR("Ethernet");
130 const CFStringRef kSCNetworkInterfaceTypeFireWire = CFSTR("FireWire");
131 const CFStringRef kSCNetworkInterfaceTypeIEEE80211 = CFSTR("IEEE80211"); // IEEE 802.11, AirPort
132 const CFStringRef kSCNetworkInterfaceTypeIPSec = CFSTR("IPSec");
133 const CFStringRef kSCNetworkInterfaceTypeIrDA = CFSTR("IrDA");
134 const CFStringRef kSCNetworkInterfaceTypeL2TP = CFSTR("L2TP");
135 const CFStringRef kSCNetworkInterfaceTypeModem = CFSTR("Modem");
136 const CFStringRef kSCNetworkInterfaceTypePPP = CFSTR("PPP");
137 const CFStringRef kSCNetworkInterfaceTypePPTP = CFSTR("PPTP");
138 const CFStringRef kSCNetworkInterfaceTypeSerial = CFSTR("Serial");
139 #if !TARGET_OS_IPHONE
140 const CFStringRef kSCNetworkInterfaceTypeVLAN = CFSTR("VLAN");
141 #endif // !TARGET_OS_IPHONE
142 const CFStringRef kSCNetworkInterfaceTypeWWAN = CFSTR("WWAN");
143
144 const CFStringRef kSCNetworkInterfaceTypeIPv4 = CFSTR("IPv4");
145
146 static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4 = {
147 INIT_CFRUNTIME_BASE(NULL, 0, 0x0080), // cfBase
148 NULL, // interface type
149 NULL, // name
150 NULL, // localized name
151 NULL, // localization key
152 NULL, // localization arg1
153 NULL, // localization arg2
154 NULL, // [layered] interface
155 NULL, // prefs
156 NULL, // serviceID
157 NULL, // unsaved
158 NULL, // entity_device
159 NULL, // entity_device_unique
160 NULL, // entity_type
161 NULL, // entity_subtype
162 NULL, // supported_interface_types
163 NULL, // supported_protocol_types
164 NULL, // address
165 NULL, // addressString
166 FALSE, // builtin
167 NULL, // configurationAction
168 NULL, // location
169 NULL, // path
170 NULL, // overrides
171 FALSE, // modemIsV92
172 NULL, // type
173 NULL, // unit
174 kSortUnknown, // sort_order
175 #if !TARGET_OS_IPHONE
176 FALSE, // supportsBond
177 { NULL, NULL}, // bond { interfaces, options }
178 FALSE, // supportsVLAN
179 { NULL, NULL, NULL } // vlan { interface, tag, options }
180 #endif // !TARGET_OS_IPHONE
181 };
182
183 const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4 = (SCNetworkInterfaceRef)&__kSCNetworkInterfaceIPv4;
184
185 #pragma mark -
186 #pragma mark SCNetworkInterface configuration details
187
188 #define doNone 0
189
190 #define do6to4 1<<0
191 #define doL2TP 1<<1
192 #define doPPP 1<<2
193 #define doPPTP 1<<3
194 #define doIPSec 1<<4
195 #define doOverIP do6to4|doL2TP|doPPTP|doIPSec
196
197 #if !TARGET_OS_IPHONE
198 #define doAppleTalk 1<<0
199 #else // !TARGET_OS_IPHONE
200 #define doAppleTalk 0
201 #endif // !TARGET_OS_IPHONE
202 #define doDNS 1<<1
203 #define doIPv4 1<<2
204 #define doIPv6 1<<3
205 #define doProxies 1<<4
206 #if !TARGET_OS_IPHONE
207 #define doSMB 1<<5
208 #else // !TARGET_OS_IPHONE
209 #define doSMB 0
210 #endif // !TARGET_OS_IPHONE
211
212 static const struct {
213 const CFStringRef *interface_type;
214 const CFStringRef *entity_hardware;
215 Boolean per_interface_config;
216 uint32_t supported_interfaces;
217 const CFStringRef *ppp_subtype;
218 uint32_t supported_protocols;
219 } configurations[] = {
220 // interface type entity_hardware if config? interface types PPP sub-type interface protocols
221 // ===================================== ================= ========== =============== ======================================= =========================================
222 { &kSCNetworkInterfaceType6to4 , &kSCEntNet6to4 , FALSE, doNone, NULL, doIPv6 },
223 { &kSCNetworkInterfaceTypeBluetooth , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
224 #if !TARGET_OS_IPHONE
225 { &kSCNetworkInterfaceTypeBond , &kSCEntNetEthernet, TRUE , doNone, NULL, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies|doSMB },
226 #endif // !TARGET_OS_IPHONE
227 { &kSCNetworkInterfaceTypeEthernet , &kSCEntNetEthernet, TRUE , doPPP, &kSCValNetInterfaceSubTypePPPoE, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies|doSMB },
228 { &kSCNetworkInterfaceTypeFireWire , &kSCEntNetFireWire, TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
229 { &kSCNetworkInterfaceTypeIEEE80211 , &kSCEntNetAirPort , TRUE , doPPP, &kSCValNetInterfaceSubTypePPPoE, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies|doSMB },
230 { &kSCNetworkInterfaceTypeIPSec , &kSCEntNetIPSec , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
231 { &kSCNetworkInterfaceTypeIrDA , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
232 { &kSCNetworkInterfaceTypeL2TP , NULL , FALSE, doPPP, &kSCValNetInterfaceSubTypeL2TP, doNone },
233 { &kSCNetworkInterfaceTypeModem , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
234 { &kSCNetworkInterfaceTypePPP , &kSCEntNetPPP , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
235 { &kSCNetworkInterfaceTypePPTP , NULL , FALSE, doPPP, &kSCValNetInterfaceSubTypePPTP, doNone },
236 { &kSCNetworkInterfaceTypeSerial , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
237 #if !TARGET_OS_IPHONE
238 { &kSCNetworkInterfaceTypeVLAN , &kSCEntNetEthernet, TRUE , doNone, NULL, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies|doSMB },
239 #endif // !TARGET_OS_IPHONE
240 { &kSCNetworkInterfaceTypeWWAN , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
241 // ===================================== ================= ========== =============== ======================================= =========================================
242 { &kSCNetworkInterfaceTypeIPv4 , NULL , FALSE, doOverIP, NULL, doNone }
243 };
244
245
246 #define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
247 static CFBundleRef bundle = NULL;
248
249
250 static CFTypeID __kSCNetworkInterfaceTypeID = _kCFRuntimeNotATypeID;
251
252
253 static const CFRuntimeClass __SCNetworkInterfaceClass = {
254 0, // version
255 "SCNetworkInterface", // className
256 NULL, // init
257 NULL, // copy
258 __SCNetworkInterfaceDeallocate, // dealloc
259 __SCNetworkInterfaceEqual, // equal
260 __SCNetworkInterfaceHash, // hash
261 NULL, // copyFormattingDesc
262 __SCNetworkInterfaceCopyDescription // copyDebugDesc
263 };
264
265
266 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
267 static pthread_once_t iokit_quiet = PTHREAD_ONCE_INIT;
268
269
270 static mach_port_t masterPort = MACH_PORT_NULL;
271
272
273 static CFStringRef
274 __SCNetworkInterfaceCopyDescription(CFTypeRef cf)
275 {
276 CFAllocatorRef allocator = CFGetAllocator(cf);
277 CFMutableStringRef result;
278 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
279
280 result = CFStringCreateMutable(allocator, 0);
281 CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkInterface %p [%p]> {"), cf, allocator);
282 CFStringAppendFormat(result, NULL, CFSTR("type = %@"), interfacePrivate->interface_type);
283 CFStringAppendFormat(result, NULL, CFSTR(", entity_device = %@"), interfacePrivate->entity_device);
284 if (interfacePrivate->entity_device_unique != NULL) {
285 CFStringAppendFormat(result, NULL, CFSTR("+%@"), interfacePrivate->entity_device_unique);
286 }
287 CFStringAppendFormat(result, NULL, CFSTR(", entity_type = %@"), interfacePrivate->entity_type);
288 if (interfacePrivate->entity_subtype != NULL) {
289 CFStringAppendFormat(result, NULL, CFSTR(" / %@"), interfacePrivate->entity_subtype);
290 }
291 if (interfacePrivate->name != NULL) {
292 CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), interfacePrivate->name);
293 }
294 if (interfacePrivate->localized_name != NULL) {
295 CFStringAppendFormat(result, NULL, CFSTR(", name(l) = %@"), interfacePrivate->localized_name);
296 } else {
297 if (interfacePrivate->localized_key != NULL) {
298 CFStringAppendFormat(result, NULL, CFSTR(", name(k) = \"%@\""), interfacePrivate->localized_key);
299 if (interfacePrivate->localized_arg1 != NULL) {
300 CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg1);
301 }
302 if (interfacePrivate->localized_arg2 != NULL) {
303 CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg2);
304 }
305 }
306 }
307 if (interfacePrivate->address != NULL) {
308 const uint8_t *data;
309 CFIndex dataLen;
310 CFIndex i;
311
312 CFStringAppendFormat(result, NULL, CFSTR(", address = 0x"));
313
314 data = CFDataGetBytePtr(interfacePrivate->address);
315 dataLen = CFDataGetLength(interfacePrivate->address);
316 for (i = 0; i < dataLen; i++) {
317 CFStringAppendFormat(result, NULL, CFSTR("%02x"), data[i]);
318 }
319 }
320 CFStringAppendFormat(result, NULL, CFSTR(", builtin = %s"), interfacePrivate->builtin ? "TRUE" : "FALSE");
321 if (interfacePrivate->modemIsV92) {
322 CFStringAppendFormat(result, NULL, CFSTR(", v.92"));
323 }
324 if (interfacePrivate->location != NULL) {
325 CFStringAppendFormat(result, NULL, CFSTR(", location = %@"), interfacePrivate->location);
326 }
327 if (interfacePrivate->type != NULL) {
328 CFStringAppendFormat(result, NULL, CFSTR(", type = %@"), interfacePrivate->type);
329 }
330 if (interfacePrivate->unit != NULL) {
331 CFStringAppendFormat(result, NULL, CFSTR(", unit = %@"), interfacePrivate->unit);
332 }
333 if (interfacePrivate->path != NULL) {
334 CFStringAppendFormat(result, NULL, CFSTR(", path = %@"), interfacePrivate->path);
335 }
336 if (interfacePrivate->configurationAction != NULL) {
337 CFStringAppendFormat(result, NULL, CFSTR(", action = %@"), interfacePrivate->configurationAction);
338 }
339 if (interfacePrivate->overrides != NULL) {
340 CFStringAppendFormat(result, NULL, CFSTR(", overrides = %p"), interfacePrivate->overrides);
341 }
342 CFStringAppendFormat(result, NULL, CFSTR(", order = %d"), interfacePrivate->sort_order);
343 if (interfacePrivate->prefs != NULL) {
344 CFStringAppendFormat(result, NULL, CFSTR(", prefs = %p"), interfacePrivate->prefs);
345 }
346 if (interfacePrivate->serviceID != NULL) {
347 CFStringAppendFormat(result, NULL, CFSTR(", service = %@"), interfacePrivate->serviceID);
348 }
349 if (interfacePrivate->interface != NULL) {
350 CFStringAppendFormat(result, NULL, CFSTR(", interface = %@"), interfacePrivate->interface);
351 }
352 if (interfacePrivate->unsaved != NULL) {
353 CFStringAppendFormat(result, NULL, CFSTR(", unsaved = %@"), interfacePrivate->unsaved);
354 }
355 #if !TARGET_OS_IPHONE
356 if (interfacePrivate->bond.interfaces != NULL) {
357 CFIndex i;
358 CFIndex n;
359
360 n = CFArrayGetCount(interfacePrivate->bond.interfaces);
361 for (i = 0; i < n; i++) {
362 SCNetworkInterfaceRef member;
363
364 member = CFArrayGetValueAtIndex(interfacePrivate->bond.interfaces, i);
365 CFStringAppendFormat(result, NULL,
366 CFSTR("%s%@"),
367 (i == 0) ? ", interfaces = " : ", ",
368 SCNetworkInterfaceGetBSDName(member));
369 }
370 }
371 if (interfacePrivate->bond.mode != NULL) {
372 CFStringAppendFormat(result, NULL, CFSTR(", mode = %@"), interfacePrivate->bond.mode);
373 }
374 if (interfacePrivate->bond.options != NULL) {
375 CFStringAppendFormat(result, NULL, CFSTR(", options = %@"), interfacePrivate->bond.options);
376 }
377 if (interfacePrivate->bond.mode != NULL) {
378 CFStringAppendFormat(result, NULL, CFSTR(", mode = %@"), interfacePrivate->bond.mode);
379 }
380 if (interfacePrivate->vlan.interface != NULL) {
381 CFStringAppendFormat(result, NULL,
382 CFSTR(", interface = %@"),
383 SCNetworkInterfaceGetBSDName(interfacePrivate->vlan.interface));
384 }
385 if (interfacePrivate->vlan.tag != NULL) {
386 CFStringAppendFormat(result, NULL, CFSTR(", tag = %@"), interfacePrivate->vlan.tag);
387 }
388 if (interfacePrivate->vlan.options != NULL) {
389 CFStringAppendFormat(result, NULL, CFSTR(", options = %@"), interfacePrivate->vlan.options);
390 }
391 #endif // !TARGET_OS_IPHONE
392 CFStringAppendFormat(result, NULL, CFSTR("}"));
393
394 return result;
395 }
396
397
398 static void
399 __SCNetworkInterfaceDeallocate(CFTypeRef cf)
400 {
401 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
402
403 /* release resources */
404
405 if (interfacePrivate->interface != NULL)
406 CFRelease(interfacePrivate->interface);
407
408 if (interfacePrivate->name != NULL)
409 CFRelease(interfacePrivate->name);
410
411 if (interfacePrivate->localized_name != NULL)
412 CFRelease(interfacePrivate->localized_name);
413
414 if (interfacePrivate->localized_arg1 != NULL)
415 CFRelease(interfacePrivate->localized_arg1);
416
417 if (interfacePrivate->localized_arg2 != NULL)
418 CFRelease(interfacePrivate->localized_arg2);
419
420 if (interfacePrivate->prefs != NULL)
421 CFRelease(interfacePrivate->prefs);
422
423 if (interfacePrivate->serviceID != NULL)
424 CFRelease(interfacePrivate->serviceID);
425
426 if (interfacePrivate->unsaved != NULL)
427 CFRelease(interfacePrivate->unsaved);
428
429 if (interfacePrivate->entity_device != NULL)
430 CFRelease(interfacePrivate->entity_device);
431
432 if (interfacePrivate->entity_device_unique != NULL)
433 CFRelease(interfacePrivate->entity_device_unique);
434
435 if (interfacePrivate->supported_interface_types != NULL)
436 CFRelease(interfacePrivate->supported_interface_types);
437
438 if (interfacePrivate->supported_protocol_types != NULL)
439 CFRelease(interfacePrivate->supported_protocol_types);
440
441 if (interfacePrivate->address != NULL)
442 CFRelease(interfacePrivate->address);
443
444 if (interfacePrivate->addressString != NULL)
445 CFRelease(interfacePrivate->addressString);
446
447 if (interfacePrivate->location != NULL)
448 CFRelease(interfacePrivate->location);
449
450 if (interfacePrivate->path != NULL)
451 CFRelease(interfacePrivate->path);
452
453 if (interfacePrivate->configurationAction != NULL)
454 CFRelease(interfacePrivate->configurationAction);
455
456 if (interfacePrivate->overrides != NULL)
457 CFRelease(interfacePrivate->overrides);
458
459 if (interfacePrivate->type != NULL)
460 CFRelease(interfacePrivate->type);
461
462 if (interfacePrivate->unit != NULL)
463 CFRelease(interfacePrivate->unit);
464
465 #if !TARGET_OS_IPHONE
466 if (interfacePrivate->bond.interfaces != NULL)
467 CFRelease(interfacePrivate->bond.interfaces);
468
469 if (interfacePrivate->bond.mode != NULL)
470 CFRelease(interfacePrivate->bond.mode);
471
472 if (interfacePrivate->bond.options != NULL)
473 CFRelease(interfacePrivate->bond.options);
474
475 if (interfacePrivate->vlan.interface != NULL)
476 CFRelease(interfacePrivate->vlan.interface);
477
478 if (interfacePrivate->vlan.tag != NULL)
479 CFRelease(interfacePrivate->vlan.tag);
480
481 if (interfacePrivate->vlan.options != NULL)
482 CFRelease(interfacePrivate->vlan.options);
483 #endif // !TARGET_OS_IPHONE
484
485 return;
486 }
487
488
489 static Boolean
490 __SCNetworkInterfaceEqual(CFTypeRef cf1, CFTypeRef cf2)
491 {
492 SCNetworkInterfacePrivateRef if1 = (SCNetworkInterfacePrivateRef)cf1;
493 SCNetworkInterfacePrivateRef if2 = (SCNetworkInterfacePrivateRef)cf2;
494
495 if (if1 == if2)
496 return TRUE;
497
498 if (!CFEqual(if1->interface_type, if2->interface_type)) {
499 return FALSE; // if not the same interface type
500 }
501
502 if (!_SC_CFEqual(if1->entity_device, if2->entity_device)) {
503 return FALSE; // if not the same device
504 }
505
506 if ((if1->entity_device_unique != NULL) && (if2->entity_device_unique != NULL)) {
507 if (!_SC_CFEqual(if1->entity_device_unique, if2->entity_device_unique)) {
508 return FALSE; // if not the same device unique identifier
509 }
510 } else if ((if1->entity_device_unique != NULL) || (if2->entity_device_unique != NULL)) {
511 CFStringRef name1;
512 CFStringRef name2;
513
514 name1 = __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef)if1);
515 name2 = __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef)if2);
516 if ((name1 != NULL) && (name2 != NULL) && !_SC_CFEqual(name1, name2)) {
517 return FALSE; // if same device but not the same display name
518 }
519 }
520
521 #if !TARGET_OS_IPHONE
522 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeBond)) {
523 if (!_SC_CFEqual(if1->bond.interfaces, if2->bond.interfaces)) {
524 return FALSE; // if not the same interfaces
525 }
526 if (!_SC_CFEqual(if1->bond.mode, if2->bond.mode)) {
527 return FALSE; // if not the same mode
528 }
529 }
530
531 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeVLAN)) {
532 if (!_SC_CFEqual(if1->vlan.interface, if2->vlan.interface)) {
533 return FALSE; // if not the same physical interface
534 }
535 if (!_SC_CFEqual(if1->vlan.tag, if2->vlan.tag)) {
536 return FALSE; // if not the same tag
537 }
538 }
539 #endif // !TARGET_OS_IPHONE
540
541 if (!_SC_CFEqual(if1->interface, if2->interface)) {
542 return FALSE; // if not the same layering
543 }
544
545 return TRUE;
546 }
547
548
549 static CFHashCode
550 __SCNetworkInterfaceHash(CFTypeRef cf)
551 {
552 CFHashCode hash = 0;
553 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
554
555 if (interfacePrivate->entity_device != NULL) {
556 if (interfacePrivate->entity_device_unique == NULL) {
557 hash = CFHash(interfacePrivate->entity_device);
558 } else {
559 CFStringRef str;
560
561 str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@+%@"),
562 interfacePrivate->entity_device,
563 interfacePrivate->entity_device_unique);
564 hash = CFHash(str);
565 CFRelease(str);
566 }
567 }
568
569 return hash;
570 }
571
572
573 static void
574 __SCNetworkInterfaceInitialize(void)
575 {
576 kern_return_t kr;
577
578 // register w/CF
579 __kSCNetworkInterfaceTypeID = _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass);
580
581 // initialize __kSCNetworkInterfaceIPv4
582 _CFRuntimeSetInstanceTypeID(&__kSCNetworkInterfaceIPv4, __kSCNetworkInterfaceTypeID);
583 __kSCNetworkInterfaceIPv4.interface_type = kSCNetworkInterfaceTypeIPv4;
584 __kSCNetworkInterfaceIPv4.localized_key = CFSTR("ipv4");
585
586 // get CFBundleRef for SystemConfiguration.framework
587 bundle = _SC_CFBundleGet();
588
589 // get mach port used to communication with IOKit
590 kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
591 if (kr != KERN_SUCCESS) {
592 SCLog(TRUE, LOG_DEBUG,
593 CFSTR("__SCNetworkInterfaceInitialize(), could not get IOMasterPort, kr = 0x%x"),
594 kr);
595 }
596
597 return;
598 }
599
600
601 __private_extern__
602 SCNetworkInterfacePrivateRef
603 __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator,
604 SCNetworkInterfaceRef interface,
605 SCPreferencesRef prefs,
606 CFStringRef serviceID,
607 io_string_t path)
608 {
609 SCNetworkInterfacePrivateRef interfacePrivate;
610 uint32_t size;
611
612 /* initialize runtime */
613 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
614
615 /* allocate target */
616 size = sizeof(SCNetworkInterfacePrivate) - sizeof(CFRuntimeBase);
617 interfacePrivate = (SCNetworkInterfacePrivateRef)_CFRuntimeCreateInstance(allocator,
618 __kSCNetworkInterfaceTypeID,
619 size,
620 NULL);
621 if (interfacePrivate == NULL) {
622 return NULL;
623 }
624
625 interfacePrivate->interface_type = NULL;
626 interfacePrivate->name = NULL;
627 interfacePrivate->localized_name = NULL;
628 interfacePrivate->localized_key = NULL;
629 interfacePrivate->localized_arg1 = NULL;
630 interfacePrivate->localized_arg2 = NULL;
631 interfacePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL;
632 interfacePrivate->prefs = (prefs != NULL) ? CFRetain(prefs) : NULL;
633 interfacePrivate->serviceID = (serviceID != NULL) ? CFRetain(serviceID) : NULL;
634 interfacePrivate->unsaved = NULL;
635 interfacePrivate->entity_device = NULL;
636 interfacePrivate->entity_device_unique = NULL;
637 interfacePrivate->entity_type = NULL;
638 interfacePrivate->entity_subtype = NULL;
639 interfacePrivate->supported_interface_types = NULL;
640 interfacePrivate->supported_protocol_types = NULL;
641 interfacePrivate->address = NULL;
642 interfacePrivate->addressString = NULL;
643 interfacePrivate->builtin = FALSE;
644 interfacePrivate->configurationAction = NULL;
645 interfacePrivate->path = (path != NULL) ? CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8)
646 : NULL;
647 interfacePrivate->location = NULL;
648 interfacePrivate->overrides = NULL;
649 interfacePrivate->modemIsV92 = FALSE;
650 interfacePrivate->type = NULL;
651 interfacePrivate->unit = NULL;
652 interfacePrivate->sort_order = kSortUnknown;
653 #if !TARGET_OS_IPHONE
654 interfacePrivate->supportsBond = FALSE;
655 interfacePrivate->bond.interfaces = NULL;
656 interfacePrivate->bond.mode = NULL;
657 interfacePrivate->bond.options = NULL;
658 interfacePrivate->supportsVLAN = FALSE;
659 interfacePrivate->vlan.interface = NULL;
660 interfacePrivate->vlan.tag = NULL;
661 interfacePrivate->vlan.options = NULL;
662 #endif // !TARGET_OS_IPHONE
663
664 return interfacePrivate;
665 }
666
667
668 #if !TARGET_OS_IPHONE
669 __private_extern__
670 Boolean
671 __SCNetworkInterfaceSupportsVLAN(CFStringRef bsd_if)
672 {
673 char * buf = NULL;
674 size_t buf_len = 0;
675 struct if_msghdr * ifm;
676 char * if_name = NULL;
677 unsigned int if_index;
678 int mib[6];
679 Boolean vlanOK = FALSE;
680
681 // get the interface index
682 if_name = _SC_cfstring_to_cstring(bsd_if, NULL, 0, kCFStringEncodingASCII);
683 if (if_name == NULL) {
684 return FALSE; // if conversion error
685 }
686 if_index = if_nametoindex(if_name);
687 if (if_index == 0) {
688 goto done; // if unknown interface
689 }
690
691 // get information for the specified interface
692 mib[0] = CTL_NET;
693 mib[1] = PF_ROUTE;
694 mib[2] = 0;
695 mib[3] = AF_LINK;
696 mib[4] = NET_RT_IFLIST;
697 mib[5] = if_index; /* ask for exactly one interface */
698
699 if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) == -1) {
700 SCLog(TRUE, LOG_ERR, CFSTR("sysctl() size failed: %s"), strerror(errno));
701 goto done;
702 }
703 buf = CFAllocatorAllocate(NULL, buf_len, 0);
704 if (sysctl(mib, 6, buf, &buf_len, NULL, 0) == -1) {
705 SCLog(TRUE, LOG_ERR, CFSTR("sysctl() failed: %s"), strerror(errno));
706 goto done;
707 }
708
709 // check the link type and hwassist flags
710 ifm = (struct if_msghdr *)buf;
711 switch (ifm->ifm_type) {
712 case RTM_IFINFO : {
713 #if defined(IF_HWASSIST_VLAN_TAGGING) && defined(IF_HWASSIST_VLAN_MTU)
714 struct if_data *if_data = &ifm->ifm_data;
715
716 if (if_data->ifi_hwassist & (IF_HWASSIST_VLAN_TAGGING | IF_HWASSIST_VLAN_MTU)) {
717 vlanOK = TRUE;
718 }
719 #endif
720 break;
721 }
722 }
723
724 done :
725
726 if (if_name != NULL) CFAllocatorDeallocate(NULL, if_name);
727 if (buf != NULL) CFAllocatorDeallocate(NULL, buf);
728
729 return vlanOK;
730 }
731
732
733 __private_extern__
734 SCNetworkInterfacePrivateRef
735 _SCBondInterfaceCreatePrivate(CFAllocatorRef allocator,
736 CFStringRef bond_if)
737 {
738 SCNetworkInterfacePrivateRef interfacePrivate;
739
740 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL, NULL);
741 if (interfacePrivate == NULL) {
742 return NULL;
743 }
744
745 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBond;
746 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
747 interfacePrivate->entity_device = CFStringCreateCopy(allocator, bond_if);
748 interfacePrivate->builtin = TRUE;
749 interfacePrivate->supportsVLAN = __SCNetworkInterfaceSupportsVLAN(bond_if);
750 interfacePrivate->sort_order = kSortBond;
751
752 interfacePrivate->localized_key = CFSTR("bond");
753 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
754
755 interfacePrivate->bond.interfaces = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
756 // interfacePrivate->bond.mode = NULL;
757 // interfacePrivate->bond.options = NULL;
758
759 return interfacePrivate;
760 }
761
762
763 __private_extern__
764 SCNetworkInterfacePrivateRef
765 _SCVLANInterfaceCreatePrivate(CFAllocatorRef allocator,
766 CFStringRef vlan_if)
767 {
768 SCNetworkInterfacePrivateRef interfacePrivate;
769
770 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL, NULL);
771 if (interfacePrivate == NULL) {
772 return NULL;
773 }
774
775 interfacePrivate->interface_type = kSCNetworkInterfaceTypeVLAN;
776 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
777 interfacePrivate->entity_device = CFStringCreateCopy(allocator, vlan_if);
778 interfacePrivate->builtin = TRUE;
779 interfacePrivate->sort_order = kSortVLAN;
780
781 interfacePrivate->localized_key = CFSTR("vlan");
782 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
783
784 // interfacePrivate->vlan.interface = NULL;
785 // interfacePrivate->vlan.tag = NULL;
786 // interfacePrivate->vlan.options = NULL;
787
788 return interfacePrivate;
789 }
790 #endif // !TARGET_OS_IPHONE
791
792
793 #pragma mark -
794 #pragma mark Interface ordering
795
796
797 static CFArrayRef
798 split_path(CFStringRef path)
799 {
800 CFArrayRef components;
801 CFMutableStringRef nPath;
802
803 // turn '@'s into '/'s
804 nPath = CFStringCreateMutableCopy(NULL, 0, path);
805 (void) CFStringFindAndReplace(nPath,
806 CFSTR("@"),
807 CFSTR("/"),
808 CFRangeMake(0, CFStringGetLength(nPath)),
809 0);
810
811 // split path into components to be compared
812 components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
813 CFRelease(nPath);
814
815 return components;
816 }
817
818
819 CFComparisonResult
820 _SCNetworkInterfaceCompare(const void *val1, const void *val2, void *context)
821 {
822 SCNetworkInterfacePrivateRef dev1 = (SCNetworkInterfacePrivateRef)val1;
823 SCNetworkInterfacePrivateRef dev2 = (SCNetworkInterfacePrivateRef)val2;
824 CFComparisonResult res = kCFCompareEqualTo;
825
826 /* sort by interface type */
827 if (dev1->sort_order != dev2->sort_order) {
828 if (dev1->sort_order < dev2->sort_order) {
829 res = kCFCompareLessThan;
830 } else {
831 res = kCFCompareGreaterThan;
832 }
833 return (res);
834 }
835
836 /* built-in interfaces sort first */
837 if (dev1->builtin != dev2->builtin) {
838 if (dev1->builtin) {
839 res = kCFCompareLessThan;
840 } else {
841 res = kCFCompareGreaterThan;
842 }
843 return (res);
844 }
845
846 /* ... and then, sort built-in interfaces by "location" */
847 if (dev1->builtin) {
848 if (dev1->location != dev2->location) {
849 if (isA_CFString(dev1->location)) {
850 if (isA_CFString(dev2->location)) {
851 res = CFStringCompare(dev1->location, dev2->location, 0);
852 } else {
853 res = kCFCompareLessThan;
854 }
855 } else {
856 res = kCFCompareGreaterThan;
857 }
858
859 if (res != kCFCompareEqualTo) {
860 return (res);
861 }
862 }
863 }
864
865 /* ... and, then sort by IOPathMatch */
866 if ((dev1->path != NULL) && (dev2->path != NULL)) {
867 CFArrayRef elements1;
868 CFArrayRef elements2;
869 CFIndex i;
870 CFIndex n;
871 CFIndex n1;
872 CFIndex n2;
873
874 elements1 = split_path(dev1->path);
875 n1 = CFArrayGetCount(elements1);
876
877 elements2 = split_path(dev2->path);
878 n2 = CFArrayGetCount(elements2);
879
880 n = (n1 <= n2) ? n1 : n2;
881 for (i = 0; i < n; i++) {
882 CFStringRef e1;
883 CFStringRef e2;
884 char *end;
885 quad_t q1;
886 quad_t q2;
887 char *str;
888 Boolean isNum;
889
890 e1 = CFArrayGetValueAtIndex(elements1, i);
891 e2 = CFArrayGetValueAtIndex(elements2, i);
892
893 str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingUTF8);
894 errno = 0;
895 q1 = strtoq(str, &end, 16);
896 isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
897 CFAllocatorDeallocate(NULL, str);
898
899 if (isNum) {
900 // if e1 is a valid numeric string
901 str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingUTF8);
902 errno = 0;
903 q2 = strtoq(str, &end, 16);
904 isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
905 CFAllocatorDeallocate(NULL, str);
906
907 if (isNum) {
908 // if e2 is also a valid numeric string
909
910 if (q1 == q2) {
911 res = kCFCompareEqualTo;
912 continue;
913 } else if (q1 < q2) {
914 res = kCFCompareLessThan;
915 } else {
916 res = kCFCompareGreaterThan;
917 }
918 break;
919 }
920 }
921
922 res = CFStringCompare(e1, e2, 0);
923 if (res != kCFCompareEqualTo) {
924 break;
925 }
926 }
927
928 if (res == kCFCompareEqualTo) {
929 if (n1 < n2) {
930 res = kCFCompareLessThan;
931 } else if (n1 < n2) {
932 res = kCFCompareGreaterThan;
933 }
934 }
935
936 CFRelease(elements1);
937 CFRelease(elements2);
938
939 if (res != kCFCompareEqualTo) {
940 return (res);
941 }
942 }
943
944 /* ... and, then sort by BSD interface name */
945 if ((dev1->entity_device != NULL) && (dev2->entity_device != NULL)) {
946 res = CFStringCompare(dev1->entity_device, dev2->entity_device, 0);
947 if (res != kCFCompareEqualTo) {
948 return (res);
949 }
950 }
951
952 /* ... and lastly, sort by BSD interface unique identifier */
953 if ((dev1->entity_device_unique != NULL) && (dev2->entity_device_unique != NULL)) {
954 res = CFStringCompare(dev1->entity_device_unique, dev2->entity_device_unique, 0);
955 // if (res != kCFCompareEqualTo) {
956 // return (res);
957 // }
958 }
959
960 return res;
961 }
962
963
964 static void
965 sort_interfaces(CFMutableArrayRef all_interfaces)
966 {
967 int n = CFArrayGetCount(all_interfaces);
968
969 if (n < 2) {
970 return;
971 }
972
973 CFArraySortValues(all_interfaces, CFRangeMake(0, n), _SCNetworkInterfaceCompare, NULL);
974 return;
975 }
976
977
978 __private_extern__
979 int
980 __SCNetworkInterfaceOrder(SCNetworkInterfaceRef interface)
981 {
982 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
983
984 return interfacePrivate->sort_order;
985 }
986
987
988 #pragma mark -
989 #pragma mark Interface details
990
991
992 static CFStringRef
993 IOCopyCFStringValue(CFTypeRef ioVal)
994 {
995 if (isA_CFString(ioVal)) {
996 return CFStringCreateCopy(NULL, ioVal);
997 }
998
999 if (isA_CFData(ioVal)) {
1000 return CFStringCreateWithCString(NULL,
1001 (const char *)CFDataGetBytePtr(ioVal),
1002 kCFStringEncodingUTF8);
1003 }
1004
1005 return NULL;
1006 }
1007
1008
1009 static CFStringRef
1010 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict, CFStringRef io_key)
1011 {
1012 CFTypeRef ioVal;
1013
1014 ioVal = CFDictionaryGetValue(io_dict, io_key);
1015 return IOCopyCFStringValue(ioVal);
1016 }
1017
1018
1019 static Boolean
1020 IOStringValueHasPrefix(CFTypeRef ioVal, CFStringRef prefix)
1021 {
1022 Boolean match = FALSE;
1023 CFIndex prefixLen = CFStringGetLength(prefix);
1024 CFStringRef str = NULL;
1025
1026 if (!isA_CFString(ioVal)) {
1027 if (isA_CFData(ioVal)) {
1028 str = CFStringCreateWithCStringNoCopy(NULL,
1029 (const char *)CFDataGetBytePtr(ioVal),
1030 kCFStringEncodingUTF8,
1031 kCFAllocatorNull);
1032 ioVal = str;
1033 } else {
1034 return FALSE;
1035 }
1036 }
1037
1038 if ((ioVal != NULL) &&
1039 (CFStringGetLength(ioVal) >= prefixLen) &&
1040 (CFStringCompareWithOptions(ioVal,
1041 prefix,
1042 CFRangeMake(0, prefixLen),
1043 kCFCompareCaseInsensitive) == kCFCompareEqualTo)) {
1044 match = TRUE;
1045 }
1046
1047 if (str != NULL) CFRelease(str);
1048 return match;
1049 }
1050
1051
1052 static const struct {
1053 const CFStringRef name;
1054 const CFStringRef slot;
1055 } slot_mappings[] = {
1056 // Beige G3
1057 { CFSTR("A1") , CFSTR("1") },
1058 { CFSTR("B1") , CFSTR("2") },
1059 { CFSTR("C1") , CFSTR("3") },
1060
1061 // Blue&White G3, Yikes G4
1062 { CFSTR("J12"), CFSTR("1") },
1063 { CFSTR("J11"), CFSTR("2") },
1064 { CFSTR("J10"), CFSTR("3") },
1065 { CFSTR("J9"), CFSTR("4") },
1066
1067 // AGP G4
1068 { CFSTR("A") , CFSTR("1") },
1069 { CFSTR("B") , CFSTR("2") },
1070 { CFSTR("C") , CFSTR("3") },
1071 { CFSTR("D") , CFSTR("4") },
1072
1073 // Digital Audio G4 (and later models)
1074 { CFSTR("1") , CFSTR("1") },
1075 { CFSTR("2") , CFSTR("2") },
1076 { CFSTR("3") , CFSTR("3") },
1077 { CFSTR("4") , CFSTR("4") },
1078 { CFSTR("5") , CFSTR("5") }
1079 };
1080
1081
1082 static CFStringRef
1083 pci_slot(io_registry_entry_t interface, CFTypeRef *pci_slot_name)
1084 {
1085 kern_return_t kr;
1086 io_registry_entry_t parent;
1087 CFMutableStringRef slot;
1088 CFTypeRef slot_name;
1089
1090 slot = NULL;
1091 if (pci_slot_name != NULL) *pci_slot_name = NULL;
1092
1093 slot_name = IORegistryEntryCreateCFProperty(interface, CFSTR("AAPL,slot-name"), NULL, 0);
1094 if (slot_name != NULL) {
1095 CFIndex i;
1096
1097 slot = CFStringCreateMutable(NULL, 0);
1098 if (isA_CFString(slot_name)) {
1099 if (pci_slot_name != NULL) *pci_slot_name = CFStringCreateCopy(NULL, slot_name);
1100 CFStringAppend(slot, slot_name);
1101 } else if (isA_CFData(slot_name)) {
1102 if (pci_slot_name != NULL) *pci_slot_name = CFDataCreateCopy(NULL, slot_name);
1103 CFStringAppendCString(slot,
1104 (const char *)CFDataGetBytePtr(slot_name),
1105 kCFStringEncodingUTF8);
1106 }
1107
1108 if (CFStringGetLength(slot) > 5) {
1109 (void) CFStringFindAndReplace(slot,
1110 CFSTR("slot-"),
1111 CFSTR(""),
1112 CFRangeMake(0, 5),
1113 kCFCompareCaseInsensitive|kCFCompareAnchored);
1114 }
1115
1116 for (i = 0; i < sizeof(slot_mappings)/sizeof(slot_mappings[0]); i++) {
1117 if (CFStringCompare(slot,
1118 slot_mappings[i].name,
1119 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
1120 CFRelease(slot);
1121 slot = (CFMutableStringRef)CFRetain(slot_mappings[i].slot);
1122 break;
1123 }
1124 }
1125
1126 CFRelease(slot_name);
1127 }
1128
1129 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &parent);
1130 switch (kr) {
1131 case kIOReturnSuccess : {
1132 CFTypeRef parent_pci_slot_name = NULL;
1133 CFStringRef parent_slot;
1134
1135 parent_slot = pci_slot(parent, &parent_pci_slot_name);
1136 if (parent_slot != NULL) {
1137 if (slot != NULL) CFRelease(slot);
1138 slot = (CFMutableStringRef)parent_slot;
1139
1140 if (pci_slot_name != NULL) {
1141 if (*pci_slot_name != NULL) CFRelease(*pci_slot_name);
1142 *pci_slot_name = parent_pci_slot_name;
1143 } else {
1144 CFRelease(parent_pci_slot_name);
1145 }
1146 }
1147
1148 IOObjectRelease(parent);
1149 break;
1150 }
1151 case kIOReturnNoDevice :
1152 // if we have hit the root node
1153 break;
1154 default :
1155 SCLog(TRUE, LOG_DEBUG, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
1156 break;
1157 }
1158
1159 return slot;
1160 }
1161
1162
1163 static CFComparisonResult
1164 compare_bsdNames(const void *val1, const void *val2, void *context)
1165 {
1166 CFStringRef bsd1 = (CFStringRef)val1;
1167 CFStringRef bsd2 = (CFStringRef)val2;
1168
1169 return CFStringCompare(bsd1, bsd2, 0);
1170 }
1171
1172
1173 static CFStringRef
1174 pci_port(CFTypeRef slot_name, CFStringRef bsdName)
1175 {
1176 CFIndex n;
1177 CFStringRef port_name = NULL;
1178 CFMutableArrayRef port_names;
1179
1180 kern_return_t kr;
1181 CFStringRef match_keys[2];
1182 CFTypeRef match_vals[2];
1183 CFDictionaryRef match_dict;
1184 CFDictionaryRef matching;
1185 io_registry_entry_t slot;
1186 io_iterator_t slot_iterator = MACH_PORT_NULL;
1187
1188 match_keys[0] = CFSTR("AAPL,slot-name");
1189 match_vals[0] = slot_name;
1190
1191 match_dict = CFDictionaryCreate(NULL,
1192 (const void **)match_keys,
1193 (const void **)match_vals,
1194 1,
1195 &kCFTypeDictionaryKeyCallBacks,
1196 &kCFTypeDictionaryValueCallBacks);
1197
1198 match_keys[0] = CFSTR(kIOProviderClassKey);
1199 match_vals[0] = CFSTR("IOPCIDevice");
1200
1201 match_keys[1] = CFSTR(kIOPropertyMatchKey);
1202 match_vals[1] = match_dict;
1203
1204 // note: the "matching" dictionary will be consumed by the following
1205 matching = CFDictionaryCreate(NULL,
1206 (const void **)match_keys,
1207 (const void **)match_vals,
1208 sizeof(match_keys)/sizeof(match_keys[0]),
1209 &kCFTypeDictionaryKeyCallBacks,
1210 &kCFTypeDictionaryValueCallBacks);
1211 CFRelease(match_dict);
1212
1213 kr = IOServiceGetMatchingServices(masterPort, matching, &slot_iterator);
1214 if (kr != kIOReturnSuccess) {
1215 SCLog(TRUE, LOG_DEBUG, CFSTR("pci_port IOServiceGetMatchingServices() failed, kr = 0x%x"), kr);
1216 return MACH_PORT_NULL;
1217 }
1218
1219 port_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1220
1221 while ((slot = IOIteratorNext(slot_iterator)) != MACH_PORT_NULL) {
1222 io_registry_entry_t child;
1223 io_iterator_t child_iterator = MACH_PORT_NULL;
1224
1225 kr = IORegistryEntryCreateIterator(slot,
1226 kIOServicePlane,
1227 kIORegistryIterateRecursively,
1228 &child_iterator);
1229 if (kr != kIOReturnSuccess) {
1230 SCLog(TRUE, LOG_DEBUG, CFSTR("pci_port IORegistryEntryCreateIterator() failed, kr = 0x%x"), kr);
1231 CFRelease(port_names);
1232 return MACH_PORT_NULL;
1233 }
1234
1235 while ((child = IOIteratorNext(child_iterator)) != MACH_PORT_NULL) {
1236 if (IOObjectConformsTo(child, kIONetworkInterfaceClass)) {
1237 CFStringRef if_bsdName;
1238
1239 if_bsdName = IORegistryEntryCreateCFProperty(child,
1240 CFSTR(kIOBSDNameKey),
1241 NULL,
1242 0);
1243 if (if_bsdName != NULL) {
1244 CFArrayAppendValue(port_names, if_bsdName);
1245 CFRelease(if_bsdName);
1246 }
1247 }
1248 IOObjectRelease(child);
1249 }
1250 IOObjectRelease(child_iterator);
1251 IOObjectRelease(slot);
1252 }
1253 IOObjectRelease(slot_iterator);
1254
1255 n = CFArrayGetCount(port_names);
1256 if (n > 1) {
1257 CFArraySortValues(port_names, CFRangeMake(0, n), compare_bsdNames, NULL);
1258 n = CFArrayGetFirstIndexOfValue(port_names, CFRangeMake(0, n), bsdName);
1259 if (n != kCFNotFound) {
1260 port_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), n + 1);
1261 }
1262 }
1263
1264 CFRelease(port_names);
1265 return port_name;
1266 }
1267
1268
1269 static Boolean
1270 pci_slot_info(io_registry_entry_t interface, CFStringRef *slot_name, CFStringRef *port_name)
1271 {
1272 CFStringRef bsd_name;
1273 Boolean ok = FALSE;
1274 CFTypeRef pci_slot_name;
1275
1276 *slot_name = NULL;
1277 *port_name = NULL;
1278
1279 bsd_name = IORegistryEntryCreateCFProperty(interface, CFSTR(kIOBSDNameKey), NULL, 0);
1280 if (bsd_name == NULL) {
1281 return FALSE;
1282 }
1283
1284 *slot_name = pci_slot(interface, &pci_slot_name);
1285 if (*slot_name != NULL) {
1286 if (pci_slot_name != NULL) {
1287 *port_name = pci_port(pci_slot_name, bsd_name);
1288 CFRelease(pci_slot_name);
1289 }
1290 ok = TRUE;
1291 }
1292
1293 CFRelease(bsd_name);
1294 return ok;
1295 }
1296
1297
1298 static Boolean
1299 isBuiltin(io_registry_entry_t interface)
1300 {
1301 CFStringRef slot;
1302
1303 slot = pci_slot(interface, NULL);
1304 if (slot != NULL) {
1305 // interfaces which have a "slot" are not built-in
1306 CFRelease(slot);
1307 return FALSE;
1308 }
1309
1310 return TRUE;
1311 }
1312
1313
1314 static Boolean
1315 isBluetoothBuiltin(Boolean *haveController)
1316 {
1317 Boolean builtin = FALSE;
1318 io_object_t hciController;
1319 io_iterator_t iter = MACH_PORT_NULL;
1320 kern_return_t kr;
1321
1322 kr = IOServiceGetMatchingServices(masterPort,
1323 IOServiceMatching("IOBluetoothHCIController"),
1324 &iter);
1325 if ((kr != kIOReturnSuccess) || (iter == MACH_PORT_NULL)) {
1326 if (kr != kIOReturnSuccess) {
1327 SCLog(TRUE, LOG_DEBUG, CFSTR("isBluetoothBuiltin IOServiceGetMatchingServices() failed, kr = 0x%x"), kr);
1328 }
1329 *haveController = FALSE;
1330 return FALSE;
1331 }
1332 *haveController = TRUE;
1333
1334 hciController = IOIteratorNext(iter);
1335 IOObjectRelease(iter);
1336 if(hciController != MACH_PORT_NULL) {
1337 CFNumberRef idVendor;
1338
1339 idVendor = IORegistryEntryCreateCFProperty(hciController, CFSTR(kUSBVendorID), NULL, 0);
1340 if (idVendor != NULL) {
1341 int idVendorVal;
1342
1343 if (isA_CFNumber(idVendor) &&
1344 CFNumberGetValue(idVendor, kCFNumberIntType, &idVendorVal) &&
1345 (idVendorVal == kIOUSBVendorIDAppleComputer)) {
1346 builtin = TRUE;
1347 }
1348
1349 CFRelease(idVendor);
1350 }
1351
1352 IOObjectRelease(hciController);
1353 }
1354
1355 return builtin;
1356 }
1357
1358
1359 #pragma mark -
1360 #pragma mark Interface enumeration
1361
1362
1363 typedef Boolean (*processInterface)(SCNetworkInterfacePrivateRef interfacePrivate,
1364 io_registry_entry_t interface,
1365 CFDictionaryRef interface_dict,
1366 io_registry_entry_t controller,
1367 CFDictionaryRef controller_dict,
1368 io_registry_entry_t bus,
1369 CFDictionaryRef bus_dict);
1370
1371
1372 static Boolean
1373 processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate,
1374 io_registry_entry_t interface,
1375 CFDictionaryRef interface_dict,
1376 io_registry_entry_t controller,
1377 CFDictionaryRef controller_dict,
1378 io_registry_entry_t bus,
1379 CFDictionaryRef bus_dict)
1380 {
1381 CFDataRef data;
1382 int ift = -1;
1383 int iVal;
1384 CFNumberRef num;
1385 CFStringRef str;
1386 CFBooleanRef val;
1387
1388 // interface type
1389 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType));
1390 if (isA_CFNumber(num) &&
1391 CFNumberGetValue(num, kCFNumberIntType, &ift)) {
1392 interfacePrivate->type = CFRetain(num);
1393 } else {
1394 SCLog(TRUE, LOG_DEBUG, CFSTR("processNetworkInterface() failed, no interface type"));
1395 return FALSE;
1396 }
1397
1398 switch (ift) {
1399 case IFT_ETHER :
1400 // Type, Hardware
1401
1402 if ((IOObjectConformsTo(controller, "IO80211Controller")) ||
1403 (IOObjectConformsTo(controller, "AirPortPCI" )) ||
1404 (IOObjectConformsTo(controller, "AirPortDriver" ))) {
1405 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
1406 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1407 interfacePrivate->sort_order = kSortAirPort;
1408 } else if (IOObjectConformsTo(controller, "IOBluetoothBNEPDriver")) {
1409 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1410 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1411 interfacePrivate->sort_order = kSortBluetoothPAN;
1412 } else {
1413 str = IODictionaryCopyCFStringValue(bus_dict, CFSTR("name"));
1414 if ((str != NULL) && CFEqual(str, CFSTR("radio"))) {
1415 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; // ??
1416 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1417 interfacePrivate->sort_order = kSortOtherWireless;
1418 } else {
1419 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1420 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1421 interfacePrivate->sort_order = kSortEthernet;
1422
1423 #if !TARGET_OS_IPHONE
1424 // BOND support only enabled for ethernet devices
1425 interfacePrivate->supportsBond = TRUE;
1426 #endif // !TARGET_OS_IPHONE
1427 }
1428
1429 if (str != NULL) CFRelease(str);
1430 }
1431
1432 // check if WWAN Ethernet
1433 if (IOObjectConformsTo(controller, "AppleUSBEthernetHost")) {
1434 interfacePrivate->sort_order = kSortTethered;
1435 } else if (IOObjectConformsTo(controller, "AppleUSBCDCECMData")) {
1436 interfacePrivate->sort_order = kSortWWANEthernet;
1437 }
1438
1439 // built-in
1440 val = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOBuiltin)));
1441 if (val == NULL) {
1442 val = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOPrimaryInterface)));
1443 }
1444 if (val != NULL) {
1445 interfacePrivate->builtin = CFBooleanGetValue(val);
1446 } else {
1447 interfacePrivate->builtin = isBuiltin(interface);
1448 }
1449
1450 if (!interfacePrivate->builtin &&
1451 CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) {
1452 // always treat AirPort interfaces as built-in
1453 interfacePrivate->builtin = TRUE;
1454 }
1455
1456 // location
1457 interfacePrivate->location = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOLocation));
1458
1459 #if !TARGET_OS_IPHONE
1460 // VLAN support
1461 num = CFDictionaryGetValue(controller_dict, CFSTR(kIOFeatures));
1462 if (isA_CFNumber(num) &&
1463 CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
1464 if (iVal & (kIONetworkFeatureHardwareVlan | kIONetworkFeatureSoftwareVlan)) {
1465 interfacePrivate->supportsVLAN = TRUE;
1466 }
1467 }
1468 #endif // !TARGET_OS_IPHONE
1469
1470 // localized name
1471 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) {
1472 interfacePrivate->localized_key = CFSTR("airport");
1473 } else if (interfacePrivate->sort_order == kSortBluetoothPAN) {
1474 interfacePrivate->localized_key = CFSTR("bluetooth-pan");
1475 } else if (interfacePrivate->sort_order == kSortOtherWireless) {
1476 interfacePrivate->localized_key = CFSTR("wireless");
1477 interfacePrivate->localized_arg1 = CFRetain(CFSTR("")); // ??
1478 } else if (interfacePrivate->builtin) {
1479 if ((interfacePrivate->location == NULL) ||
1480 (CFStringGetLength(interfacePrivate->location) == 0)) {
1481 interfacePrivate->localized_key = CFSTR("ether");
1482 } else {
1483 interfacePrivate->localized_key = CFSTR("multiether");
1484 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location);
1485 }
1486 } else {
1487 CFStringRef provider;
1488
1489 // check provider class
1490 provider = IORegistryEntrySearchCFProperty(interface,
1491 kIOServicePlane,
1492 CFSTR(kIOProviderClassKey),
1493 NULL,
1494 kIORegistryIterateRecursively | kIORegistryIterateParents);
1495 if (provider != NULL) {
1496 if (CFEqual(provider, CFSTR("IOPCIDevice"))) {
1497 CFStringRef port_name;
1498 CFStringRef slot_name;
1499
1500 if (pci_slot_info(interface, &slot_name, &port_name)) {
1501 if (port_name == NULL) {
1502 interfacePrivate->localized_key = CFSTR("pci-ether");
1503 interfacePrivate->localized_arg1 = slot_name;
1504 } else {
1505 interfacePrivate->localized_key = CFSTR("pci-multiether");
1506 interfacePrivate->localized_arg1 = slot_name;
1507 interfacePrivate->localized_arg2 = port_name;
1508 }
1509 }
1510 } else if (CFEqual(provider, CFSTR("IOUSBDevice")) ||
1511 CFEqual(provider, CFSTR("IOUSBInterface"))) {
1512 // check if a "Product Name" has been provided
1513 val = IORegistryEntrySearchCFProperty(interface,
1514 kIOServicePlane,
1515 CFSTR(kIOPropertyProductNameKey),
1516 NULL,
1517 kIORegistryIterateRecursively | kIORegistryIterateParents);
1518 if (val == NULL) {
1519 // check if a "USB Product Name" has been provided
1520 val = IORegistryEntrySearchCFProperty(interface,
1521 kIOServicePlane,
1522 CFSTR(kUSBProductString),
1523 NULL,
1524 kIORegistryIterateRecursively | kIORegistryIterateParents);
1525 }
1526 if (val != NULL) {
1527 CFStringRef productName;
1528
1529 productName = IOCopyCFStringValue(val);
1530 CFRelease(val);
1531
1532 if (productName != NULL) {
1533 if (CFStringGetLength(productName) > 0) {
1534 // if we have a [somewhat reasonable?] product name
1535 if (interfacePrivate->name != NULL) {
1536 CFRelease(interfacePrivate->name);
1537 }
1538 interfacePrivate->name = CFRetain(productName);
1539 if (interfacePrivate->localized_name != NULL) {
1540 CFRelease(interfacePrivate->localized_name);
1541 }
1542 interfacePrivate->localized_name = copy_interface_string(bundle, productName, TRUE);
1543 }
1544
1545 CFRelease(productName);
1546 }
1547 } else {
1548 interfacePrivate->localized_key = CFSTR("usb-ether");
1549 interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
1550 }
1551 }
1552 CFRelease(provider);
1553 }
1554
1555 if (interfacePrivate->localized_key == NULL) {
1556 // if no provider, not a PCI device, or no slot information
1557 interfacePrivate->localized_key = CFSTR("generic-ether");
1558 interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
1559 }
1560 }
1561
1562 break;
1563 case IFT_IEEE1394 :
1564 // Type
1565 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
1566
1567 // Entity
1568 interfacePrivate->entity_type = kSCValNetInterfaceTypeFireWire;
1569
1570 // built-in
1571 interfacePrivate->builtin = isBuiltin(interface);
1572
1573 // sort order
1574 interfacePrivate->sort_order = kSortFireWire;
1575
1576 // localized name
1577 if (interfacePrivate->builtin) {
1578 interfacePrivate->localized_key = CFSTR("firewire");
1579 } else {
1580 CFStringRef slot_name;
1581
1582 slot_name = pci_slot(interface, NULL);
1583 if (slot_name != NULL) {
1584 interfacePrivate->localized_key = CFSTR("pci-firewire");
1585 interfacePrivate->localized_arg1 = slot_name;
1586 }
1587 }
1588
1589 break;
1590 default :
1591 SCLog(TRUE, LOG_DEBUG, CFSTR("processNetworkInterface() failed, unknown interface type = %d"), ift);
1592 return FALSE;
1593 }
1594
1595 // Device
1596 interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
1597
1598 // Hardware (MAC) address
1599 data = CFDictionaryGetValue(controller_dict, CFSTR(kIOMACAddress));
1600 if (isA_CFData(data)) {
1601 interfacePrivate->address = CFRetain(data);
1602 }
1603
1604 // interface unit
1605 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceUnit));
1606 if (isA_CFNumber(num) &&
1607 CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
1608 interfacePrivate->unit = CFRetain(num);
1609 }
1610
1611 return TRUE;
1612 }
1613
1614
1615 static void
1616 set_connection_script(SCNetworkInterfacePrivateRef interfacePrivate, CFStringRef script)
1617 {
1618 CFDictionaryRef dict;
1619 CFMutableDictionaryRef newDict;
1620
1621 if (interfacePrivate->overrides == NULL) {
1622 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1623 0,
1624 &kCFTypeDictionaryKeyCallBacks,
1625 &kCFTypeDictionaryValueCallBacks);
1626 }
1627
1628 dict = CFDictionaryGetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
1629 if (dict != NULL) {
1630 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
1631 } else {
1632 newDict = CFDictionaryCreateMutable(NULL,
1633 0,
1634 &kCFTypeDictionaryKeyCallBacks,
1635 &kCFTypeDictionaryValueCallBacks);
1636 }
1637 if (script != NULL) {
1638 CFDictionarySetValue(newDict, kSCPropNetModemConnectionScript, script);
1639 } else {
1640 CFDictionaryRemoveValue(newDict, kSCPropNetModemConnectionScript);
1641 }
1642 if (CFDictionaryGetCount(newDict) > 0) {
1643 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem, newDict);
1644 } else {
1645 CFDictionaryRemoveValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
1646 }
1647 CFRelease(newDict);
1648
1649 if (CFDictionaryGetCount(interfacePrivate->overrides) == 0) {
1650 CFRelease(interfacePrivate->overrides);
1651 interfacePrivate->overrides = NULL;
1652 }
1653 return;
1654 }
1655
1656
1657 static Boolean
1658 is_valid_connection_script(CFStringRef script)
1659 {
1660 char ccl[MAXPATHLEN];
1661 char path[MAXPATHLEN];
1662 NSSearchPathEnumerationState state;
1663
1664 (void) _SC_cfstring_to_cstring(script,
1665 ccl,
1666 sizeof(ccl),
1667 kCFStringEncodingUTF8);
1668
1669 state = NSStartSearchPathEnumeration(NSLibraryDirectory,
1670 NSLocalDomainMask|NSSystemDomainMask);
1671 while ((state = NSGetNextSearchPathEnumeration(state, path))) {
1672 size_t n;
1673 struct stat statBuf;
1674
1675 if (ccl[0] == '/') {
1676 path[0] = '\0'; // if modemCCL is a full path
1677 } else {
1678 strlcat(path, "/Modem Scripts/", sizeof(path));
1679 }
1680 strlcat(path, ccl, sizeof(path));
1681
1682 if (stat(path, &statBuf) != 0) {
1683 if (errno == ENOENT) {
1684 goto bundle;
1685 }
1686
1687 SCLog(TRUE, LOG_DEBUG,
1688 CFSTR("processSerialInterface stat() failed: %s"),
1689 strerror(errno));
1690 continue;
1691 }
1692 if (S_ISREG(statBuf.st_mode)) {
1693 // if we have a valid CCL script
1694 return TRUE;
1695 }
1696
1697 #define BUNDLE_EXT ".ccl"
1698 #define BUNDLE_EXT_LEN sizeof(BUNDLE_EXT) - 1
1699
1700 bundle :
1701
1702 n = strlen(path);
1703 if ((n <= BUNDLE_EXT_LEN) ||
1704 (strstr(&path[n - BUNDLE_EXT_LEN], BUNDLE_EXT) == NULL)) {
1705 strlcat(path, BUNDLE_EXT, sizeof(path));
1706 if (stat(path, &statBuf) != 0) {
1707 if (errno == ENOENT) {
1708 continue;
1709 }
1710
1711 SCLog(TRUE, LOG_DEBUG,
1712 CFSTR("processSerialInterface stat() failed: %s"),
1713 strerror(errno));
1714 continue;
1715 }
1716 }
1717 if (S_ISDIR(statBuf.st_mode)) {
1718 // if we have a valid CCL bundle
1719 return TRUE;
1720 }
1721 }
1722
1723 return FALSE;
1724 }
1725
1726
1727 static Boolean
1728 processSerialInterface(SCNetworkInterfacePrivateRef interfacePrivate,
1729 io_registry_entry_t interface,
1730 CFDictionaryRef interface_dict,
1731 io_registry_entry_t controller,
1732 CFDictionaryRef controller_dict,
1733 io_registry_entry_t bus,
1734 CFDictionaryRef bus_dict)
1735 {
1736 CFStringRef base = NULL;
1737 CFStringRef ift;
1738 Boolean isModem = FALSE;
1739 Boolean isWWAN = FALSE;
1740 CFStringRef modemCCL = NULL;
1741 Boolean ok = FALSE;
1742 CFTypeRef val;
1743
1744 // check if hidden
1745 val = IORegistryEntrySearchCFProperty(interface,
1746 kIOServicePlane,
1747 CFSTR("HiddenPort"),
1748 NULL,
1749 kIORegistryIterateRecursively | kIORegistryIterateParents);
1750 if (val != NULL) {
1751 CFRelease(val);
1752 return FALSE; // if this interface should not be exposed
1753 }
1754
1755 // check if initializing
1756 val = IORegistryEntrySearchCFProperty(interface,
1757 kIOServicePlane,
1758 CFSTR("Initializing"),
1759 NULL,
1760 kIORegistryIterateRecursively | kIORegistryIterateParents);
1761 if (val != NULL) {
1762 Boolean initializing;
1763
1764 initializing = isA_CFBoolean(val) && CFBooleanGetValue(val);
1765 CFRelease(val);
1766 if (initializing) {
1767 return FALSE; // if this interface is still initializing
1768 }
1769 }
1770
1771 // check if WWAN
1772 val = IORegistryEntrySearchCFProperty(interface,
1773 kIOServicePlane,
1774 CFSTR("WWAN"),
1775 NULL,
1776 kIORegistryIterateRecursively | kIORegistryIterateParents);
1777 if (val != NULL) {
1778 isWWAN = isA_CFBoolean(val) && CFBooleanGetValue(val);
1779 CFRelease(val);
1780 }
1781
1782 // Entity (Device)
1783 interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYDeviceKey));
1784 if (interfacePrivate->entity_device == NULL) {
1785 return FALSE;
1786 }
1787
1788 base = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYBaseNameKey));
1789 if (base == NULL) {
1790 base = CFRetain(interfacePrivate->entity_device);
1791 }
1792
1793 /*
1794 * From MoreSCF:
1795 *
1796 * Exclude ports named "irda" because otherwise the IrDA ports on the
1797 * original iMac (rev's A through D) show up as serial ports. Given
1798 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
1799 * even support it, these ports definitely shouldn't be listed.
1800 */
1801 if (CFStringCompare(base,
1802 CFSTR("irda"),
1803 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
1804 goto done;
1805 }
1806
1807 if (IOStringValueHasPrefix(base, CFSTR("bluetooth"))) {
1808 Boolean haveController = FALSE;
1809
1810 // Bluetooth
1811 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
1812 interfacePrivate->sort_order = kSortBluetooth;
1813 interfacePrivate->builtin = isBluetoothBuiltin(&haveController);
1814 if (!haveController) {
1815 // if device with no controller present
1816 goto done;
1817 }
1818 } else if (IOStringValueHasPrefix(base, CFSTR("irda-ircomm"))) {
1819 // IrDA
1820 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
1821 interfacePrivate->sort_order = kSortIrDA;
1822 } else if (isWWAN) {
1823 // WWAN
1824 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN;
1825 interfacePrivate->sort_order = kSortWWAN;
1826 } else {
1827 // Modem
1828 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
1829 interfacePrivate->sort_order = kSortModem;
1830
1831 // V.92 support
1832 val = IORegistryEntrySearchCFProperty(interface,
1833 kIOServicePlane,
1834 CFSTR(kIODeviceSupportsHoldKey),
1835 NULL,
1836 kIORegistryIterateRecursively | kIORegistryIterateParents);
1837 if (val != NULL) {
1838 uint32_t v92;
1839
1840 if (isA_CFNumber(val) &&
1841 CFNumberGetValue(val, kCFNumberSInt32Type, &v92)) {
1842 interfacePrivate->modemIsV92 = (v92 == 1);
1843 }
1844 CFRelease(val);
1845 }
1846 }
1847
1848 // Entity (Type)
1849 interfacePrivate->entity_type = kSCEntNetModem;
1850
1851 // Entity (Hardware)
1852 ift = CFDictionaryGetValue(interface_dict, CFSTR(kIOSerialBSDTypeKey));
1853 if (!isA_CFString(ift)) {
1854 goto done;
1855 }
1856
1857 if (CFEqual(ift, CFSTR(kIOSerialBSDModemType))) {
1858 // if modem
1859 isModem = TRUE;
1860
1861 if (CFEqual(base, CFSTR("modem"))) {
1862 interfacePrivate->builtin = TRUE;
1863 interfacePrivate->sort_order = kSortInternalModem;
1864 } else if (CFEqual(base, CFSTR("usbmodem"))) {
1865 interfacePrivate->sort_order = kSortUSBModem;
1866 }
1867 } else if (CFEqual(ift, CFSTR(kIOSerialBSDRS232Type))) {
1868 // if serial port
1869 interfacePrivate->sort_order = kSortSerialPort;
1870 } else {
1871 goto done;
1872 }
1873
1874 // configuration template overrides
1875 val = IORegistryEntrySearchCFProperty(interface,
1876 kIOServicePlane,
1877 CFSTR("DevicePPPOverrides"),
1878 NULL,
1879 kIORegistryIterateRecursively | kIORegistryIterateParents);
1880 if (val != NULL) {
1881 if (isA_CFDictionary(val)) {
1882 if (interfacePrivate->overrides == NULL) {
1883 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1884 0,
1885 &kCFTypeDictionaryKeyCallBacks,
1886 &kCFTypeDictionaryValueCallBacks);
1887 }
1888 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypePPP, val);
1889 }
1890 CFRelease(val);
1891 }
1892
1893 val = IORegistryEntrySearchCFProperty(interface,
1894 kIOServicePlane,
1895 CFSTR("DeviceModemOverrides"),
1896 NULL,
1897 kIORegistryIterateRecursively | kIORegistryIterateParents);
1898 if (val != NULL) {
1899 if (isA_CFDictionary(val)) {
1900 CFStringRef uniqueID;
1901
1902 if (interfacePrivate->overrides == NULL) {
1903 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1904 0,
1905 &kCFTypeDictionaryKeyCallBacks,
1906 &kCFTypeDictionaryValueCallBacks);
1907 }
1908 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem, val);
1909
1910 modemCCL = CFDictionaryGetValue(val, kSCPropNetModemConnectionScript);
1911 modemCCL = isA_CFString(modemCCL);
1912
1913 uniqueID = CFDictionaryGetValue(val, CFSTR("UniqueIdentifier"));
1914 uniqueID = isA_CFString(uniqueID);
1915 if (uniqueID != NULL) {
1916 // retain the device's base name and the unique id
1917 CFRelease(interfacePrivate->entity_device);
1918 interfacePrivate->entity_device = CFRetain(base);
1919 interfacePrivate->entity_device_unique = CFStringCreateCopy(NULL, uniqueID);
1920 }
1921 }
1922 CFRelease(val);
1923 }
1924
1925 // if not part of the DeviceModemOverrides, look harder for the modem CCL
1926 if (modemCCL == NULL) {
1927 val = IORegistryEntrySearchCFProperty(interface,
1928 kIOServicePlane,
1929 CFSTR("ModemCCL"),
1930 NULL,
1931 kIORegistryIterateRecursively | kIORegistryIterateParents);
1932 if (val != NULL) {
1933 modemCCL = IOCopyCFStringValue(val);
1934 if (modemCCL != NULL) {
1935 set_connection_script(interfacePrivate, modemCCL);
1936 CFRelease(modemCCL);
1937 }
1938
1939 CFRelease(val);
1940 }
1941 }
1942
1943 // localized name
1944 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIrDA)) {
1945 interfacePrivate->localized_key = CFSTR("irda");
1946 } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBluetooth)) {
1947 interfacePrivate->localized_key = CFSTR("bluetooth");
1948 } else {
1949 CFStringRef localized = NULL;
1950 CFStringRef name = NULL;
1951 CFMutableStringRef port;
1952
1953 port = CFStringCreateMutableCopy(NULL, 0, base);
1954 CFStringLowercase(port, NULL);
1955
1956 if (!isModem) {
1957 CFStringAppend(port, CFSTR("-port"));
1958 }
1959
1960 // set non-localized name
1961 if (bundle != NULL) {
1962 name = copy_interface_string(bundle, port, FALSE);
1963 }
1964 if (name != NULL) {
1965 if (!CFEqual(port, name)) {
1966 // if [English] localization available
1967 interfacePrivate->name = name;
1968 } else {
1969 // if no [English] localization available, use TTY base name
1970 CFRelease(name);
1971 interfacePrivate->name = CFStringCreateCopy(NULL, base);
1972 }
1973 } else {
1974 interfacePrivate->name = CFStringCreateCopy(NULL, base);
1975 }
1976
1977 // set localized name
1978 if (bundle != NULL) {
1979 localized = copy_interface_string(bundle, port, TRUE);
1980 }
1981 if (localized != NULL) {
1982 if (!CFEqual(port, localized)) {
1983 // if localization available
1984 interfacePrivate->localized_name = localized;
1985 } else {
1986 // if no localization available, use TTY base name
1987 CFRelease(localized);
1988 interfacePrivate->localized_name = CFStringCreateCopy(NULL, base);
1989 }
1990 } else {
1991 interfacePrivate->localized_name = CFStringCreateCopy(NULL, base);
1992 }
1993
1994 if (!isModem || !CFEqual(base, CFSTR("modem"))) {
1995 CFStringRef productName;
1996
1997 // check if a "Product Name" has been provided
1998 val = IORegistryEntrySearchCFProperty(interface,
1999 kIOServicePlane,
2000 CFSTR(kIOPropertyProductNameKey),
2001 NULL,
2002 kIORegistryIterateRecursively | kIORegistryIterateParents);
2003 if (val == NULL) {
2004 // check if a "USB Product Name" has been provided
2005 val = IORegistryEntrySearchCFProperty(interface,
2006 kIOServicePlane,
2007 CFSTR(kUSBProductString),
2008 NULL,
2009 kIORegistryIterateRecursively | kIORegistryIterateParents);
2010 }
2011 if (val != NULL) {
2012 productName = IOCopyCFStringValue(val);
2013 CFRelease(val);
2014
2015 if (productName != NULL) {
2016 if (CFStringGetLength(productName) > 0) {
2017 // if we have a [somewhat reasonable?] product name
2018 if (interfacePrivate->name != NULL) {
2019 CFRelease(interfacePrivate->name);
2020 }
2021 interfacePrivate->name = CFRetain(productName);
2022 if (interfacePrivate->localized_name != NULL) {
2023 CFRelease(interfacePrivate->localized_name);
2024 }
2025 interfacePrivate->localized_name = copy_interface_string(bundle, productName, TRUE);
2026
2027 // if not provided, also check if the product name
2028 // matches a CCL script
2029 if ((modemCCL == NULL) &&
2030 is_valid_connection_script(productName)) {
2031 set_connection_script(interfacePrivate, productName);
2032 }
2033 }
2034
2035 CFRelease(productName);
2036 }
2037 }
2038 }
2039
2040 CFRelease(port);
2041 }
2042
2043 ok = TRUE;
2044
2045 done :
2046
2047 if (!ok && (interfacePrivate->entity_device != NULL)) {
2048 CFRelease(interfacePrivate->entity_device);
2049 interfacePrivate->entity_device = NULL;
2050 }
2051 if (base != NULL) CFRelease(base);
2052
2053 return ok;
2054 }
2055
2056
2057 static SCNetworkInterfaceRef
2058 createInterface(io_registry_entry_t interface, processInterface func)
2059 {
2060 io_registry_entry_t bus = MACH_PORT_NULL;
2061 CFMutableDictionaryRef bus_dict = NULL;
2062 io_registry_entry_t controller = MACH_PORT_NULL;
2063 CFMutableDictionaryRef controller_dict = NULL;
2064 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
2065 CFMutableDictionaryRef interface_dict = NULL;
2066 kern_return_t kr;
2067 io_string_t path;
2068
2069 kr = IORegistryEntryGetPath(interface, kIOServicePlane, path);
2070 if (kr != kIOReturnSuccess) {
2071 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetPath() failed, kr = 0x%x"), kr);
2072 goto done;
2073 }
2074
2075 kr = IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions);
2076 if (kr != kIOReturnSuccess) {
2077 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
2078 goto done;
2079 }
2080
2081 /* get the controller node */
2082 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &controller);
2083 if (kr != KERN_SUCCESS) {
2084 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
2085 goto done;
2086 }
2087
2088 /* get the dictionary associated with the node */
2089 kr = IORegistryEntryCreateCFProperties(controller, &controller_dict, NULL, kNilOptions);
2090 if (kr != KERN_SUCCESS) {
2091 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
2092 goto done;
2093 }
2094
2095 /* get the bus node */
2096 kr = IORegistryEntryGetParentEntry(controller, kIOServicePlane, &bus);
2097 if (kr != KERN_SUCCESS) {
2098 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
2099 goto done;
2100 }
2101
2102 /* get the dictionary associated with the node */
2103 kr = IORegistryEntryCreateCFProperties(bus, &bus_dict, NULL, kNilOptions);
2104 if (kr != KERN_SUCCESS) {
2105 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
2106 goto done;
2107 }
2108
2109 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL, path);
2110
2111 if ((*func)(interfacePrivate, interface, interface_dict, controller, controller_dict, bus, bus_dict)) {
2112 CFTypeRef val;
2113
2114 /* check user-notification / auto-configuration preferences */
2115 val = IORegistryEntrySearchCFProperty(interface,
2116 kIOServicePlane,
2117 kSCNetworkInterfaceConfigurationActionKey,
2118 NULL,
2119 kIORegistryIterateRecursively | kIORegistryIterateParents);
2120 if (val != NULL) {
2121 if (isA_CFString(val)) {
2122 interfacePrivate->configurationAction = CFRetain(val);
2123 }
2124 CFRelease(val);
2125 }
2126 } else {
2127 CFRelease(interfacePrivate);
2128 interfacePrivate = NULL;
2129 }
2130
2131 done :
2132
2133 if (interface_dict != NULL) CFRelease(interface_dict);
2134
2135 if (controller != MACH_PORT_NULL) IOObjectRelease(controller);
2136 if (controller_dict != NULL) CFRelease(controller_dict);
2137
2138 if (bus != MACH_PORT_NULL) IOObjectRelease(bus);
2139 if (bus_dict != NULL) CFRelease(bus_dict);
2140
2141 return (SCNetworkInterfaceRef)interfacePrivate;
2142 }
2143
2144
2145 static CFArrayRef
2146 findMatchingInterfaces(CFDictionaryRef matching, processInterface func)
2147 {
2148 CFMutableArrayRef interfaces;
2149 io_registry_entry_t interface;
2150 kern_return_t kr;
2151 io_iterator_t iterator = MACH_PORT_NULL;
2152
2153 kr = IOServiceGetMatchingServices(masterPort, matching, &iterator);
2154 if (kr != kIOReturnSuccess) {
2155 SCLog(TRUE, LOG_DEBUG, CFSTR("findMatchingInterfaces IOServiceGetMatchingServices() failed, kr = 0x%x"), kr);
2156 return NULL;
2157 }
2158
2159 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2160
2161 while ((interface = IOIteratorNext(iterator)) != MACH_PORT_NULL) {
2162 SCNetworkInterfaceRef match;
2163
2164 match = createInterface(interface, func);
2165 if (match != NULL) {
2166 CFArrayAppendValue(interfaces, match);
2167 CFRelease(match);
2168 }
2169
2170 IOObjectRelease(interface);
2171 }
2172
2173 IOObjectRelease(iterator);
2174
2175 return interfaces;
2176 }
2177
2178
2179 #pragma mark -
2180 #pragma mark helper functions
2181
2182
2183 static CFIndex
2184 findConfiguration(CFStringRef interface_type)
2185 {
2186 CFIndex i;
2187
2188 for (i = 0; i < sizeof(configurations)/sizeof(configurations[0]); i++) {
2189 if (CFEqual(interface_type, *configurations[i].interface_type)) {
2190 return i;
2191 }
2192 }
2193
2194 return kCFNotFound;
2195 }
2196
2197
2198 __private_extern__
2199 CFStringRef
2200 __SCNetworkInterfaceGetDefaultConfigurationType(SCNetworkInterfaceRef interface)
2201 {
2202 CFIndex interfaceIndex;
2203 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2204
2205 if (interfacePrivate->serviceID == NULL) {
2206 // if not associated with a service (yet)
2207 _SCErrorSet(kSCStatusInvalidArgument);
2208 return NULL;
2209 }
2210
2211 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2212 if (interfaceIndex == kCFNotFound) {
2213 // unknown interface type, use per-service configuration preferences
2214 return interfacePrivate->interface_type; // entity
2215 }
2216
2217 if (configurations[interfaceIndex].entity_hardware != NULL) {
2218 // if configuration information can be associated with this interface type
2219 return *configurations[interfaceIndex].entity_hardware;
2220 }
2221
2222 _SCErrorSet(kSCStatusInvalidArgument);
2223 return NULL;
2224 }
2225
2226
2227 __private_extern__
2228 Boolean
2229 __SCNetworkInterfaceIsValidExtendedConfigurationType(SCNetworkInterfaceRef interface,
2230 CFStringRef extendedType,
2231 Boolean requirePerInterface)
2232 {
2233 CFStringRef defaultType;
2234 CFIndex extendedIndex;
2235 CFIndex interfaceIndex;
2236 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2237 Boolean isL2TP = FALSE;
2238 Boolean ok = FALSE;
2239
2240 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
2241 if (defaultType == NULL) {
2242 goto done;
2243 }
2244
2245 if (CFEqual(extendedType, defaultType)) {
2246 // extended and default configuration types cannot conflict
2247 goto done;
2248 }
2249
2250 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2251 if (interfaceIndex == kCFNotFound) {
2252 // configuration information for unknown interface type's
2253 // are stored along with the service and we don't allow
2254 // per-service extended configurations
2255 goto done;
2256 }
2257
2258 if (CFEqual(extendedType, kSCEntNetIPSec)) {
2259 CFStringRef interfaceType;
2260
2261 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
2262 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
2263 SCNetworkInterfaceRef child;
2264
2265 child = SCNetworkInterfaceGetInterface(interface);
2266 if (child != NULL) {
2267 interfaceType = SCNetworkInterfaceGetInterfaceType(child);
2268 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
2269 isL2TP = TRUE;
2270 }
2271 }
2272 }
2273 }
2274
2275 if (requirePerInterface &&
2276 !configurations[interfaceIndex].per_interface_config &&
2277 !isL2TP) {
2278 // we don't allow per-service extended configurations (except
2279 // that we do allow IPSec as an extended type for PPP->L2TP)
2280 goto done;
2281 }
2282
2283 extendedIndex = findConfiguration(extendedType);
2284 if ((extendedIndex != kCFNotFound) && !isL2TP) {
2285 // extended type cannot match a known interface type (except
2286 // that we do allow IPSec as an extended type for PPP->L2TP)
2287 goto done;
2288 }
2289
2290 /*
2291 * ???
2292 * Do we match specific/known extended configuration types (e.g. EAPOL)
2293 * and ensure that any non-standard extended configuration types be of
2294 * the form com.myCompany.myType?
2295 * ???
2296 */
2297
2298 ok = TRUE;
2299
2300 done :
2301
2302 if (!ok) {
2303 _SCErrorSet(kSCStatusInvalidArgument);
2304 }
2305 return ok;
2306 }
2307
2308
2309 typedef struct {
2310 CFStringRef defaultType;
2311 CFMutableArrayRef types;
2312 } extendedConfiguration, *extendedConfigurationRef;
2313
2314
2315 static void
2316 __addExtendedConfigurationType(const void *key, const void *value, void *context)
2317 {
2318 CFStringRef extendedType = (CFStringRef)key;
2319 extendedConfigurationRef myContextRef = (extendedConfigurationRef)context;
2320
2321 if (CFEqual(extendedType, myContextRef->defaultType)) {
2322 // do not include the default configuration type
2323 return;
2324 }
2325
2326 if (CFArrayContainsValue(myContextRef->types,
2327 CFRangeMake(0, CFArrayGetCount(myContextRef->types)),
2328 extendedType)) {
2329 // if extendedType already has already been added
2330 return;
2331 }
2332
2333 CFArrayAppendValue(myContextRef->types, extendedType);
2334
2335 return;
2336 }
2337
2338
2339 static CFArrayRef
2340 extendedConfigurationTypes(SCNetworkInterfaceRef interface)
2341 {
2342 CFIndex i;
2343 CFIndex interfaceIndex;
2344 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2345 extendedConfiguration myContext;
2346 SCNetworkServiceRef service;
2347 CFArrayRef sets;
2348 CFIndex n;
2349
2350 myContext.defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
2351 if (myContext.defaultType == NULL) {
2352 myContext.types = NULL;
2353 goto done;
2354 }
2355
2356 myContext.types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2357
2358 if (interfacePrivate->serviceID == NULL) {
2359 // if not associated with a service (yet)
2360 goto done;
2361 }
2362
2363 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2364 if (interfaceIndex == kCFNotFound) {
2365 // we don't allow per-service extended configurations
2366 goto done;
2367 }
2368
2369 if (!configurations[interfaceIndex].per_interface_config) {
2370 // known interface type but we still don't allow
2371 // per-service extended configurations
2372 goto done;
2373 }
2374
2375 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
2376 interfacePrivate->prefs,
2377 interfacePrivate->serviceID,
2378 interface);
2379
2380 sets = SCNetworkSetCopyAll(interfacePrivate->prefs);
2381 n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
2382
2383 for (i = 0; i < n; i++) {
2384 CFDictionaryRef configs;
2385 Boolean found;
2386 CFStringRef path;
2387 CFArrayRef services;
2388 SCNetworkSetRef set;
2389
2390 set = CFArrayGetValueAtIndex(sets, i);
2391 services = SCNetworkSetCopyServices(set);
2392 found = CFArrayContainsValue(services,
2393 CFRangeMake(0, CFArrayGetCount(services)),
2394 service);
2395 CFRelease(services);
2396
2397 if (!found) {
2398 continue;
2399 }
2400
2401 // add stored extended configuration types
2402 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
2403 SCNetworkSetGetSetID(set), // set
2404 interfacePrivate->entity_device, // service
2405 NULL); // entity
2406 configs = __getPrefsConfiguration(interfacePrivate->prefs, path);
2407 CFRelease(path);
2408 if (isA_CFDictionary(configs)) {
2409 CFDictionaryApplyFunction(configs,
2410 __addExtendedConfigurationType,
2411 &myContext);
2412 }
2413
2414 // add not-yet-stored extended configuration types
2415 if (interfacePrivate->unsaved != NULL) {
2416 CFDictionaryApplyFunction(interfacePrivate->unsaved,
2417 __addExtendedConfigurationType,
2418 &myContext);
2419 }
2420
2421 break;
2422 }
2423
2424 CFRelease(service);
2425 if (sets != NULL) CFRelease(sets);
2426
2427 done :
2428
2429 return myContext.types;
2430 }
2431
2432
2433 static CFArrayRef
2434 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate,
2435 CFStringRef extendedType)
2436 {
2437 CFMutableArrayRef array;
2438 CFIndex i;
2439 CFIndex interfaceIndex;
2440 CFIndex n;
2441 CFStringRef path;
2442 SCNetworkServiceRef service;
2443 CFArrayRef sets;
2444
2445 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2446
2447 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2448 if (interfaceIndex == kCFNotFound) {
2449 // unknown interface type, use per-service configuration preferences
2450 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
2451 interfacePrivate->serviceID, // service
2452 extendedType); // entity
2453 CFArrayAppendValue(array, path);
2454 CFRelease(path);
2455 return array;
2456 }
2457
2458 if (!configurations[interfaceIndex].per_interface_config) {
2459 // known interface type, per-service configuration preferences
2460 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
2461 interfacePrivate->serviceID, // service
2462 extendedType); // entity
2463 CFArrayAppendValue(array, path);
2464 CFRelease(path);
2465 return array;
2466 }
2467
2468 // known interface type, per-interface configuration preferences
2469 //
2470 // 1. look for all sets which contain the associated service
2471 // 2. add a per-set path for the interface configuration for
2472 // each set.
2473
2474 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
2475 interfacePrivate->prefs,
2476 interfacePrivate->serviceID,
2477 (SCNetworkInterfaceRef)interfacePrivate);
2478
2479 sets = SCNetworkSetCopyAll(interfacePrivate->prefs);
2480 n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
2481
2482 for (i = 0; i < n; i++) {
2483 CFArrayRef services;
2484 SCNetworkSetRef set;
2485
2486 set = CFArrayGetValueAtIndex(sets, i);
2487 services = SCNetworkSetCopyServices(set);
2488 if (CFArrayContainsValue(services,
2489 CFRangeMake(0, CFArrayGetCount(services)),
2490 service)) {
2491 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
2492 SCNetworkSetGetSetID(set), // set
2493 interfacePrivate->entity_device, // service
2494 extendedType); // entity
2495 CFArrayAppendValue(array, path);
2496 CFRelease(path);
2497 }
2498 CFRelease(services);
2499 }
2500
2501 if (CFArrayGetCount(array) == 0) {
2502 CFRelease(array);
2503 array = NULL;
2504 }
2505
2506 CFRelease(service);
2507 if (sets != NULL) CFRelease(sets);
2508 return array;
2509 }
2510
2511
2512 #pragma mark -
2513 #pragma mark SCNetworkInterface <--> preferences entity
2514
2515
2516 __private_extern__
2517 CFDictionaryRef
2518 __SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface)
2519 {
2520 CFMutableDictionaryRef entity;
2521 CFIndex interfaceIndex;
2522 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2523
2524 entity = CFDictionaryCreateMutable(NULL,
2525 0,
2526 &kCFTypeDictionaryKeyCallBacks,
2527 &kCFTypeDictionaryValueCallBacks);
2528 if (interfacePrivate->entity_type != NULL) {
2529 CFDictionarySetValue(entity,
2530 kSCPropNetInterfaceType,
2531 interfacePrivate->entity_type);
2532 }
2533 if (interfacePrivate->entity_subtype != NULL) {
2534 CFDictionarySetValue(entity,
2535 kSCPropNetInterfaceSubType,
2536 interfacePrivate->entity_subtype);
2537 }
2538 if (interfacePrivate->entity_device != NULL) {
2539 CFDictionarySetValue(entity,
2540 kSCPropNetInterfaceDeviceName,
2541 interfacePrivate->entity_device);
2542 }
2543 if (interfacePrivate->entity_device_unique != NULL) {
2544 CFDictionarySetValue(entity,
2545 CFSTR("DeviceUniqueIdentifier"),
2546 interfacePrivate->entity_device_unique);
2547 }
2548
2549 // match the "hardware" with the lowest layer
2550 while (TRUE) {
2551 SCNetworkInterfaceRef nextInterface;
2552
2553 nextInterface = SCNetworkInterfaceGetInterface(interface);
2554 if (nextInterface == NULL) {
2555 break;
2556 }
2557
2558 interface = nextInterface;
2559 }
2560 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2561
2562 if (CFEqual(interface, kSCNetworkInterfaceIPv4)) {
2563 return entity;
2564 }
2565
2566 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2567 if (interfaceIndex != kCFNotFound) {
2568 if (configurations[interfaceIndex].entity_hardware != NULL) {
2569 CFDictionarySetValue(entity,
2570 kSCPropNetInterfaceHardware,
2571 *configurations[interfaceIndex].entity_hardware);
2572 }
2573 } else {
2574 CFDictionarySetValue(entity,
2575 kSCPropNetInterfaceHardware,
2576 interfacePrivate->interface_type);
2577 }
2578
2579 // add the localized display name (which will only be used when/if the
2580 // interface is removed from the system)
2581 CFDictionarySetValue(entity,
2582 kSCPropUserDefinedName,
2583 SCNetworkInterfaceGetLocalizedDisplayName(interface));
2584
2585 // note that this is a V.92 capable modem
2586 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeModem) &&
2587 interfacePrivate->modemIsV92) {
2588 int one = 1;
2589 CFNumberRef num;
2590
2591 num = CFNumberCreate(NULL, kCFNumberIntType, &one);
2592 CFDictionarySetValue(entity,
2593 kSCPropNetInterfaceSupportsModemOnHold,
2594 num);
2595 CFRelease(num);
2596 }
2597
2598 return entity;
2599 }
2600
2601
2602 #if !TARGET_OS_IPHONE
2603 static SCNetworkInterfaceRef
2604 findInterface(CFArrayRef interfaces, CFStringRef match_if)
2605 {
2606 CFIndex i;
2607 CFIndex n;
2608
2609 n = CFArrayGetCount(interfaces);
2610 for (i = 0; i < n; i++) {
2611 SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(interfaces, i);
2612 CFStringRef interfaceName;
2613
2614 interfaceName = SCNetworkInterfaceGetBSDName(interface);
2615 if ((interfaceName != NULL) && CFEqual(interfaceName, match_if)) {
2616 CFRetain(interface);
2617 return interface;
2618 }
2619 }
2620
2621 return NULL;
2622 }
2623
2624
2625 static SCNetworkInterfaceRef
2626 findBondInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
2627 {
2628 CFArrayRef bonds;
2629 SCNetworkInterfaceRef interface = NULL;
2630
2631 if (prefs == NULL) {
2632 return (NULL);
2633 }
2634
2635 // check if the interface is an Ethernet Bond
2636 bonds = SCBondInterfaceCopyAll(prefs);
2637 if (bonds != NULL) {
2638 interface = findInterface(bonds, ifDevice);
2639 CFRelease(bonds);
2640 }
2641 return interface;
2642 }
2643
2644 static SCNetworkInterfaceRef
2645 findVLANInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
2646 {
2647 SCNetworkInterfaceRef interface = NULL;
2648 CFArrayRef vlans;
2649
2650 if (prefs == NULL) {
2651 return (NULL);
2652 }
2653
2654 // check if the interface is a VLAN
2655 vlans = SCVLANInterfaceCopyAll(prefs);
2656 if (vlans != NULL) {
2657 interface = findInterface(vlans, ifDevice);
2658 CFRelease(vlans);
2659 }
2660 return interface;
2661 }
2662 #endif // !TARGET_OS_IPHONE
2663
2664
2665 SCNetworkInterfaceRef
2666 _SCNetworkInterfaceCreateWithBSDName(CFAllocatorRef allocator,
2667 CFStringRef bsdName,
2668 UInt32 flags)
2669 {
2670 CFMutableDictionaryRef entity;
2671 SCNetworkInterfaceRef interface;
2672
2673 entity = CFDictionaryCreateMutable(NULL,
2674 0,
2675 &kCFTypeDictionaryKeyCallBacks,
2676 &kCFTypeDictionaryValueCallBacks);
2677 CFDictionarySetValue(entity, kSCPropNetInterfaceDeviceName, bsdName);
2678 #if !TARGET_OS_IPHONE
2679 if ((flags & kIncludeBondInterfaces) == 0) {
2680 CFDictionarySetValue(entity, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue);
2681 }
2682 if ((flags & kIncludeVLANInterfaces) == 0) {
2683 CFDictionarySetValue(entity, CFSTR("_NO_VLAN_INTERFACES_"), kCFBooleanTrue);
2684 }
2685 #endif // !TARGET_OS_IPHONE
2686 interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL);
2687 CFRelease(entity);
2688
2689 return interface;
2690 }
2691
2692
2693 static void
2694 __SCNetworkInterfaceSetService(SCNetworkInterfaceRef interface,
2695 SCNetworkServiceRef service)
2696 {
2697 SCNetworkInterfacePrivateRef interfacePrivate;
2698 SCNetworkServicePrivateRef servicePrivate;
2699
2700 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2701 if (interfacePrivate->prefs != NULL) {
2702 CFRelease(interfacePrivate->prefs);
2703 interfacePrivate->prefs = NULL;
2704 }
2705 if (interfacePrivate->serviceID != NULL) {
2706 CFRelease(interfacePrivate->serviceID);
2707 interfacePrivate->serviceID = NULL;
2708 }
2709
2710 servicePrivate = (SCNetworkServicePrivateRef)service;
2711 if (servicePrivate->prefs != NULL) {
2712 interfacePrivate->prefs = CFRetain(servicePrivate->prefs);
2713 }
2714 if (servicePrivate->serviceID != NULL) {
2715 interfacePrivate->serviceID = CFRetain(servicePrivate->serviceID);
2716 }
2717
2718 return;
2719 }
2720
2721
2722 static Boolean
2723 _SCNetworkInterfaceMatchesName(CFStringRef name, CFStringRef key)
2724 {
2725 Boolean match;
2726 CFStringRef str;
2727
2728 if (bundle == NULL) {
2729 // if no bundle
2730 return FALSE;
2731 }
2732
2733 if (!isA_CFString(name)) {
2734 // if no interface "name"
2735 return FALSE;
2736 }
2737
2738 // check non-localized name for a match
2739 str = copy_interface_string(bundle, key, FALSE);
2740 if (str != NULL) {
2741 match = CFEqual(name, str);
2742 CFRelease(str);
2743 if (match) {
2744 return TRUE;
2745 }
2746 }
2747
2748 // check localized name for a match
2749 str = copy_interface_string(bundle, key, TRUE);
2750 if (str != NULL) {
2751 match = CFEqual(name, str);
2752 CFRelease(str);
2753 if (match) {
2754 return TRUE;
2755 }
2756 }
2757
2758 return FALSE;
2759 }
2760
2761
2762 SCNetworkInterfaceRef
2763 _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator,
2764 CFDictionaryRef interface_entity,
2765 SCNetworkServiceRef service)
2766 {
2767 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
2768 CFStringRef ifDevice;
2769 CFStringRef ifName = NULL;
2770 CFStringRef ifSubType;
2771 CFStringRef ifType;
2772 CFStringRef ifUnique;
2773 CFArrayRef matching_interfaces = NULL;
2774
2775 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2776 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
2777
2778 ifType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceType);
2779 if (ifType == NULL) {
2780 /*
2781 * The interface "Type" was not specified. We'll make an
2782 * assumption that this is an "Ethernet" interface. If a
2783 * real interface exists with the provided interface name
2784 * then the actual type will be set accordingly. If not, we'll
2785 * end up crafting an "Ethernet" SCNetworkInterface which
2786 * will keep the rest of the configuration APIs happy.
2787 */
2788 ifType = kSCValNetInterfaceTypeEthernet;
2789 }
2790
2791 if (!isA_CFString(ifType)) {
2792 return NULL;
2793 }
2794
2795 ifSubType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceSubType);
2796 if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2797 if (!isA_CFString(ifSubType)) {
2798 return NULL;
2799 }
2800 }
2801
2802 ifDevice = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceDeviceName);
2803 ifUnique = CFDictionaryGetValue(interface_entity, CFSTR("DeviceUniqueIdentifier"));
2804
2805 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet) ||
2806 CFEqual(ifType, kSCValNetInterfaceTypeFireWire) ||
2807 (CFEqual(ifType, kSCValNetInterfaceTypePPP) && CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE))) {
2808 char bsdName[IFNAMSIZ + 1];
2809 CFMutableDictionaryRef matching;
2810
2811 if (!isA_CFString(ifDevice)) {
2812 return NULL;
2813 }
2814
2815 if (_SC_cfstring_to_cstring(ifDevice, bsdName, sizeof(bsdName), kCFStringEncodingASCII) == NULL) {
2816 goto done;
2817 }
2818
2819 matching = IOBSDNameMatching(masterPort, 0, bsdName);
2820 if (matching == NULL) {
2821 goto done;
2822 }
2823
2824 // note: the "matching" dictionary will be consumed by the following
2825 matching_interfaces = findMatchingInterfaces(matching, processNetworkInterface);
2826
2827 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2828 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
2829 CFDictionaryRef matching;
2830 CFStringRef match_keys[2];
2831 CFStringRef match_vals[2];
2832
2833 if (!isA_CFString(ifDevice)) {
2834 return NULL;
2835 }
2836
2837 match_keys[0] = CFSTR(kIOProviderClassKey);
2838 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
2839
2840 match_keys[1] = CFSTR(kIOTTYBaseNameKey);
2841 match_vals[1] = ifDevice;
2842
2843 matching = CFDictionaryCreate(NULL,
2844 (const void **)match_keys,
2845 (const void **)match_vals,
2846 sizeof(match_keys)/sizeof(match_keys[0]),
2847 &kCFTypeDictionaryKeyCallBacks,
2848 &kCFTypeDictionaryValueCallBacks);
2849
2850 // note: the "matching" dictionary will be consumed by the following
2851 matching_interfaces = findMatchingInterfaces(matching, processSerialInterface);
2852
2853 if (ifUnique == NULL) {
2854 CFIndex n;
2855 Boolean useDeviceName = TRUE;
2856
2857 n = (matching_interfaces != NULL) ? CFArrayGetCount(matching_interfaces) : 0;
2858 if (n > 0) {
2859 CFIndex i;
2860
2861 for (i = 0; i < n; i++) {
2862 SCNetworkInterfacePrivateRef scanPrivate;
2863
2864 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i);
2865 if (scanPrivate->entity_device_unique != NULL) {
2866 useDeviceName = FALSE;
2867 break;
2868 }
2869 }
2870 }
2871
2872 if (useDeviceName) {
2873 if (matching_interfaces != NULL) {
2874 CFRelease(matching_interfaces);
2875 }
2876
2877 match_keys[1] = CFSTR(kIOTTYDeviceKey);
2878 matching = CFDictionaryCreate(NULL,
2879 (const void **)match_keys,
2880 (const void **)match_vals,
2881 sizeof(match_keys)/sizeof(match_keys[0]),
2882 &kCFTypeDictionaryKeyCallBacks,
2883 &kCFTypeDictionaryValueCallBacks);
2884
2885 // note: the "matching" dictionary will be consumed by the following
2886 matching_interfaces = findMatchingInterfaces(matching, processSerialInterface);
2887 }
2888 }
2889 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypeL2TP)) {
2890 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2891 kSCNetworkInterfaceTypeL2TP);
2892 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPTP)) {
2893 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2894 kSCNetworkInterfaceTypePPTP);
2895 } else {
2896 // XXX do we allow non-Apple variants of PPP??? XXX
2897 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2898 ifSubType);
2899 }
2900 } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) {
2901 if (!isA_CFString(ifDevice)) {
2902 return NULL;
2903 }
2904
2905 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2906 kSCNetworkInterfaceType6to4);
2907 } else if (CFEqual(ifType, kSCValNetInterfaceTypeIPSec)) {
2908 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2909 kSCNetworkInterfaceTypeIPSec);
2910 } else if ((CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) && (ifDevice == NULL)) {
2911 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2912 ifType);
2913 }
2914
2915 if (matching_interfaces != NULL) {
2916 CFIndex n;
2917 SCPreferencesRef prefs;
2918
2919 n = CFArrayGetCount(matching_interfaces);
2920 switch (n) {
2921 case 1 :
2922 interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0);
2923 if (_SC_CFEqual(ifUnique, interfacePrivate->entity_device_unique)) {
2924 // if the unique ID's match
2925 CFRetain(interfacePrivate);
2926 break;
2927 }
2928
2929 interfacePrivate = NULL;
2930 // fall through
2931 case 0 :
2932 if (!CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
2933 break;
2934 }
2935 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), NULL);
2936 if (prefs == NULL) {
2937 break;
2938 }
2939 #if !TARGET_OS_IPHONE
2940 if (!CFDictionaryContainsKey(interface_entity, CFSTR("_NO_VLAN_INTERFACES_"))) {
2941 interfacePrivate = (SCNetworkInterfacePrivateRef)findVLANInterface(prefs, ifDevice);
2942 }
2943 if ((interfacePrivate == NULL)
2944 && !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BOND_INTERFACES_"))) {
2945 interfacePrivate = (SCNetworkInterfacePrivateRef)findBondInterface(prefs, ifDevice);
2946 }
2947 #endif // !TARGET_OS_IPHONE
2948 CFRelease(prefs);
2949 break;
2950 default :
2951 if (ifUnique != NULL) {
2952 CFIndex i;
2953
2954 // we are looking for an interface with a unique ID
2955 // so let's try to focus our choices
2956 for (i = 0; i < n; i++) {
2957 SCNetworkInterfacePrivateRef scanPrivate;
2958
2959 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i);
2960 if (_SC_CFEqual(ifUnique, scanPrivate->entity_device_unique)) {
2961 if (interfacePrivate != NULL) {
2962 // if we've matched more than one interface
2963 interfacePrivate = NULL;
2964 break;
2965 }
2966 interfacePrivate = scanPrivate;
2967 }
2968 }
2969 } else if (CFDictionaryGetValueIfPresent(interface_entity,
2970 kSCPropUserDefinedName,
2971 (const void **)&ifName)) {
2972 CFIndex i;
2973
2974 // we don't have a unique ID but do have an interface
2975 // name. If the matching interfaces do have IDs than
2976 // we can try to focus our choices using the name
2977 for (i = 0; i < n; i++) {
2978 SCNetworkInterfacePrivateRef scanPrivate;
2979
2980 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i);
2981 if (scanPrivate->entity_device_unique != NULL) {
2982 SCNetworkInterfaceRef scan = (SCNetworkInterfaceRef)scanPrivate;
2983 CFStringRef scanName;
2984
2985 scanName = __SCNetworkInterfaceGetNonLocalizedDisplayName(scan);
2986 if ((scanName != NULL) && !_SC_CFEqual(ifName, scanName)) {
2987 continue; // if not the same display name
2988 }
2989 }
2990
2991 if (interfacePrivate != NULL) {
2992 // if we've matched more than one interface
2993 interfacePrivate = NULL;
2994 break;
2995 }
2996 interfacePrivate = scanPrivate;
2997 }
2998 }
2999 if (interfacePrivate == NULL) {
3000 SCLog(TRUE, LOG_ERR, CFSTR("_SCNetworkInterfaceCreateWithEntity() failed, more than one interface matches %@"), ifDevice);
3001 interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0);
3002 }
3003 CFRetain(interfacePrivate);
3004 break;
3005 }
3006 CFRelease(matching_interfaces);
3007 }
3008
3009 done :
3010
3011 if (interfacePrivate == NULL) {
3012 /*
3013 * if device not present on this system
3014 */
3015 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL, NULL);
3016 interfacePrivate->entity_type = ifType;
3017 interfacePrivate->entity_subtype = ifSubType;
3018 interfacePrivate->entity_device = (ifDevice != NULL) ? CFStringCreateCopy(NULL, ifDevice) : NULL;
3019 interfacePrivate->entity_device_unique = (ifUnique != NULL) ? CFStringCreateCopy(NULL, ifUnique) : NULL;
3020
3021 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
3022 CFStringRef entity_hardware;
3023
3024 entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware);
3025 if (isA_CFString((entity_hardware)) &&
3026 CFEqual(entity_hardware, kSCEntNetAirPort)) {
3027 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
3028 interfacePrivate->sort_order = kSortAirPort;
3029 } else {
3030 CFStringRef name;
3031
3032 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
3033
3034 name = CFDictionaryGetValue(interface_entity, kSCPropUserDefinedName);
3035 if (_SCNetworkInterfaceMatchesName(name, CFSTR("iPhone"))) {
3036 interfacePrivate->sort_order = kSortTethered;
3037 } else if (_SCNetworkInterfaceMatchesName(name, CFSTR("bluetooth-pan"))) {
3038 interfacePrivate->sort_order = kSortBluetoothPAN;
3039 } else {
3040 interfacePrivate->sort_order = kSortEthernet;
3041 }
3042 }
3043 } else if (CFEqual(ifType, kSCValNetInterfaceTypeFireWire)) {
3044 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
3045 interfacePrivate->sort_order = kSortFireWire;
3046 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
3047 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE)) {
3048 CFStringRef entity_hardware;
3049
3050 entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware);
3051 if (isA_CFString((entity_hardware)) &&
3052 CFEqual(entity_hardware, kSCEntNetAirPort)) {
3053 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
3054 interfacePrivate->sort_order = kSortAirPort;
3055 } else {
3056 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
3057 interfacePrivate->sort_order = kSortEthernet;
3058 }
3059 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
3060 if (CFStringHasPrefix(ifDevice, CFSTR("Bluetooth"))) {
3061 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
3062 interfacePrivate->sort_order = kSortBluetooth;
3063 } else if (CFStringHasPrefix(ifDevice, CFSTR("irda"))) {
3064 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
3065 interfacePrivate->sort_order = kSortIrDA;
3066 } else if (CFStringHasPrefix(ifDevice, CFSTR("wwan"))) {
3067 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN;
3068 interfacePrivate->sort_order = kSortWWAN;
3069 } else {
3070 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
3071 interfacePrivate->sort_order = kSortModem;
3072 }
3073 } else {
3074 // PPTP, L2TP, ...
3075 CFRelease(interfacePrivate);
3076 interfacePrivate = (SCNetworkInterfacePrivateRef)kSCNetworkInterfaceIPv4;
3077 CFRetain(interfacePrivate);
3078 }
3079 } else if (CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) {
3080 // if vendor interface
3081 interfacePrivate->interface_type = ifType;
3082 } else {
3083 // if unknown interface
3084 CFRelease(interfacePrivate);
3085 interfacePrivate = NULL;
3086 }
3087 }
3088
3089 if ((interfacePrivate != NULL) && (service != NULL)) {
3090 __SCNetworkInterfaceSetService((SCNetworkInterfaceRef)interfacePrivate,
3091 service);
3092 #if !TARGET_OS_IPHONE
3093 // set prefs & serviceID to VLANs and Bonds
3094 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBond)) {
3095 CFIndex i;
3096 CFArrayRef members;
3097 CFIndex n;
3098
3099 members = SCBondInterfaceGetMemberInterfaces((SCNetworkInterfaceRef)interfacePrivate);
3100 n = (members != NULL) ? CFArrayGetCount(members) : 0;
3101 for (i = 0; i < n; i++) {
3102 SCNetworkInterfaceRef member;
3103
3104 member = CFArrayGetValueAtIndex(members, i);
3105 __SCNetworkInterfaceSetService(member, service);
3106 }
3107 } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeVLAN)) {
3108 SCNetworkInterfaceRef vlan_physical;
3109
3110 vlan_physical = SCVLANInterfaceGetPhysicalInterface((SCNetworkInterfaceRef)interfacePrivate);
3111 if (vlan_physical != NULL) {
3112 __SCNetworkInterfaceSetService(vlan_physical, service);
3113 }
3114 }
3115 #endif // !TARGET_OS_IPHONE
3116 }
3117
3118 if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
3119 SCNetworkInterfaceRef parent;
3120
3121 // create parent
3122 parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate,
3123 kSCNetworkInterfaceTypePPP);
3124 CFRelease(interfacePrivate);
3125 interfacePrivate = (SCNetworkInterfacePrivateRef)parent;
3126 }
3127
3128 return (SCNetworkInterfaceRef)interfacePrivate;
3129 }
3130
3131
3132 #pragma mark -
3133 #pragma mark SCNetworkInterface APIs
3134
3135
3136 __private_extern__
3137 CFArrayRef
3138 __SCNetworkInterfaceCopyAll_IONetworkInterface(void)
3139 {
3140 CFDictionaryRef matching;
3141 CFArrayRef new_interfaces;
3142
3143 // get Ethernet, Firewire, and AirPort interfaces
3144
3145 matching = IOServiceMatching(kIONetworkInterfaceClass);
3146 new_interfaces = findMatchingInterfaces(matching, processNetworkInterface);
3147
3148 return new_interfaces;
3149 }
3150
3151
3152 static
3153 CFArrayRef
3154 __SCNetworkInterfaceCopyAll_Modem()
3155 {
3156 CFDictionaryRef matching;
3157 CFStringRef match_keys[2];
3158 CFStringRef match_vals[2];
3159 CFArrayRef new_interfaces;
3160
3161 match_keys[0] = CFSTR(kIOProviderClassKey);
3162 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
3163
3164 match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
3165 match_vals[1] = CFSTR(kIOSerialBSDModemType);
3166
3167 matching = CFDictionaryCreate(NULL,
3168 (const void **)match_keys,
3169 (const void **)match_vals,
3170 sizeof(match_keys)/sizeof(match_keys[0]),
3171 &kCFTypeDictionaryKeyCallBacks,
3172 &kCFTypeDictionaryValueCallBacks);
3173 new_interfaces = findMatchingInterfaces(matching, processSerialInterface);
3174
3175 return new_interfaces;
3176 }
3177
3178
3179 static
3180 CFArrayRef
3181 __SCNetworkInterfaceCopyAll_RS232()
3182 {
3183 CFDictionaryRef matching;
3184 CFStringRef match_keys[2];
3185 CFStringRef match_vals[2];
3186 CFArrayRef new_interfaces;
3187
3188 match_keys[0] = CFSTR(kIOProviderClassKey);
3189 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
3190
3191 match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
3192 match_vals[1] = CFSTR(kIOSerialBSDRS232Type);
3193
3194 matching = CFDictionaryCreate(NULL,
3195 (const void **)match_keys,
3196 (const void **)match_vals,
3197 sizeof(match_keys)/sizeof(match_keys[0]),
3198 &kCFTypeDictionaryKeyCallBacks,
3199 &kCFTypeDictionaryValueCallBacks);
3200 new_interfaces = findMatchingInterfaces(matching, processSerialInterface);
3201
3202 return new_interfaces;
3203 }
3204
3205
3206 static void
3207 add_interfaces(CFMutableArrayRef all_interfaces, CFArrayRef new_interfaces)
3208 {
3209 CFIndex i;
3210 CFIndex n;
3211
3212 n = CFArrayGetCount(new_interfaces);
3213 for (i = 0; i < n; i++) {
3214 CFStringRef bsdName;
3215 SCNetworkInterfaceRef interface;
3216
3217 interface = CFArrayGetValueAtIndex(new_interfaces, i);
3218 bsdName = SCNetworkInterfaceGetBSDName(interface);
3219 if (bsdName != NULL) {
3220 CFArrayAppendValue(all_interfaces, interface);
3221 }
3222 }
3223
3224 return;
3225 }
3226
3227
3228 static void
3229 __waitForInterfaces()
3230 {
3231 CFStringRef key;
3232 CFArrayRef keys;
3233 Boolean ok;
3234 SCDynamicStoreRef store;
3235
3236 store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL, NULL);
3237 if (store == NULL) {
3238 return;
3239 }
3240
3241 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin);
3242 keys = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
3243 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
3244 CFRelease(keys);
3245 if (!ok) {
3246 SCLog(TRUE, LOG_ERR,
3247 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"), SCErrorString(SCError()));
3248 goto done;
3249 }
3250
3251 while (TRUE) {
3252 CFArrayRef changedKeys;
3253 CFDictionaryRef dict;
3254 Boolean quiet = FALSE;
3255
3256 // check if quiet
3257 dict = SCDynamicStoreCopyValue(store, key);
3258 if (dict != NULL) {
3259 if (isA_CFDictionary(dict) &&
3260 (CFDictionaryContainsKey(dict, CFSTR("*QUIET*")) ||
3261 CFDictionaryContainsKey(dict, CFSTR("*TIMEOUT*")))) {
3262 quiet = TRUE;
3263 }
3264 CFRelease(dict);
3265 }
3266 if (quiet) {
3267 break;
3268 }
3269
3270 ok = SCDynamicStoreNotifyWait(store);
3271 if (!ok) {
3272 SCLog(TRUE, LOG_ERR,
3273 CFSTR("SCDynamicStoreNotifyWait() failed: %s"), SCErrorString(SCError()));
3274 goto done;
3275 }
3276
3277 changedKeys = SCDynamicStoreCopyNotifiedKeys(store);
3278 if (changedKeys != NULL) {
3279 CFRelease(changedKeys);
3280 }
3281 }
3282
3283 done :
3284
3285 CFRelease(key);
3286 CFRelease(store);
3287 return;
3288 }
3289
3290
3291 CFArrayRef /* of SCNetworkInterfaceRef's */
3292 SCNetworkInterfaceCopyAll()
3293 {
3294 CFMutableArrayRef all_interfaces;
3295 CFArrayRef new_interfaces;
3296 #if !TARGET_OS_IPHONE
3297 SCPreferencesRef prefs;
3298 #endif // !TARGET_OS_IPHONE
3299
3300 /* initialize runtime */
3301 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3302
3303 /* wait for IOKit to quiesce */
3304 pthread_once(&iokit_quiet, __waitForInterfaces);
3305
3306 all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3307
3308 // get Ethernet, Firewire, and AirPort interfaces
3309 new_interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
3310 if (new_interfaces != NULL) {
3311 add_interfaces(all_interfaces, new_interfaces);
3312 CFRelease(new_interfaces);
3313 }
3314
3315 // get Modem interfaces
3316 new_interfaces = __SCNetworkInterfaceCopyAll_Modem();
3317 if (new_interfaces != NULL) {
3318 add_interfaces(all_interfaces, new_interfaces);
3319 CFRelease(new_interfaces);
3320 }
3321
3322 // get serial (RS232) interfaces
3323 new_interfaces = __SCNetworkInterfaceCopyAll_RS232();
3324 if (new_interfaces != NULL) {
3325 add_interfaces(all_interfaces, new_interfaces);
3326 CFRelease(new_interfaces);
3327 }
3328
3329 #if !TARGET_OS_IPHONE
3330 // get virtual network interfaces (Bond, VLAN)
3331 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL);
3332 if (prefs != NULL) {
3333 new_interfaces = SCBondInterfaceCopyAll(prefs);
3334 if (new_interfaces != NULL) {
3335 add_interfaces(all_interfaces, new_interfaces);
3336 CFRelease(new_interfaces);
3337 }
3338
3339 new_interfaces = SCVLANInterfaceCopyAll(prefs);
3340 if (new_interfaces != NULL) {
3341 add_interfaces(all_interfaces, new_interfaces);
3342 CFRelease(new_interfaces);
3343 }
3344
3345 CFRelease(prefs);
3346 }
3347 #endif // !TARGET_OS_IPHONE
3348
3349 // all interfaces have been identified, order and return
3350 sort_interfaces(all_interfaces);
3351
3352 return all_interfaces;
3353 }
3354
3355
3356 CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */
3357 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface)
3358 {
3359 CFIndex i;
3360 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3361
3362 if (!isA_SCNetworkInterface(interface)) {
3363 _SCErrorSet(kSCStatusInvalidArgument);
3364 return NULL;
3365 }
3366
3367 if (interfacePrivate->supported_interface_types != NULL) {
3368 goto done;
3369 }
3370
3371 i = findConfiguration(interfacePrivate->interface_type);
3372 if (i != kCFNotFound) {
3373 if (configurations[i].supported_interfaces != doNone) {
3374 interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3375 if (configurations[i].supported_interfaces & do6to4) {
3376 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceType6to4);
3377 }
3378 if (configurations[i].supported_interfaces & doL2TP) {
3379 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeL2TP);
3380 }
3381 if (configurations[i].supported_interfaces & doPPP) {
3382 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPP);
3383 }
3384 if (configurations[i].supported_interfaces & doPPTP) {
3385 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPTP);
3386 }
3387 if (configurations[i].supported_interfaces & doIPSec) {
3388 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeIPSec);
3389 }
3390 }
3391 }
3392
3393 done :
3394
3395 return interfacePrivate->supported_interface_types;
3396 }
3397
3398
3399 CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */
3400 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface)
3401 {
3402 CFIndex i;
3403 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3404
3405 if (!isA_SCNetworkInterface(interface)) {
3406 _SCErrorSet(kSCStatusInvalidArgument);
3407 return NULL;
3408 }
3409
3410 if (interfacePrivate->supported_protocol_types != NULL) {
3411 goto done;
3412 }
3413
3414 i = findConfiguration(interfacePrivate->interface_type);
3415 if (i != kCFNotFound) {
3416 if (configurations[i].supported_protocols != doNone) {
3417 interfacePrivate->supported_protocol_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3418 #if !TARGET_OS_IPHONE
3419 if (configurations[i].supported_protocols & doAppleTalk) {
3420 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeAppleTalk);
3421 }
3422 #endif // !TARGET_OS_IPHONE
3423 if (configurations[i].supported_protocols & doDNS) {
3424 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeDNS);
3425 }
3426 if (configurations[i].supported_protocols & doIPv4) {
3427 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv4);
3428 }
3429 if (configurations[i].supported_protocols & doIPv6) {
3430 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv6);
3431 }
3432 if (configurations[i].supported_protocols & doProxies) {
3433 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeProxies);
3434 }
3435 #if !TARGET_OS_IPHONE
3436 if (configurations[i].supported_protocols & doSMB) {
3437 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeSMB);
3438 }
3439 #endif // !TARGET_OS_IPHONE
3440 }
3441 }
3442
3443 done :
3444
3445 return interfacePrivate->supported_protocol_types;
3446 }
3447
3448
3449 SCNetworkInterfaceRef
3450 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child, CFStringRef interfaceType)
3451 {
3452 SCNetworkInterfacePrivateRef childPrivate = (SCNetworkInterfacePrivateRef)child;
3453 CFIndex childIndex;
3454 SCNetworkInterfacePrivateRef parentPrivate;
3455
3456 if (!isA_SCNetworkInterface(child)) {
3457 _SCErrorSet(kSCStatusInvalidArgument);
3458 return NULL;
3459 }
3460
3461 if (!isA_CFString(interfaceType)) {
3462 _SCErrorSet(kSCStatusInvalidArgument);
3463 return NULL;
3464 }
3465
3466 childIndex = findConfiguration(childPrivate->interface_type);
3467
3468 parentPrivate = __SCNetworkInterfaceCreatePrivate(NULL,
3469 child,
3470 childPrivate->prefs,
3471 childPrivate->serviceID,
3472 NULL);
3473 if (parentPrivate == NULL) {
3474 _SCErrorSet(kSCStatusFailed);
3475 return NULL;
3476 }
3477
3478 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
3479 parentPrivate->interface_type = kSCNetworkInterfaceTypePPP;
3480 parentPrivate->entity_type = kSCValNetInterfaceTypePPP;
3481
3482 // entity subtype
3483 if (childIndex != kCFNotFound) {
3484 if (configurations[childIndex].ppp_subtype != NULL) {
3485 parentPrivate->entity_subtype = *configurations[childIndex].ppp_subtype;
3486 } else {
3487 // sorry, the child interface does not support PPP
3488 goto fail;
3489 }
3490 } else {
3491 // if the child's interface type not known, use the child entities "Type"
3492 parentPrivate->entity_subtype = childPrivate->entity_type;
3493 }
3494
3495 if (childPrivate->entity_device != NULL) {
3496 parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device);
3497 }
3498
3499 if (childPrivate->entity_device_unique != NULL) {
3500 parentPrivate->entity_device_unique = CFStringCreateCopy(NULL, childPrivate->entity_device_unique);
3501 }
3502 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
3503 if ((childIndex == kCFNotFound) ||
3504 ((configurations[childIndex].supported_interfaces & doL2TP) != doL2TP)) {
3505 // if the child interface does not support L2TP
3506 goto fail;
3507 }
3508 parentPrivate->interface_type = kSCNetworkInterfaceTypeL2TP;
3509 parentPrivate->localized_key = CFSTR("l2tp");
3510 parentPrivate->entity_type = kSCEntNetL2TP; // interface config goes into "L2TP"
3511 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) {
3512 if ((childIndex == kCFNotFound) ||
3513 ((configurations[childIndex].supported_interfaces & doPPTP) != doPPTP)) {
3514 // if the child interface does not support PPTP
3515 goto fail;
3516 }
3517 parentPrivate->interface_type = kSCNetworkInterfaceTypePPTP;
3518 parentPrivate->localized_key = CFSTR("pptp");
3519 parentPrivate->entity_type = kSCEntNetPPTP; // interface config goes into "PPTP"
3520 } else if (CFEqual(interfaceType, kSCNetworkInterfaceType6to4)) {
3521 if ((childIndex == kCFNotFound) ||
3522 ((configurations[childIndex].supported_interfaces & do6to4) != do6to4)) {
3523 // if the child interface does not support 6to4
3524 goto fail;
3525 }
3526
3527 parentPrivate->interface_type = kSCNetworkInterfaceType6to4;
3528 parentPrivate->localized_key = CFSTR("6to4");
3529 parentPrivate->entity_type = kSCValNetInterfaceType6to4;
3530 parentPrivate->entity_device = CFRetain(CFSTR("stf0"));
3531 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) {
3532 if ((childIndex == kCFNotFound) ||
3533 ((configurations[childIndex].supported_interfaces & doIPSec) != doIPSec)) {
3534 // if the child interface does not support IPSec
3535 goto fail;
3536 }
3537 parentPrivate->interface_type = kSCNetworkInterfaceTypeIPSec;
3538 parentPrivate->localized_key = CFSTR("ipsec");
3539 parentPrivate->entity_type = kSCValNetInterfaceTypeIPSec;
3540 } else if (CFStringFind(interfaceType, CFSTR("."), 0).location != kCFNotFound) {
3541 // if custom interface type
3542 parentPrivate->interface_type = interfaceType;
3543 parentPrivate->entity_type = interfaceType; // interface config goes into a
3544 // a dictionary with the same
3545 // name as the interfaceType
3546 } else {
3547 // unknown interface type
3548 goto fail;
3549 }
3550
3551 if (childPrivate->overrides != NULL) {
3552 parentPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, childPrivate->overrides);
3553 }
3554
3555 // The following change handles the case where a user has both an Ethernet and
3556 // PPPoE network service. Because a PPPoE service is typically associated with
3557 // an ISP we want it to be sorted higher in the service order.
3558 if ((parentPrivate->entity_subtype != NULL) &&
3559 (CFEqual(parentPrivate->entity_subtype, kSCValNetInterfaceSubTypePPPoE))) {
3560 if ((childPrivate->interface_type != NULL) &&
3561 (CFEqual(childPrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211))) {
3562 parentPrivate->sort_order = kSortAirportPPP;
3563 } else {
3564 parentPrivate->sort_order = kSortEthernetPPP;
3565 }
3566 } else {
3567 // set sort order of the parent to match the child interface
3568 parentPrivate->sort_order = childPrivate->sort_order;
3569 }
3570
3571 return (SCNetworkInterfaceRef)parentPrivate;
3572
3573 fail :
3574
3575 CFRelease(parentPrivate);
3576 _SCErrorSet(kSCStatusInvalidArgument);
3577 return NULL;
3578 }
3579
3580
3581 __private_extern__
3582 CFDictionaryRef
3583 __SCNetworkInterfaceGetDefaultConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface)
3584 {
3585 CFDictionaryRef config = NULL;
3586 CFStringRef defaultType;
3587 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3588
3589 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3590 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3591
3592 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
3593 if (defaultType != NULL) {
3594 if (set != NULL) {
3595 CFStringRef path;
3596
3597 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
3598 SCNetworkSetGetSetID(set), // set
3599 interfacePrivate->entity_device, // interface
3600 defaultType); // entity
3601 if (path != NULL) {
3602 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
3603 CFRelease(path);
3604
3605 if (config == NULL) {
3606 // if the "set" does not have a saved configuration, use
3607 // the [template] "interface" configuration
3608 if (interfacePrivate->unsaved != NULL) {
3609 config = CFDictionaryGetValue(interfacePrivate->unsaved, defaultType);
3610 if (config == (CFDictionaryRef)kCFNull) {
3611 config = NULL;
3612 }
3613 }
3614 }
3615 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
3616 config = NULL;
3617 }
3618 }
3619 }
3620 }
3621
3622 return config;
3623 }
3624
3625
3626 static CFDictionaryRef
3627 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface,
3628 CFStringRef extendedType)
3629 {
3630 CFDictionaryRef config = NULL;
3631 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3632 CFArrayRef paths;
3633
3634 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3635 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3636
3637 paths = copyConfigurationPaths(interfacePrivate, extendedType);
3638 if (paths != NULL) {
3639 CFStringRef path;
3640
3641 path = CFArrayGetValueAtIndex(paths, 0);
3642 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
3643
3644 CFRelease(paths);
3645 } else {
3646 if (interfacePrivate->unsaved != NULL) {
3647 config = CFDictionaryGetValue(interfacePrivate->unsaved, extendedType);
3648 if (config == (CFDictionaryRef)kCFNull) {
3649 config = NULL;
3650 }
3651 }
3652 }
3653
3654 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
3655 config = NULL;
3656 }
3657
3658 return config;
3659 }
3660
3661
3662 CFDictionaryRef
3663 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface)
3664 {
3665 CFDictionaryRef config;
3666 CFStringRef defaultType;
3667
3668 if (!isA_SCNetworkInterface(interface)) {
3669 _SCErrorSet(kSCStatusInvalidArgument);
3670 return NULL;
3671 }
3672
3673 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
3674 if (defaultType == NULL) {
3675 return NULL;
3676 }
3677
3678 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType);
3679 if (config == NULL) {
3680 if (CFEqual(defaultType, kSCEntNetAirPort)) {
3681 SCNetworkInterfacePrivateRef interfacePrivate;
3682 CFStringRef path;
3683
3684 // if AirPort interface, check for a per-service config
3685 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3686 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
3687 interfacePrivate->serviceID, // service
3688 kSCEntNetAirPort); // entity
3689 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
3690 CFRelease(path);
3691 }
3692 }
3693 if (config == NULL) {
3694 _SCErrorSet(kSCStatusOK);
3695 }
3696
3697 return config;
3698 }
3699
3700
3701 CFDictionaryRef
3702 SCNetworkInterfaceGetExtendedConfiguration(SCNetworkInterfaceRef interface,
3703 CFStringRef extendedType)
3704 {
3705 CFDictionaryRef config;
3706
3707 if (!isA_SCNetworkInterface(interface)) {
3708 _SCErrorSet(kSCStatusInvalidArgument);
3709 return NULL;
3710 }
3711
3712 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) {
3713 _SCErrorSet(kSCStatusInvalidArgument);
3714 return NULL;
3715 }
3716
3717 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType);
3718 if (config == NULL) {
3719 _SCErrorSet(kSCStatusOK);
3720 }
3721
3722 return config;
3723 }
3724
3725
3726 CFStringRef
3727 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface)
3728 {
3729 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3730
3731 if (!isA_SCNetworkInterface(interface)) {
3732 _SCErrorSet(kSCStatusInvalidArgument);
3733 return NULL;
3734 }
3735
3736 if ((interfacePrivate->interface != NULL) &&
3737 (interfacePrivate->interface != kSCNetworkInterfaceIPv4)) {
3738 _SCErrorSet(kSCStatusOK);
3739 return NULL;
3740 }
3741
3742 return interfacePrivate->entity_device;
3743 }
3744
3745
3746 CFStringRef
3747 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface)
3748 {
3749 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3750
3751 if (!isA_SCNetworkInterface(interface)) {
3752 _SCErrorSet(kSCStatusInvalidArgument);
3753 return NULL;
3754 }
3755
3756 if ((interfacePrivate->address != NULL) &&
3757 (interfacePrivate->addressString == NULL)) {
3758 uint8_t *bp;
3759 char *cp;
3760 CFIndex n;
3761 char mac[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
3762 char *mac_p = mac;
3763
3764 bp = (uint8_t *)CFDataGetBytePtr(interfacePrivate->address);
3765 n = CFDataGetLength(interfacePrivate->address) * 3;
3766
3767 if (n > sizeof(mac)) {
3768 mac_p = CFAllocatorAllocate(NULL, 0, n);
3769 }
3770
3771 for (cp = mac_p; n > 0; n -= 3) {
3772 cp += snprintf(cp, n, "%2.2x:", *bp++);
3773 }
3774
3775 interfacePrivate->addressString = CFStringCreateWithCString(NULL, mac_p, kCFStringEncodingUTF8);
3776 if (mac_p != mac) CFAllocatorDeallocate(NULL, mac_p);
3777 }
3778
3779 return interfacePrivate->addressString;
3780 }
3781
3782
3783 SCNetworkInterfaceRef
3784 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface)
3785 {
3786 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3787
3788 if (!isA_SCNetworkInterface(interface)) {
3789 _SCErrorSet(kSCStatusInvalidArgument);
3790 return NULL;
3791 }
3792
3793 return interfacePrivate->interface;
3794 }
3795
3796
3797 CFStringRef
3798 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface)
3799 {
3800 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3801
3802 if (!isA_SCNetworkInterface(interface)) {
3803 _SCErrorSet(kSCStatusInvalidArgument);
3804 return NULL;
3805 }
3806
3807 return interfacePrivate->interface_type;
3808 }
3809
3810
3811 static CFStringRef
3812 copy_interface_string(CFBundleRef bundle, CFStringRef key, Boolean localized)
3813 {
3814 CFStringRef str = NULL;
3815
3816 if (localized) {
3817 str = CFBundleCopyLocalizedString(bundle,
3818 key,
3819 key,
3820 NETWORKINTERFACE_LOCALIZATIONS);
3821 } else {
3822 str = _SC_CFBundleCopyNonLocalizedString(bundle,
3823 key,
3824 key,
3825 NETWORKINTERFACE_LOCALIZATIONS);
3826 }
3827
3828 return str;
3829 }
3830
3831
3832 static CFStringRef
3833 copy_display_name(SCNetworkInterfaceRef interface, Boolean localized, Boolean oldLocalization)
3834 {
3835 CFMutableStringRef local;
3836 CFStringRef name;
3837
3838 local = CFStringCreateMutable(NULL, 0);
3839
3840 while (interface != NULL) {
3841 Boolean added = FALSE;
3842 SCNetworkInterfaceRef child = NULL;
3843 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3844
3845 if ((interfacePrivate->interface != NULL) &&
3846 (interfacePrivate->interface != kSCNetworkInterfaceIPv4)) {
3847 child = interfacePrivate->interface;
3848 }
3849
3850 if ((bundle != NULL) && (interfacePrivate->localized_key != NULL)) {
3851 CFStringRef fmt;
3852 CFStringRef key = interfacePrivate->localized_key;
3853
3854 if (oldLocalization) {
3855 key = CFStringCreateWithFormat(NULL, NULL, CFSTR("X-%@"),
3856 interfacePrivate->localized_key);
3857 }
3858 fmt = copy_interface_string(bundle, key, localized);
3859 if (fmt != NULL) {
3860 CFStringAppendFormat(local,
3861 NULL,
3862 fmt,
3863 interfacePrivate->localized_arg1,
3864 interfacePrivate->localized_arg2);
3865 CFRelease(fmt);
3866 added = TRUE;
3867 }
3868 if (oldLocalization) {
3869 CFRelease(key);
3870 }
3871 }
3872
3873 if (!added &&
3874 (interfacePrivate->prefs != NULL) &&
3875 (interfacePrivate->serviceID != NULL) &&
3876 (child == NULL)) {
3877 CFDictionaryRef entity;
3878 CFStringRef path;
3879
3880 // check for (and use) the name of the interface when it
3881 // was last available
3882 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,
3883 interfacePrivate->serviceID,
3884 kSCEntNetInterface);
3885 entity = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
3886 CFRelease(path);
3887 if (isA_CFDictionary(entity)) {
3888 CFStringRef name;
3889
3890 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
3891 if (isA_CFString(name)) {
3892 CFStringAppend(local, name);
3893 added = TRUE;
3894 }
3895 }
3896 }
3897
3898 if (!added) {
3899 // create (non-)localized name based on the interface type
3900 CFStringAppend(local, interfacePrivate->interface_type);
3901
3902 // ... and, if this is a leaf node, the interface device
3903 if ((interfacePrivate->entity_device != NULL) && (child == NULL)) {
3904 CFStringAppendFormat(local, NULL, CFSTR(" (%@)"), interfacePrivate->entity_device);
3905 }
3906 }
3907
3908 if (child != NULL) {
3909 // if this interface is layered over another
3910 CFStringAppend(local, CFSTR(" --> "));
3911 }
3912
3913 interface = child;
3914 }
3915
3916 name = CFStringCreateCopy(NULL, local);
3917 CFRelease(local);
3918
3919 return name;
3920 }
3921
3922
3923 __private_extern__
3924 CFStringRef
3925 __SCNetworkInterfaceCopyXLocalizedDisplayName(SCNetworkInterfaceRef interface)
3926 {
3927 CFStringRef name;
3928
3929 if (!isA_SCNetworkInterface(interface)) {
3930 _SCErrorSet(kSCStatusInvalidArgument);
3931 return NULL;
3932 }
3933
3934 name = copy_display_name(interface, TRUE, TRUE);
3935 return name;
3936 }
3937
3938
3939 __private_extern__
3940 CFStringRef
3941 __SCNetworkInterfaceCopyXNonLocalizedDisplayName(SCNetworkInterfaceRef interface)
3942 {
3943 CFStringRef localized_name;
3944
3945 if (!isA_SCNetworkInterface(interface)) {
3946 _SCErrorSet(kSCStatusInvalidArgument);
3947 return NULL;
3948 }
3949
3950 localized_name = copy_display_name(interface, FALSE, TRUE);
3951 return localized_name;
3952 }
3953
3954
3955 __private_extern__
3956 CFStringRef
3957 __SCNetworkInterfaceGetNonLocalizedDisplayName(SCNetworkInterfaceRef interface)
3958 {
3959 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3960
3961 if (!isA_SCNetworkInterface(interface)) {
3962 _SCErrorSet(kSCStatusInvalidArgument);
3963 return NULL;
3964 }
3965
3966 if (interfacePrivate->name == NULL) {
3967 interfacePrivate->name = copy_display_name(interface, FALSE, FALSE);
3968 }
3969
3970 return interfacePrivate->name;
3971 }
3972
3973
3974 CFStringRef
3975 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface)
3976 {
3977 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3978
3979 if (!isA_SCNetworkInterface(interface)) {
3980 _SCErrorSet(kSCStatusInvalidArgument);
3981 return NULL;
3982 }
3983
3984 if (interfacePrivate->localized_name == NULL) {
3985 interfacePrivate->localized_name = copy_display_name(interface, TRUE, FALSE);
3986 }
3987
3988 return interfacePrivate->localized_name;
3989 }
3990
3991
3992 __private_extern__
3993 CFDictionaryRef
3994 __SCNetworkInterfaceGetTemplateOverrides(SCNetworkInterfaceRef interface, CFStringRef interfaceType)
3995 {
3996 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3997 CFDictionaryRef overrides = NULL;
3998
3999 if (interfacePrivate->overrides != NULL) {
4000 overrides = CFDictionaryGetValue(interfacePrivate->overrides, interfaceType);
4001 }
4002
4003 return overrides;
4004 }
4005
4006
4007 CFTypeID
4008 SCNetworkInterfaceGetTypeID(void)
4009 {
4010 pthread_once(&initialized, __SCNetworkInterfaceInitialize); /* initialize runtime */
4011 return __kSCNetworkInterfaceTypeID;
4012 }
4013
4014
4015 __private_extern__
4016 Boolean
4017 __SCNetworkInterfaceSetDefaultConfiguration(SCNetworkSetRef set,
4018 SCNetworkInterfaceRef interface,
4019 CFStringRef defaultType,
4020 CFDictionaryRef config,
4021 Boolean okToHold)
4022 {
4023 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4024 Boolean ok = FALSE;
4025
4026 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4027 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
4028
4029 if (defaultType == NULL) {
4030 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
4031 if (defaultType == NULL) {
4032 return FALSE;
4033 }
4034 }
4035
4036 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
4037 config = NULL;
4038 }
4039
4040 if (set != NULL) {
4041 CFStringRef path;
4042
4043 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
4044 SCNetworkSetGetSetID(set), // set
4045 interfacePrivate->entity_device, // interface
4046 defaultType); // entity
4047 if (path != NULL) {
4048 ok = __setPrefsConfiguration(interfacePrivate->prefs, path, config, FALSE);
4049 CFRelease(path);
4050 if (ok) {
4051 // if configuration has been saved
4052 if (interfacePrivate->unsaved != NULL) {
4053 CFDictionaryRemoveValue(interfacePrivate->unsaved, defaultType);
4054 if (CFDictionaryGetCount(interfacePrivate->unsaved) == 0) {
4055 CFRelease(interfacePrivate->unsaved);
4056 interfacePrivate->unsaved = NULL;
4057 }
4058 }
4059 }
4060 } else {
4061 if (okToHold) {
4062 if (config == NULL) {
4063 // remember that we are clearing the configuration
4064 config = (CFDictionaryRef)kCFNull;
4065 }
4066
4067 if (interfacePrivate->unsaved == NULL) {
4068 interfacePrivate->unsaved = CFDictionaryCreateMutable(NULL,
4069 0,
4070 &kCFTypeDictionaryKeyCallBacks,
4071 &kCFTypeDictionaryValueCallBacks);
4072 }
4073 CFDictionarySetValue(interfacePrivate->unsaved, defaultType, config);
4074 ok = TRUE;
4075 } else {
4076 _SCErrorSet(kSCStatusNoKey);
4077 }
4078 }
4079 }
4080
4081 return ok;
4082 }
4083
4084
4085 __private_extern__
4086 Boolean
4087 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface,
4088 CFStringRef extendedType,
4089 CFDictionaryRef config,
4090 Boolean okToHold)
4091 {
4092 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4093 Boolean ok = FALSE;
4094 CFArrayRef paths;
4095
4096 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4097 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
4098
4099 if (extendedType == NULL) {
4100 extendedType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
4101 if (extendedType == NULL) {
4102 return FALSE;
4103 }
4104 }
4105
4106 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
4107 config = NULL;
4108 }
4109
4110 paths = copyConfigurationPaths(interfacePrivate, extendedType);
4111 if (paths != NULL) {
4112 CFIndex i;
4113 CFIndex n;
4114
4115 n = CFArrayGetCount(paths);
4116 for (i = 0; i < n; i++) {
4117 CFStringRef path;
4118
4119 path = CFArrayGetValueAtIndex(paths, i);
4120 ok = __setPrefsConfiguration(interfacePrivate->prefs, path, config, FALSE);
4121 if (!ok) {
4122 break;
4123 }
4124 }
4125
4126 if (ok) {
4127 // if configuration has been saved
4128 if (interfacePrivate->unsaved != NULL) {
4129 CFDictionaryRemoveValue(interfacePrivate->unsaved, extendedType);
4130 if (CFDictionaryGetCount(interfacePrivate->unsaved) == 0) {
4131 CFRelease(interfacePrivate->unsaved);
4132 interfacePrivate->unsaved = NULL;
4133 }
4134 }
4135 }
4136
4137 CFRelease(paths);
4138 } else {
4139 if (okToHold) {
4140 if (config == NULL) {
4141 // remember that we are clearing the configuration
4142 config = (CFDictionaryRef)kCFNull;
4143 }
4144
4145 if (interfacePrivate->unsaved == NULL) {
4146 interfacePrivate->unsaved = CFDictionaryCreateMutable(NULL,
4147 0,
4148 &kCFTypeDictionaryKeyCallBacks,
4149 &kCFTypeDictionaryValueCallBacks);
4150 }
4151 CFDictionarySetValue(interfacePrivate->unsaved, extendedType, config);
4152 ok = TRUE;
4153 } else {
4154 _SCErrorSet(kSCStatusNoKey);
4155 }
4156 }
4157
4158 return ok;
4159 }
4160
4161
4162 Boolean
4163 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config)
4164 {
4165 CFStringRef defaultType;
4166
4167 if (!isA_SCNetworkInterface(interface)) {
4168 _SCErrorSet(kSCStatusInvalidArgument);
4169 return FALSE;
4170 }
4171
4172 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
4173 if (defaultType == NULL) {
4174 return FALSE;
4175 }
4176
4177 return __SCNetworkInterfaceSetConfiguration(interface, defaultType, config, FALSE);
4178 }
4179
4180
4181 Boolean
4182 SCNetworkInterfaceSetExtendedConfiguration(SCNetworkInterfaceRef interface,
4183 CFStringRef extendedType,
4184 CFDictionaryRef config)
4185 {
4186 if (!isA_SCNetworkInterface(interface)) {
4187 _SCErrorSet(kSCStatusInvalidArgument);
4188 return FALSE;
4189 }
4190
4191 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) {
4192 return FALSE;
4193 }
4194
4195 return __SCNetworkInterfaceSetConfiguration(interface, extendedType, config, FALSE);
4196 }
4197
4198
4199 #pragma mark -
4200 #pragma mark SCNetworkInterface [Refresh Configuration] API
4201
4202
4203 #ifndef kSCEntNetRefreshConfiguration
4204 #define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration")
4205 #endif // kSCEntNetRefreshConfiguration
4206
4207 Boolean
4208 _SCNetworkInterfaceForceConfigurationRefresh(CFStringRef ifName)
4209 {
4210 CFStringRef key;
4211 Boolean ok = FALSE;
4212 SCDynamicStoreRef store;
4213
4214 if (!isA_CFString(ifName)) {
4215 _SCErrorSet(kSCStatusInvalidArgument);
4216 return FALSE;
4217 }
4218
4219 store = SCDynamicStoreCreate(NULL, CFSTR("_SCNetworkInterfaceForceConfigurationRefresh"), NULL, NULL);
4220 if (store == NULL) {
4221 return FALSE;
4222 }
4223
4224 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
4225 kSCDynamicStoreDomainState,
4226 ifName,
4227 kSCEntNetRefreshConfiguration);
4228 ok = SCDynamicStoreNotifyValue(store, key);
4229 CFRelease(key);
4230 CFRelease(store);
4231 return ok;
4232 }
4233
4234
4235 static Boolean
4236 __SCNetworkInterfaceForceConfigurationRefresh_helper(SCPreferencesRef prefs, CFStringRef ifName)
4237 {
4238 CFDataRef data = NULL;
4239 Boolean ok;
4240 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
4241 uint32_t status = kSCStatusOK;
4242 CFDataRef reply = NULL;
4243
4244 if (prefsPrivate->helper == -1) {
4245 ok = __SCPreferencesCreate_helper(prefs);
4246 if (!ok) {
4247 return FALSE;
4248 }
4249 }
4250
4251 // serialize the interface name
4252 ok = _SCSerializeString(ifName, &data, NULL, NULL);
4253 if (!ok) {
4254 goto fail;
4255 }
4256
4257 // have the helper "refresh" the configuration
4258 status = kSCStatusOK;
4259 reply = NULL;
4260 ok = _SCHelperExec(prefsPrivate->helper,
4261 SCHELPER_MSG_INTERFACE_REFRESH,
4262 data,
4263 &status,
4264 NULL);
4265 if (data != NULL) CFRelease(data);
4266 if (!ok) {
4267 goto fail;
4268 }
4269
4270 if (status != kSCStatusOK) {
4271 goto error;
4272 }
4273
4274 return TRUE;
4275
4276 fail :
4277
4278 // close helper
4279 if (prefsPrivate->helper != -1) {
4280 _SCHelperClose(prefsPrivate->helper);
4281 prefsPrivate->helper = -1;
4282 }
4283
4284 status = kSCStatusAccessError;
4285
4286 error :
4287
4288 // return error
4289 _SCErrorSet(status);
4290 return FALSE;
4291 }
4292
4293
4294 Boolean
4295 SCNetworkInterfaceForceConfigurationRefresh(SCNetworkInterfaceRef interface)
4296 {
4297 CFStringRef ifName;
4298 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4299
4300 if (!isA_SCNetworkInterface(interface)) {
4301 _SCErrorSet(kSCStatusInvalidArgument);
4302 return FALSE;
4303 }
4304
4305 ifName = SCNetworkInterfaceGetBSDName(interface);
4306 if (ifName == NULL) {
4307 _SCErrorSet(kSCStatusInvalidArgument);
4308 return FALSE;
4309 }
4310
4311 if (interfacePrivate->prefs != NULL) {
4312 SCPreferencesRef prefs = interfacePrivate->prefs;
4313 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
4314
4315 if (prefsPrivate->authorizationData != NULL) {
4316 return __SCNetworkInterfaceForceConfigurationRefresh_helper(prefs, ifName);
4317 }
4318 }
4319
4320 return _SCNetworkInterfaceForceConfigurationRefresh(ifName);
4321 }
4322
4323
4324 Boolean
4325 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName)
4326 {
4327 return _SCNetworkInterfaceForceConfigurationRefresh(ifName);
4328 }
4329
4330
4331 #pragma mark -
4332 #pragma mark SCNetworkInterface Password APIs
4333
4334
4335 static CFStringRef
4336 getPasswordID(CFDictionaryRef config, CFStringRef serviceID)
4337 {
4338 CFStringRef unique_id = NULL;
4339
4340 if (config != NULL) {
4341 CFStringRef encryption;
4342
4343 encryption = CFDictionaryGetValue(config, kSCPropNetPPPAuthPasswordEncryption);
4344 if (isA_CFString(encryption) &&
4345 CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
4346 unique_id = CFDictionaryGetValue(config, kSCPropNetPPPAuthPassword);
4347 }
4348 }
4349 if (unique_id == NULL) {
4350 unique_id = serviceID;
4351 }
4352
4353 return unique_id;
4354 }
4355
4356
4357 static CFStringRef
4358 copySharedSecretID(CFDictionaryRef config, CFStringRef serviceID)
4359 {
4360 CFMutableStringRef shared_id = NULL;
4361
4362 if (config != NULL) {
4363 CFStringRef encryption;
4364
4365 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecretEncryption);
4366 if (isA_CFString(encryption) &&
4367 CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
4368 shared_id = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecret);
4369 if (shared_id != NULL) {
4370 CFRetain(shared_id);
4371 }
4372 }
4373 }
4374
4375 if (shared_id == NULL) {
4376 CFStringRef unique_id;
4377
4378 unique_id = getPasswordID(config, serviceID);
4379 shared_id = CFStringCreateMutableCopy(NULL, 0, unique_id);
4380 CFStringAppend(shared_id, CFSTR(".SS"));
4381 }
4382
4383 return shared_id;
4384 }
4385
4386
4387 static CFStringRef
4388 copyXAuthID(CFDictionaryRef config, CFStringRef serviceID)
4389 {
4390 CFMutableStringRef xauth_id = NULL;
4391
4392 if (config != NULL) {
4393 CFStringRef encryption;
4394
4395 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPasswordEncryption);
4396 if (isA_CFString(encryption) &&
4397 CFEqual(encryption, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) {
4398 xauth_id = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPassword);
4399 if (xauth_id != NULL) {
4400 CFRetain(xauth_id);
4401 }
4402 }
4403 }
4404
4405 if (xauth_id == NULL) {
4406 CFStringRef unique_id;
4407
4408 unique_id = getPasswordID(config, serviceID);
4409 xauth_id = CFStringCreateMutableCopy(NULL, 0, unique_id);
4410 CFStringAppend(xauth_id, CFSTR(".XAUTH"));
4411 }
4412
4413 return xauth_id;
4414 }
4415
4416
4417 static Boolean
4418 checkInterfacePassword(SCNetworkInterfaceRef interface,
4419 SCNetworkInterfacePasswordType passwordType,
4420 SCPreferencesRef *prefs,
4421 CFStringRef *serviceID)
4422 {
4423 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4424
4425 if (!isA_SCNetworkInterface(interface)) {
4426 goto error;
4427 }
4428
4429 *serviceID = interfacePrivate->serviceID;
4430 if (*serviceID == NULL) {
4431 goto error;
4432 }
4433
4434 *prefs = interfacePrivate->prefs;
4435 if (*prefs == NULL) {
4436 goto error;
4437 }
4438
4439 switch (passwordType) {
4440 case kSCNetworkInterfacePasswordTypePPP : {
4441 CFStringRef interfaceType;
4442
4443 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
4444 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
4445 // if PPP
4446 break;
4447 }
4448
4449 goto error;
4450 }
4451
4452 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
4453 CFStringRef interfaceType;
4454
4455 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
4456 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
4457 interface = SCNetworkInterfaceGetInterface(interface);
4458 if (interface != NULL) {
4459 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
4460 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
4461 // if PPP->L2TP interface
4462 break;
4463 }
4464 }
4465 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) {
4466 // if IPSec interface
4467 break;
4468 }
4469
4470 goto error;
4471 }
4472
4473 case kSCNetworkInterfacePasswordTypeEAPOL : {
4474 break;
4475 }
4476
4477 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
4478 CFStringRef interfaceType;
4479
4480 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
4481 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) {
4482 // if IPSec interface
4483 break;
4484 }
4485
4486 goto error;
4487 }
4488
4489 default :
4490 break;
4491 }
4492
4493 return TRUE;
4494
4495 error :
4496
4497 _SCErrorSet(kSCStatusInvalidArgument);
4498 return FALSE;
4499 }
4500
4501
4502 Boolean
4503 SCNetworkInterfaceCheckPassword(SCNetworkInterfaceRef interface,
4504 SCNetworkInterfacePasswordType passwordType)
4505 {
4506 Boolean exists = FALSE;
4507 SCPreferencesRef prefs = NULL;
4508 CFStringRef serviceID = NULL;
4509
4510 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
4511 return FALSE;
4512 }
4513
4514 switch (passwordType) {
4515 case kSCNetworkInterfacePasswordTypePPP : {
4516 CFDictionaryRef config;
4517 CFStringRef unique_id;
4518
4519 // get configuration
4520 config = SCNetworkInterfaceGetConfiguration(interface);
4521
4522 // get serviceID
4523 unique_id = getPasswordID(config, serviceID);
4524
4525 // check
4526 exists = __extract_password(prefs,
4527 config,
4528 kSCPropNetPPPAuthPassword,
4529 kSCPropNetPPPAuthPasswordEncryption,
4530 kSCValNetPPPAuthPasswordEncryptionKeychain,
4531 unique_id,
4532 NULL);
4533 break;
4534 }
4535
4536 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
4537 CFDictionaryRef config;
4538 Boolean extended;
4539 CFStringRef shared_id;
4540
4541 // get configuration
4542 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP);
4543 if (extended) {
4544 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
4545 } else {
4546 config = SCNetworkInterfaceGetConfiguration(interface);
4547 }
4548
4549 // get sharedSecret ID
4550 shared_id = copySharedSecretID(config, serviceID);
4551
4552 // check
4553 exists = __extract_password(prefs,
4554 config,
4555 kSCPropNetIPSecSharedSecret,
4556 kSCPropNetIPSecSharedSecretEncryption,
4557 kSCValNetIPSecSharedSecretEncryptionKeychain,
4558 shared_id,
4559 NULL);
4560 CFRelease(shared_id);
4561 break;
4562 }
4563
4564 case kSCNetworkInterfacePasswordTypeEAPOL : {
4565 CFDictionaryRef config;
4566 CFStringRef unique_id = NULL;
4567
4568 // get configuration
4569 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
4570
4571 // get 802.1X identifier
4572 if (config != NULL) {
4573 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
4574 }
4575 if (!isA_CFString(unique_id)) {
4576 return FALSE;
4577 }
4578
4579 // check password
4580 exists = _SCPreferencesSystemKeychainPasswordItemExists(prefs, unique_id);
4581 break;
4582 }
4583
4584 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
4585 CFDictionaryRef config;
4586 CFStringRef xauth_id;
4587
4588 // get configuration
4589 config = SCNetworkInterfaceGetConfiguration(interface);
4590
4591 // get XAuth ID
4592 xauth_id = copyXAuthID(config, serviceID);
4593
4594 // check
4595 exists = __extract_password(prefs,
4596 config,
4597 kSCPropNetIPSecXAuthPassword,
4598 kSCPropNetIPSecXAuthPasswordEncryption,
4599 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
4600 xauth_id,
4601 NULL);
4602 CFRelease(xauth_id);
4603 break;
4604 }
4605
4606 default :
4607 _SCErrorSet(kSCStatusInvalidArgument);
4608 return FALSE;
4609 }
4610
4611 return exists;
4612 }
4613
4614
4615 CFDataRef
4616 SCNetworkInterfaceCopyPassword(SCNetworkInterfaceRef interface,
4617 SCNetworkInterfacePasswordType passwordType)
4618 {
4619 CFDataRef password = NULL;
4620 SCPreferencesRef prefs = NULL;
4621 CFStringRef serviceID = NULL;
4622
4623 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
4624 return NULL;
4625 }
4626
4627 switch (passwordType) {
4628 case kSCNetworkInterfacePasswordTypePPP : {
4629 CFDictionaryRef config;
4630 CFStringRef unique_id;
4631
4632 // get configuration
4633 config = SCNetworkInterfaceGetConfiguration(interface);
4634
4635 // get serviceID
4636 unique_id = getPasswordID(config, serviceID);
4637
4638 // extract
4639 (void) __extract_password(prefs,
4640 config,
4641 kSCPropNetPPPAuthPassword,
4642 kSCPropNetPPPAuthPasswordEncryption,
4643 kSCValNetPPPAuthPasswordEncryptionKeychain,
4644 unique_id,
4645 &password);
4646 break;
4647 }
4648
4649 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
4650 CFDictionaryRef config;
4651 Boolean extended;
4652 CFStringRef shared_id;
4653
4654 // get configuration
4655 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP);
4656 if (extended) {
4657 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
4658 } else {
4659 config = SCNetworkInterfaceGetConfiguration(interface);
4660 }
4661
4662 // get sharedSecret ID
4663 shared_id = copySharedSecretID(config, serviceID);
4664
4665 // extract
4666 (void) __extract_password(prefs,
4667 config,
4668 kSCPropNetIPSecSharedSecret,
4669 kSCPropNetIPSecSharedSecretEncryption,
4670 kSCValNetIPSecSharedSecretEncryptionKeychain,
4671 shared_id,
4672 &password);
4673
4674 CFRelease(shared_id);
4675 break;
4676 }
4677
4678 case kSCNetworkInterfacePasswordTypeEAPOL : {
4679 CFDictionaryRef config;
4680 CFStringRef unique_id = NULL;
4681
4682 // get configuration
4683 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
4684
4685 // get 802.1X identifier
4686 if (config != NULL) {
4687 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
4688 }
4689 if (!isA_CFString(unique_id)) {
4690 _SCErrorSet(kSCStatusFailed);
4691 return NULL;
4692 }
4693
4694 // copy password
4695 password = _SCPreferencesSystemKeychainPasswordItemCopy(prefs, unique_id);
4696 break;
4697 }
4698
4699 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
4700 CFDictionaryRef config;
4701 CFStringRef xauth_id;
4702
4703 // get configuration
4704 config = SCNetworkInterfaceGetConfiguration(interface);
4705
4706 // get XAuth ID
4707 xauth_id = copyXAuthID(config, serviceID);
4708
4709 // extract
4710 (void) __extract_password(prefs,
4711 config,
4712 kSCPropNetIPSecXAuthPassword,
4713 kSCPropNetIPSecXAuthPasswordEncryption,
4714 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
4715 xauth_id,
4716 &password);
4717 CFRelease(xauth_id);
4718 break;
4719 }
4720
4721 default :
4722 _SCErrorSet(kSCStatusInvalidArgument);
4723 return NULL;
4724 }
4725
4726 return password;
4727 }
4728
4729
4730 Boolean
4731 SCNetworkInterfaceRemovePassword(SCNetworkInterfaceRef interface,
4732 SCNetworkInterfacePasswordType passwordType)
4733 {
4734 Boolean ok = FALSE;
4735 SCPreferencesRef prefs = NULL;
4736 CFStringRef serviceID = NULL;
4737
4738 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
4739 return FALSE;
4740 }
4741
4742 switch (passwordType) {
4743 case kSCNetworkInterfacePasswordTypePPP : {
4744 CFDictionaryRef config;
4745 CFDictionaryRef newConfig = NULL;
4746 CFStringRef unique_id;
4747
4748 // get configuration
4749 config = SCNetworkInterfaceGetConfiguration(interface);
4750
4751 // get serviceID
4752 unique_id = getPasswordID(config, serviceID);
4753
4754 // remove password
4755 ok = __remove_password(prefs,
4756 config,
4757 kSCPropNetPPPAuthPassword,
4758 kSCPropNetPPPAuthPasswordEncryption,
4759 kSCValNetPPPAuthPasswordEncryptionKeychain,
4760 unique_id,
4761 &newConfig);
4762 if (ok) {
4763 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
4764 if (newConfig != NULL) CFRelease(newConfig);
4765 }
4766
4767 break;
4768 }
4769
4770 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
4771 CFDictionaryRef config;
4772 Boolean extended;
4773 CFDictionaryRef newConfig = NULL;
4774 CFStringRef shared_id;
4775
4776 // get configuration
4777 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP);
4778 if (extended) {
4779 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
4780 } else {
4781 config = SCNetworkInterfaceGetConfiguration(interface);
4782 }
4783
4784 // get sharedSecret ID
4785 shared_id = copySharedSecretID(config, serviceID);
4786
4787 // remove password
4788 ok = __remove_password(prefs,
4789 config,
4790 kSCPropNetIPSecSharedSecret,
4791 kSCPropNetIPSecSharedSecretEncryption,
4792 kSCValNetIPSecSharedSecretEncryptionKeychain,
4793 shared_id,
4794 &newConfig);
4795 if (ok) {
4796 if (extended) {
4797 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
4798 kSCEntNetIPSec,
4799 newConfig);
4800 } else {
4801 ok = SCNetworkInterfaceSetConfiguration(interface,
4802 newConfig);
4803 }
4804 if (newConfig != NULL) CFRelease(newConfig);
4805 }
4806
4807 CFRelease(shared_id);
4808 break;
4809 }
4810
4811 case kSCNetworkInterfacePasswordTypeEAPOL : {
4812 CFDictionaryRef config;
4813 CFStringRef unique_id = NULL;
4814
4815 // get configuration
4816 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
4817
4818 // get 802.1X identifier
4819 if (config != NULL) {
4820 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
4821 }
4822 if (!isA_CFString(unique_id)) {
4823 _SCErrorSet(kSCStatusFailed);
4824 return FALSE;
4825 }
4826
4827 // remove password
4828 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, unique_id);
4829 break;
4830 }
4831
4832 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
4833 CFDictionaryRef config;
4834 CFDictionaryRef newConfig = NULL;
4835 CFStringRef xauth_id;
4836
4837 // get configuration
4838 config = SCNetworkInterfaceGetConfiguration(interface);
4839
4840 // get XAuth ID
4841 xauth_id = copyXAuthID(config, serviceID);
4842
4843 // remove password
4844 ok = __remove_password(prefs,
4845 config,
4846 kSCPropNetIPSecXAuthPassword,
4847 kSCPropNetIPSecXAuthPasswordEncryption,
4848 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
4849 xauth_id,
4850 &newConfig);
4851 if (ok) {
4852 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
4853 if (newConfig != NULL) CFRelease(newConfig);
4854 }
4855
4856 CFRelease(xauth_id);
4857 break;
4858 }
4859
4860 default :
4861 _SCErrorSet(kSCStatusInvalidArgument);
4862 return FALSE;
4863 }
4864
4865 return ok;
4866 }
4867
4868
4869 Boolean
4870 SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface,
4871 SCNetworkInterfacePasswordType passwordType,
4872 CFDataRef password,
4873 CFDictionaryRef options)
4874 {
4875 CFStringRef account = NULL;
4876 CFDictionaryRef config;
4877 CFStringRef description = NULL;
4878 CFStringRef label = NULL;
4879 Boolean ok = FALSE;
4880 SCPreferencesRef prefs = NULL;
4881 CFStringRef serviceID = NULL;
4882
4883 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
4884 return FALSE;
4885 }
4886
4887 switch (passwordType) {
4888 case kSCNetworkInterfacePasswordTypePPP : {
4889 SCNetworkServiceRef service = NULL;
4890 CFStringRef unique_id;
4891
4892 // get configuration
4893 config = SCNetworkInterfaceGetConfiguration(interface);
4894
4895 // get serviceID
4896 unique_id = getPasswordID(config, serviceID);
4897
4898 // get "Account", "Name", "Kind"
4899 if (config != NULL) {
4900 // auth name --> keychain "Account"
4901 account = CFDictionaryGetValue(config, kSCPropNetPPPAuthName);
4902
4903 // PPP [user defined] "name" --> keychain "Name"
4904 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
4905 }
4906
4907 if (label == NULL) {
4908 // service name --> keychain "Name"
4909 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
4910 prefs,
4911 serviceID,
4912 interface);
4913
4914 label = SCNetworkServiceGetName(service);
4915 if (label == NULL) {
4916 // interface name --> keychain "Name"
4917 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
4918 }
4919 }
4920
4921 if (bundle != NULL) {
4922 // "PPP Password" --> keychain "Kind"
4923 description = CFBundleCopyLocalizedString(bundle,
4924 CFSTR("KEYCHAIN_KIND_PPP_PASSWORD"),
4925 CFSTR("PPP Password"),
4926 NULL);
4927 }
4928
4929 // store password
4930 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
4931 unique_id,
4932 (label != NULL) ? label : CFSTR("Network Connection"),
4933 (description != NULL) ? description : CFSTR("PPP Password"),
4934 account,
4935 password,
4936 options);
4937 if (ok) {
4938 CFMutableDictionaryRef newConfig;
4939
4940 if (config != NULL) {
4941 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
4942 } else {
4943 newConfig = CFDictionaryCreateMutable(NULL,
4944 0,
4945 &kCFTypeDictionaryKeyCallBacks,
4946 &kCFTypeDictionaryValueCallBacks);
4947 }
4948 CFDictionarySetValue(newConfig,
4949 kSCPropNetPPPAuthPassword,
4950 unique_id);
4951 CFDictionarySetValue(newConfig,
4952 kSCPropNetPPPAuthPasswordEncryption,
4953 kSCValNetPPPAuthPasswordEncryptionKeychain);
4954 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
4955 CFRelease(newConfig);
4956 }
4957
4958 if (description != NULL) CFRelease(description);
4959 if (service != NULL) CFRelease(service);
4960 break;
4961 }
4962
4963 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
4964 CFDictionaryRef baseConfig = NULL;
4965 Boolean extended;
4966 SCNetworkServiceRef service = NULL;
4967 CFStringRef shared_id;
4968
4969 // get configuration
4970 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP);
4971 config = SCNetworkInterfaceGetConfiguration(interface);
4972 if (extended) {
4973 baseConfig = config;
4974 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
4975 }
4976
4977 // get sharedSecret ID
4978 shared_id = copySharedSecretID(config, serviceID);
4979
4980 // get "Account", "Name", "Kind"
4981 if (config != NULL) {
4982 CFStringRef localIdentifier;
4983 CFStringRef localIdentifierType;
4984
4985 if (CFDictionaryGetValueIfPresent(config,
4986 kSCPropNetIPSecLocalIdentifierType,
4987 (const void **)&localIdentifierType)
4988 && CFEqual(localIdentifierType, kSCValNetIPSecLocalIdentifierTypeKeyID)
4989 && CFDictionaryGetValueIfPresent(config,
4990 kSCPropNetIPSecLocalIdentifier,
4991 (const void **)&localIdentifier)
4992 && isA_CFString(localIdentifier)) {
4993 // local identifier --> keychain "Account"
4994 account = localIdentifier;
4995 }
4996
4997 // PPP [user defined] "name" --> keychain "Name"
4998 if (!extended) {
4999 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
5000 } else {
5001 if (baseConfig != NULL) {
5002 label = CFDictionaryGetValue(baseConfig, kSCPropUserDefinedName);
5003 }
5004 }
5005 }
5006
5007 if (label == NULL) {
5008 // service name --> keychain "Name"
5009 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
5010 prefs,
5011 serviceID,
5012 interface);
5013
5014 label = SCNetworkServiceGetName(service);
5015 if (label == NULL) {
5016 // interface name --> keychain "Name"
5017 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
5018 }
5019 }
5020
5021 if (bundle != NULL) {
5022 // "IPSec Shared Secret" --> keychain "Kind"
5023 description = CFBundleCopyLocalizedString(bundle,
5024 CFSTR("KEYCHAIN_KIND_IPSEC_SHARED_SECRET"),
5025 CFSTR("IPSec Shared Secret"),
5026 NULL);
5027 }
5028
5029 // set password
5030 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
5031 shared_id,
5032 (label != NULL) ? label : CFSTR("VPN Connection"),
5033 (description != NULL) ? description : CFSTR("IPSec Shared Secret"),
5034 account,
5035 password,
5036 options);
5037 if (ok) {
5038 CFMutableDictionaryRef newConfig = NULL;
5039
5040 if (config != NULL) {
5041 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
5042 } else {
5043 newConfig = CFDictionaryCreateMutable(NULL,
5044 0,
5045 &kCFTypeDictionaryKeyCallBacks,
5046 &kCFTypeDictionaryValueCallBacks);
5047 }
5048 CFDictionarySetValue(newConfig,
5049 kSCPropNetIPSecSharedSecret,
5050 shared_id);
5051 CFDictionarySetValue(newConfig,
5052 kSCPropNetIPSecSharedSecretEncryption,
5053 kSCValNetIPSecSharedSecretEncryptionKeychain);
5054 if (extended) {
5055 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
5056 kSCEntNetIPSec,
5057 newConfig);
5058 } else {
5059 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
5060 }
5061 CFRelease(newConfig);
5062 }
5063
5064 if (description != NULL) CFRelease(description);
5065 if (service != NULL) CFRelease(service);
5066 CFRelease(shared_id);
5067 break;
5068 }
5069
5070 case kSCNetworkInterfacePasswordTypeEAPOL : {
5071 CFStringRef account = NULL;
5072 CFStringRef unique_id = NULL;
5073
5074 // get configuration
5075 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
5076
5077 // get 802.1X identifier
5078 if (config != NULL) {
5079 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
5080 }
5081 if (isA_CFString(unique_id)) {
5082 CFRetain(unique_id);
5083 } else {
5084 CFUUIDRef uuid;
5085
5086 uuid = CFUUIDCreate(NULL);
5087 unique_id = CFUUIDCreateString(NULL, uuid);
5088 CFRelease(uuid);
5089 }
5090
5091 // 802.1x UserName --> keychain "Account"
5092 if (config != NULL) {
5093 account = CFDictionaryGetValue(config, kEAPClientPropUserName);
5094 }
5095
5096 // get "Name", "Kind"
5097 if (bundle != NULL) {
5098 CFStringRef interface_name;
5099
5100 // "Network Connection (%@)" --> keychain "Name"
5101 interface_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
5102 if (interface_name != NULL) {
5103 CFStringRef label_fmt;
5104
5105 label_fmt = CFBundleCopyLocalizedString(bundle,
5106 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL_INTERFACE"),
5107 CFSTR("Network Connection (%@)"),
5108 NULL);
5109 label = CFStringCreateWithFormat(NULL, NULL, label_fmt, interface_name);
5110 CFRelease(label_fmt);
5111 } else {
5112 label = CFBundleCopyLocalizedString(bundle,
5113 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL"),
5114 CFSTR("Network Connection"),
5115 NULL);
5116 }
5117
5118 // "802.1X Password" --> keychain "Kind"
5119 description = CFBundleCopyLocalizedString(bundle,
5120 CFSTR("KEYCHAIN_KIND_EAPOL"),
5121 CFSTR("802.1X Password"),
5122 NULL);
5123 }
5124
5125 // set password
5126 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
5127 unique_id,
5128 (label != NULL) ? label : CFSTR("Network Connection"),
5129 (description != NULL) ? description : CFSTR("802.1X Password"),
5130 account,
5131 password,
5132 options);
5133 if (ok) {
5134 CFMutableDictionaryRef newConfig = NULL;
5135
5136 if (config != NULL) {
5137 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
5138 } else {
5139 newConfig = CFDictionaryCreateMutable(NULL,
5140 0,
5141 &kCFTypeDictionaryKeyCallBacks,
5142 &kCFTypeDictionaryValueCallBacks);
5143 }
5144 CFDictionarySetValue(newConfig,
5145 kEAPClientPropUserPasswordKeychainItemID,
5146 unique_id);
5147 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
5148 kSCEntNetEAPOL,
5149 newConfig);
5150 CFRelease(newConfig);
5151 }
5152
5153 CFRelease(unique_id);
5154 if (label != NULL) CFRelease(label);
5155 if (description != NULL) CFRelease(description);
5156 break;
5157 }
5158
5159 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
5160 SCNetworkServiceRef service = NULL;
5161 CFStringRef xauth_id;
5162
5163 // get configuration
5164 config = SCNetworkInterfaceGetConfiguration(interface);
5165
5166 // get XAuth ID
5167 xauth_id = copyXAuthID(config, serviceID);
5168
5169 // get "Account", "Name", "Kind"
5170 if (config != NULL) {
5171 // auth name --> keychain "Account"
5172 account = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthName);
5173
5174 // IPSec [user defined] "name" --> keychain "Name"
5175 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
5176 }
5177
5178 if (label == NULL) {
5179 // service name --> keychain "Name"
5180 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
5181 prefs,
5182 serviceID,
5183 interface);
5184
5185 label = SCNetworkServiceGetName(service);
5186 if (label == NULL) {
5187 // interface name --> keychain "Name"
5188 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
5189 }
5190 }
5191
5192 if (bundle != NULL) {
5193 // "IPSec XAuth Password" --> keychain "Kind"
5194 description = CFBundleCopyLocalizedString(bundle,
5195 CFSTR("KEYCHAIN_KIND_IPSEC_XAUTH_PASSWORD"),
5196 CFSTR("IPSec XAuth Password"),
5197 NULL);
5198 }
5199
5200 // store password
5201 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
5202 xauth_id,
5203 (label != NULL) ? label : CFSTR("VPN Connection"),
5204 (description != NULL) ? description : CFSTR("IPSec XAuth Password"),
5205 account,
5206 password,
5207 options);
5208 if (ok) {
5209 CFMutableDictionaryRef newConfig;
5210
5211 if (config != NULL) {
5212 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
5213 } else {
5214 newConfig = CFDictionaryCreateMutable(NULL,
5215 0,
5216 &kCFTypeDictionaryKeyCallBacks,
5217 &kCFTypeDictionaryValueCallBacks);
5218 }
5219 CFDictionarySetValue(newConfig,
5220 kSCPropNetIPSecXAuthPassword,
5221 xauth_id);
5222 CFDictionarySetValue(newConfig,
5223 kSCPropNetIPSecXAuthPasswordEncryption,
5224 kSCValNetIPSecXAuthPasswordEncryptionKeychain);
5225 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
5226 CFRelease(newConfig);
5227 }
5228
5229 CFRelease(xauth_id);
5230 if (description != NULL) CFRelease(description);
5231 if (service != NULL) CFRelease(service);
5232 break;
5233 }
5234
5235 default :
5236 _SCErrorSet(kSCStatusInvalidArgument);
5237 break;
5238 }
5239
5240 return ok;
5241 }
5242
5243
5244 #pragma mark -
5245 #pragma mark SCNetworkInterface [InterfaceNamer] SPIs
5246
5247
5248 SCNetworkInterfaceRef
5249 _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj)
5250 {
5251 SCNetworkInterfaceRef interface = NULL;
5252
5253 /* initialize runtime */
5254 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
5255
5256 if (IOObjectConformsTo(if_obj, kIONetworkInterfaceClass)) {
5257 interface = createInterface(if_obj, processNetworkInterface);
5258 } else if (IOObjectConformsTo(if_obj, kIOSerialBSDServiceValue)) {
5259 interface = createInterface(if_obj, processSerialInterface);
5260 }
5261
5262 return interface;
5263 }
5264
5265
5266 CFStringRef
5267 _SCNetworkInterfaceGetConfigurationAction(SCNetworkInterfaceRef interface)
5268 {
5269 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5270
5271 return interfacePrivate->configurationAction;
5272 }
5273
5274
5275 CFDataRef
5276 _SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface)
5277 {
5278 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5279
5280 return interfacePrivate->address;
5281 }
5282
5283
5284 CFNumberRef
5285 _SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface)
5286 {
5287 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5288
5289 return interfacePrivate->type;
5290 }
5291
5292
5293 CFNumberRef
5294 _SCNetworkInterfaceGetIOInterfaceUnit(SCNetworkInterfaceRef interface)
5295 {
5296 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5297
5298 return interfacePrivate->unit;
5299 }
5300
5301
5302 CFStringRef
5303 _SCNetworkInterfaceGetIOPath(SCNetworkInterfaceRef interface)
5304 {
5305 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5306
5307 return interfacePrivate->path;
5308 }
5309
5310
5311 Boolean
5312 _SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface)
5313 {
5314 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5315
5316 return interfacePrivate->builtin;
5317 }
5318
5319
5320 #pragma mark -
5321 #pragma mark SCNetworkInterface SPIs
5322
5323
5324 CFStringRef
5325 _SCNetworkInterfaceCopySlashDevPath(SCNetworkInterfaceRef interface)
5326 {
5327 io_registry_entry_t device;
5328 io_iterator_t device_iterator = MACH_PORT_NULL;
5329 CFStringRef device_path = NULL;
5330 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5331 kern_return_t kr;
5332 CFStringRef match_keys[2];
5333 CFTypeRef match_vals[2];
5334 CFDictionaryRef match_dict;
5335 CFDictionaryRef matching;
5336
5337 if (interfacePrivate->entity_device == NULL) {
5338 return NULL;
5339 }
5340
5341 if (interfacePrivate->entity_device_unique == NULL) {
5342 goto done;
5343 }
5344
5345 match_keys[0] = CFSTR(kIOTTYBaseNameKey);
5346 match_vals[0] = interfacePrivate->entity_device;
5347 match_dict = CFDictionaryCreate(NULL,
5348 (const void **)match_keys,
5349 (const void **)match_vals,
5350 1,
5351 &kCFTypeDictionaryKeyCallBacks,
5352 &kCFTypeDictionaryValueCallBacks);
5353
5354 match_keys[0] = CFSTR(kIOProviderClassKey);
5355 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
5356 match_keys[1] = CFSTR(kIOPropertyMatchKey);
5357 match_vals[1] = match_dict;
5358 matching = CFDictionaryCreate(NULL,
5359 (const void **)match_keys,
5360 (const void **)match_vals,
5361 sizeof(match_keys)/sizeof(match_keys[0]),
5362 &kCFTypeDictionaryKeyCallBacks,
5363 &kCFTypeDictionaryValueCallBacks);
5364 CFRelease(match_dict);
5365
5366 // note: this "matching" dictionary will be consumed by the call to IOServiceGetMatchingServices
5367 kr = IOServiceGetMatchingServices(masterPort, matching, &device_iterator);
5368 if (kr != kIOReturnSuccess) {
5369 SCLog(TRUE, LOG_DEBUG, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x"), kr);
5370 goto done;
5371 }
5372
5373 while ((device_path == NULL) &&
5374 ((device = IOIteratorNext(device_iterator)) != MACH_PORT_NULL)) {
5375 CFDictionaryRef overrides;
5376
5377 overrides = IORegistryEntrySearchCFProperty(device,
5378 kIOServicePlane,
5379 CFSTR("DeviceModemOverrides"),
5380 NULL,
5381 kIORegistryIterateRecursively | kIORegistryIterateParents);
5382 if (overrides != NULL) {
5383 if (isA_CFDictionary(overrides)) {
5384 CFStringRef matchIdentifier;
5385
5386 matchIdentifier = CFDictionaryGetValue(overrides, CFSTR("UniqueIdentifier"));
5387 if (isA_CFString(matchIdentifier) &&
5388 CFEqual(interfacePrivate->entity_device_unique, matchIdentifier)) {
5389 device_path = IORegistryEntryCreateCFProperty(device,
5390 CFSTR(kIOTTYDeviceKey),
5391 NULL,
5392 0);
5393 }
5394 }
5395 CFRelease(overrides);
5396 }
5397 IOObjectRelease(device);
5398 }
5399
5400 IOObjectRelease(device_iterator);
5401
5402 done :
5403
5404 if (device_path == NULL) {
5405 // if we haven't found an exact match to our UniqueIdentifier
5406 // so we simply return the base name.
5407 device_path = SCNetworkInterfaceGetBSDName(interface);
5408 if (device_path != NULL) {
5409 CFRetain(device_path);
5410 }
5411 }
5412
5413 return device_path;
5414 }
5415
5416
5417 Boolean
5418 _SCNetworkInterfaceIsBluetoothPAN(SCNetworkInterfaceRef interface)
5419 {
5420 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5421
5422 return (interfacePrivate->sort_order == kSortBluetoothPAN);
5423 }
5424
5425
5426 Boolean
5427 _SCNetworkInterfaceIsModemV92(SCNetworkInterfaceRef interface)
5428 {
5429 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5430
5431 return interfacePrivate->modemIsV92;
5432 }
5433
5434
5435 Boolean
5436 _SCNetworkInterfaceIsTethered(SCNetworkInterfaceRef interface)
5437 {
5438 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5439
5440 return (interfacePrivate->sort_order == kSortTethered);
5441 }
5442
5443
5444 #pragma mark -
5445 #pragma mark SCNetworkInterface [internal] SPIs
5446
5447
5448 __private_extern__
5449 SCNetworkInterfacePrivateRef
5450 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator,
5451 SCNetworkInterfaceRef interface,
5452 SCPreferencesRef prefs,
5453 CFStringRef serviceID)
5454 {
5455 SCNetworkInterfacePrivateRef oldPrivate = (SCNetworkInterfacePrivateRef)interface;
5456 SCNetworkInterfacePrivateRef newPrivate;
5457
5458 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
5459 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
5460
5461 if (interface == kSCNetworkInterfaceIPv4) {
5462 return (SCNetworkInterfacePrivateRef)CFRetain(interface);
5463 }
5464
5465 newPrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, prefs, serviceID, NULL);
5466 newPrivate->interface_type = oldPrivate->interface_type;
5467 if (oldPrivate->interface != NULL) {
5468 newPrivate->interface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, // allocator
5469 oldPrivate->interface, // interface
5470 prefs, // [new] prefs
5471 serviceID); // [new] serviceID
5472 }
5473 if (oldPrivate->name != NULL) {
5474 newPrivate->name = CFRetain(oldPrivate->name);
5475 }
5476 if (oldPrivate->localized_name != NULL) {
5477 newPrivate->localized_name = CFRetain(oldPrivate->localized_name);
5478 }
5479 newPrivate->localized_key = oldPrivate->localized_key;
5480 if (oldPrivate->localized_arg1 != NULL) {
5481 newPrivate->localized_arg1 = CFRetain(oldPrivate->localized_arg1);
5482 }
5483 if (oldPrivate->localized_arg2 != NULL) {
5484 newPrivate->localized_arg2 = CFRetain(oldPrivate->localized_arg2);
5485 }
5486 if (oldPrivate->unsaved != NULL) {
5487 newPrivate->unsaved = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->unsaved);
5488 }
5489 if (oldPrivate->entity_device != NULL) {
5490 newPrivate->entity_device = CFRetain(oldPrivate->entity_device);
5491 }
5492 if (oldPrivate->entity_device_unique != NULL) {
5493 newPrivate->entity_device_unique = CFRetain(oldPrivate->entity_device_unique);
5494 }
5495 newPrivate->entity_type = oldPrivate->entity_type;
5496 newPrivate->entity_subtype = oldPrivate->entity_subtype;
5497 if (oldPrivate->supported_interface_types != NULL) {
5498 newPrivate->supported_interface_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_interface_types);
5499 }
5500 if (oldPrivate->supported_protocol_types != NULL) {
5501 newPrivate->supported_protocol_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_protocol_types);
5502 }
5503 if (oldPrivate->address != NULL) {
5504 newPrivate->address = CFRetain(oldPrivate->address);
5505 }
5506 newPrivate->builtin = oldPrivate->builtin;
5507 if (oldPrivate->configurationAction != NULL) {
5508 newPrivate->configurationAction = CFRetain(oldPrivate->configurationAction);
5509 }
5510 if (oldPrivate->location != NULL) {
5511 newPrivate->location = CFRetain(oldPrivate->location);
5512 }
5513 if (oldPrivate->path != NULL) {
5514 newPrivate->path = CFRetain(oldPrivate->path);
5515 }
5516 if (oldPrivate->overrides != NULL) {
5517 newPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->overrides);
5518 }
5519 newPrivate->modemIsV92 = oldPrivate->modemIsV92;
5520 if (oldPrivate->type != NULL) {
5521 newPrivate->type = CFRetain(oldPrivate->type);
5522 }
5523 if (oldPrivate->unit != NULL) {
5524 newPrivate->unit = CFRetain(oldPrivate->unit);
5525 }
5526 newPrivate->sort_order = oldPrivate->sort_order;
5527 #if !TARGET_OS_IPHONE
5528 newPrivate->supportsBond = oldPrivate->supportsBond;
5529 if (oldPrivate->bond.interfaces != NULL) {
5530 newPrivate->bond.interfaces = CFRetain(oldPrivate->bond.interfaces);
5531 }
5532 if (oldPrivate->bond.mode != NULL) {
5533 newPrivate->bond.mode = CFRetain(oldPrivate->bond.mode);
5534 }
5535 if (oldPrivate->bond.options != NULL) {
5536 newPrivate->bond.options = CFRetain(oldPrivate->bond.options);
5537 }
5538 newPrivate->supportsVLAN = oldPrivate->supportsVLAN;
5539 if (oldPrivate->vlan.interface != NULL) {
5540 newPrivate->vlan.interface = CFRetain(oldPrivate->vlan.interface);
5541 }
5542 if (oldPrivate->vlan.tag != NULL) {
5543 newPrivate->vlan.tag = CFRetain(oldPrivate->vlan.tag);
5544 }
5545 if (oldPrivate->vlan.options != NULL) {
5546 newPrivate->vlan.options = CFRetain(oldPrivate->vlan.options);
5547 }
5548 #endif // !TARGET_OS_IPHONE
5549
5550 return newPrivate;
5551 }
5552
5553
5554 __private_extern__
5555 CFArrayRef
5556 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface)
5557 {
5558 CFMutableArrayRef configs;
5559
5560 configs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
5561
5562 while (interface != NULL) {
5563 CFStringRef defaultType;
5564 CFMutableDictionaryRef interfaceConfiguration;
5565
5566 interfaceConfiguration = CFDictionaryCreateMutable(NULL,
5567 0,
5568 &kCFTypeDictionaryKeyCallBacks,
5569 &kCFTypeDictionaryValueCallBacks);
5570
5571 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
5572 if (defaultType != NULL) {
5573 CFDictionaryRef config;
5574 CFArrayRef extendedTypes;
5575
5576 if (set == NULL) {
5577 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType);
5578 } else {
5579 config = __SCNetworkInterfaceGetDefaultConfiguration(set, interface);
5580 }
5581 if (config == NULL) {
5582 config = (CFDictionaryRef)kCFNull;
5583 }
5584 CFDictionarySetValue(interfaceConfiguration, defaultType, config);
5585
5586 extendedTypes = extendedConfigurationTypes(interface);
5587 if (extendedTypes != NULL) {
5588 CFIndex i;
5589 CFIndex n;
5590
5591 n = CFArrayGetCount(extendedTypes);
5592 for (i = 0; i < n; i++) {
5593 CFStringRef extendedType;
5594
5595 extendedType = CFArrayGetValueAtIndex(extendedTypes, i);
5596 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType);
5597 if (config == NULL) {
5598 config = (CFDictionaryRef)kCFNull;
5599 }
5600 CFDictionarySetValue(interfaceConfiguration, extendedType, config);
5601 }
5602
5603 CFRelease(extendedTypes);
5604 }
5605 }
5606
5607 CFArrayAppendValue(configs, interfaceConfiguration);
5608 CFRelease(interfaceConfiguration);
5609
5610 interface = SCNetworkInterfaceGetInterface(interface);
5611 }
5612
5613 return configs;
5614 }
5615
5616
5617 __private_extern__
5618 void
5619 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface, CFArrayRef configs)
5620 {
5621 CFIndex i;
5622
5623 for (i = 0; interface != NULL; i++) {
5624 CFStringRef defaultType;
5625 CFDictionaryRef interfaceConfiguration;
5626
5627 interfaceConfiguration = (configs != NULL) ? CFArrayGetValueAtIndex(configs, i) : NULL;
5628
5629 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
5630 if (defaultType != NULL) {
5631 CFDictionaryRef config;
5632 CFArrayRef extendedTypes;
5633
5634 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, defaultType)
5635 : NULL;
5636 if (config == (CFDictionaryRef)kCFNull) {
5637 config = NULL;
5638 }
5639 if (set == NULL) {
5640 // if service is not associated with the set
5641 if (!__SCNetworkInterfaceSetConfiguration(interface, defaultType, config, TRUE)) {
5642 SCLog(TRUE, LOG_DEBUG,
5643 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
5644 interface,
5645 defaultType);
5646 }
5647 } else {
5648 // apply default configuration to this set
5649 if (!__SCNetworkInterfaceSetDefaultConfiguration(set, interface, defaultType, config, TRUE)) {
5650 SCLog(TRUE, LOG_DEBUG,
5651 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetDefaultConfiguration() failed, interface=%@, type=%@"),
5652 interface,
5653 defaultType);
5654 }
5655 }
5656
5657 extendedTypes = extendedConfigurationTypes(interface);
5658 if (extendedTypes != NULL) {
5659 CFIndex j;
5660 CFIndex n;
5661
5662 n = CFArrayGetCount(extendedTypes);
5663 for (j = 0; j < n; j++) {
5664 CFStringRef extendedType;
5665
5666 extendedType = CFArrayGetValueAtIndex(extendedTypes, j);
5667 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, extendedType)
5668 : NULL;
5669 if (config == (CFDictionaryRef)kCFNull) {
5670 config = NULL;
5671 }
5672 if (!__SCNetworkInterfaceSetConfiguration(interface, extendedType, config, TRUE)) {
5673 SCLog(TRUE, LOG_DEBUG,
5674 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
5675 interface,
5676 defaultType);
5677 }
5678 }
5679
5680 CFRelease(extendedTypes);
5681 }
5682 }
5683
5684 interface = SCNetworkInterfaceGetInterface(interface);
5685 }
5686
5687 return;
5688 }