]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkInterface.c
configd-963.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkInterface.c
1 /*
2 * Copyright (c) 2004-2017 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 "SCNetworkConfigurationInternal.h"
41 #include "SCPreferencesInternal.h"
42 #include "SCHelper_client.h"
43 #include "plugin_shared.h"
44
45 #if !TARGET_OS_IPHONE
46 #include <EAP8021X/EAPClientProperties.h>
47 #else // !TARGET_OS_IPHONE
48 #ifndef kEAPClientPropUserName
49 #define kEAPClientPropUserName CFSTR("UserName")
50 #endif
51 #ifndef kEAPClientPropUserPasswordKeychainItemID
52 #define kEAPClientPropUserPasswordKeychainItemID CFSTR("UserPasswordKeychainItemID")
53 #endif
54 #endif // !TARGET_OS_IPHONE
55
56 #include <IOKit/IOKitLib.h>
57 #include <IOKit/IOCFBundle.h>
58 #include <IOKit/IOBSD.h>
59 #include <IOKit/network/IONetworkController.h>
60 #include <IOKit/network/IONetworkInterface.h>
61 #include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass
62 #include <IOKit/serial/IOSerialKeys.h>
63 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
64 #if !TARGET_OS_SIMULATOR
65 #include <IOKit/usb/IOUSBLib.h>
66 #endif // !TARGET_OS_SIMULATOR
67
68 #include "dy_framework.h"
69
70 #ifndef kPCIThunderboltString
71 #define kPCIThunderboltString "PCI-Thunderbolt"
72 #endif
73
74 #ifndef kIOUserEthernetInterfaceRoleKey
75 #define kIOUserEthernetInterfaceRoleKey "InterfaceRole"
76 #endif
77
78 #ifndef kIOUSBHostInterfaceClassName
79 #define kIOUSBHostInterfaceClassName "IOUSBHostInterface"
80 #endif
81
82 #include <string.h>
83 #include <sysdir.h>
84 #include <mach/mach.h>
85 #include <net/if.h>
86 #include <net/if_types.h>
87 #include <net/if_dl.h>
88 #include <net/route.h>
89 #include <sys/ioctl.h>
90 #include <sys/param.h>
91 #include <sys/types.h>
92 #include <sys/socket.h>
93 #include <sys/stat.h>
94 #include <sys/sysctl.h>
95 #include <pthread.h>
96 #include <ifaddrs.h>
97
98
99 static CFStringRef copy_interface_string (CFBundleRef bundle, CFStringRef key, Boolean localized);
100 static CFStringRef __SCNetworkInterfaceCopyDescription (CFTypeRef cf);
101 static CFStringRef __SCNetworkInterfaceCopyFormattingDescription (CFTypeRef cf, CFDictionaryRef formatOptions);
102 static void __SCNetworkInterfaceDeallocate (CFTypeRef cf);
103 static Boolean __SCNetworkInterfaceEqual (CFTypeRef cf1, CFTypeRef cf2);
104 static CFHashCode __SCNetworkInterfaceHash (CFTypeRef cf);
105 static void __SCNetworkInterfaceCacheAdd (CFStringRef bsdName, CFArrayRef matchingInterfaces);
106 static Boolean __SCNetworkInterfaceCacheIsOpen ();
107 static CFArrayRef __SCNetworkInterfaceCacheCopy (CFStringRef bsdName);
108
109
110 enum {
111 kSortInternalModem,
112 kSortUSBModem,
113 kSortModem,
114 kSortBluetooth,
115 kSortIrDA,
116 kSortSerialPort,
117 kSortWWAN,
118 kSortEthernetPPP,
119 kSortAirportPPP,
120 kSortEthernet,
121 kSortFireWire,
122 kSortAirPort,
123 kSortOtherWireless,
124 kSortTethered,
125 kSortWWANEthernet,
126 kSortBluetoothPAN_GN,
127 kSortBluetoothPAN_NAP,
128 kSortBluetoothPAN_U,
129 kSortThunderbolt,
130 kSortBond,
131 kSortBridge,
132 kSortVLAN,
133 kSortUnknown
134 };
135
136
137 const CFStringRef kSCNetworkInterfaceType6to4 = CFSTR("6to4");
138 const CFStringRef kSCNetworkInterfaceTypeBluetooth = CFSTR("Bluetooth");
139 const CFStringRef kSCNetworkInterfaceTypeBond = CFSTR("Bond");
140 const CFStringRef kSCNetworkInterfaceTypeBridge = CFSTR("Bridge");
141 const CFStringRef kSCNetworkInterfaceTypeEthernet = CFSTR("Ethernet");
142 const CFStringRef kSCNetworkInterfaceTypeFireWire = CFSTR("FireWire");
143 const CFStringRef kSCNetworkInterfaceTypeIEEE80211 = CFSTR("IEEE80211"); // IEEE 802.11, AirPort
144 const CFStringRef kSCNetworkInterfaceTypeIPSec = CFSTR("IPSec");
145 const CFStringRef kSCNetworkInterfaceTypeIrDA = CFSTR("IrDA");
146 const CFStringRef kSCNetworkInterfaceTypeL2TP = CFSTR("L2TP");
147 const CFStringRef kSCNetworkInterfaceTypeLoopback = CFSTR("Loopback");
148 const CFStringRef kSCNetworkInterfaceTypeModem = CFSTR("Modem");
149 const CFStringRef kSCNetworkInterfaceTypePPP = CFSTR("PPP");
150 const CFStringRef kSCNetworkInterfaceTypePPTP = CFSTR("PPTP");
151 const CFStringRef kSCNetworkInterfaceTypeSerial = CFSTR("Serial");
152 const CFStringRef kSCNetworkInterfaceTypeVLAN = CFSTR("VLAN");
153 const CFStringRef kSCNetworkInterfaceTypeVPN = CFSTR("VPN");
154 const CFStringRef kSCNetworkInterfaceTypeWWAN = CFSTR("WWAN");
155
156 const CFStringRef kSCNetworkInterfaceTypeIPv4 = CFSTR("IPv4");
157
158 static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4 = {
159 .cfBase = INIT_CFRUNTIME_BASE(), // cfBase
160 .sort_order = kSortUnknown, // sort_order
161 };
162
163 const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4 = (SCNetworkInterfaceRef)&__kSCNetworkInterfaceIPv4;
164
165 static SCNetworkInterfacePrivate __kSCNetworkInterfaceLoopback = {
166 .cfBase = INIT_CFRUNTIME_BASE(), // cfBase
167 .sort_order = kSortUnknown, // sort_order
168 };
169
170 const SCNetworkInterfaceRef kSCNetworkInterfaceLoopback = (SCNetworkInterfaceRef)&__kSCNetworkInterfaceLoopback;
171
172 static CFMutableSetRef vendor_interface_types = NULL;
173
174 // A thread-specific convenience cache of all interfaces matching a bsd name
175 // Key: CFStringRef (BSD name)
176 // Value: CFArrayRef (matching interfaces)
177 static __thread CFMutableDictionaryRef S_interface_cache = NULL;
178
179 #pragma mark -
180 #pragma mark SCNetworkInterface configuration details
181
182 #define doNone 0
183
184 #define do6to4 1<<0
185 #define doL2TP 1<<1
186 #define doPPP 1<<2
187 #define doPPTP 1<<3
188 #define doIPSec 1<<4
189 #define doOverIP do6to4|doL2TP|doPPTP|doIPSec
190
191 #define doDNS 1<<1
192 #define doIPv4 1<<2
193 #define doIPv6 1<<3
194 #define doProxies 1<<4
195 #if !TARGET_OS_IPHONE
196 #define doSMB 1<<5
197 #else // !TARGET_OS_IPHONE
198 #define doSMB 0
199 #endif // !TARGET_OS_IPHONE
200
201 static const struct {
202 const CFStringRef *interface_type;
203 const CFStringRef *entity_hardware;
204 Boolean per_interface_config;
205 uint32_t supported_interfaces;
206 const CFStringRef *ppp_subtype;
207 uint32_t supported_protocols;
208 } configurations[] = {
209 // interface type entity_hardware if config? interface types PPP sub-type interface protocols
210 // ===================================== ==================== ========== =============== ======================================= =========================================
211 { &kSCNetworkInterfaceType6to4 , &kSCEntNet6to4 , FALSE, doNone, NULL, doIPv6 },
212 { &kSCNetworkInterfaceTypeBluetooth , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
213 { &kSCNetworkInterfaceTypeBond , &kSCEntNetEthernet , TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
214 { &kSCNetworkInterfaceTypeBridge , &kSCEntNetEthernet , TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
215 { &kSCNetworkInterfaceTypeEthernet , &kSCEntNetEthernet , TRUE , doPPP, &kSCValNetInterfaceSubTypePPPoE, doDNS|doIPv4|doIPv6|doProxies|doSMB },
216 { &kSCNetworkInterfaceTypeFireWire , &kSCEntNetFireWire , TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
217 { &kSCNetworkInterfaceTypeIEEE80211 , &kSCEntNetAirPort , TRUE , doPPP, &kSCValNetInterfaceSubTypePPPoE, doDNS|doIPv4|doIPv6|doProxies|doSMB },
218 { &kSCNetworkInterfaceTypeIPSec , &kSCEntNetIPSec , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
219 { &kSCNetworkInterfaceTypeIrDA , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
220 { &kSCNetworkInterfaceTypeL2TP , NULL , FALSE, doPPP, &kSCValNetInterfaceSubTypeL2TP, doNone },
221 { &kSCNetworkInterfaceTypeModem , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
222 { &kSCNetworkInterfaceTypePPP , &kSCEntNetPPP , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
223 #pragma GCC diagnostic push
224 #pragma GCC diagnostic ignored "-Wdeprecated"
225 { &kSCNetworkInterfaceTypePPTP , NULL , FALSE, doPPP, &kSCValNetInterfaceSubTypePPTP, doNone },
226 #pragma GCC diagnostic pop
227 { &kSCNetworkInterfaceTypeSerial , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
228 { &kSCNetworkInterfaceTypeVLAN , &kSCEntNetEthernet , TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
229 { &kSCNetworkInterfaceTypeVPN , &kSCEntNetVPN , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
230 { &kSCNetworkInterfaceTypeWWAN , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
231 // ===================================== =================== ========== =============== ======================================= =========================================
232 { &kSCNetworkInterfaceTypeLoopback , NULL , TRUE , doNone, NULL, doIPv4|doIPv6 },
233 // ===================================== =================== ========== =============== ======================================= =========================================
234 { &kSCNetworkInterfaceTypeIPv4 , NULL , FALSE, doOverIP, NULL, doNone }
235 };
236
237
238 #define kSCNetworkInterfaceActive "Active"
239 #define kSCNetworkInterfaceInfo "SCNetworkInterfaceInfo"
240 #define kSCNetworkInterfaceType "SCNetworkInterfaceType"
241 #define kSCNetworkInterfaceBSDName kIOBSDNameKey
242 #define kSCNetworkInterfaceIOBuiltin kIOBuiltin
243 #define kSCNetworkInterfaceIOInterfaceNamePrefix kIOInterfaceNamePrefix
244 #define kSCNetworkInterfaceIOInterfaceType kIOInterfaceType
245 #define kSCNetworkInterfaceIOInterfaceUnit kIOInterfaceUnit
246 #define kSCNetworkInterfaceIOMACAddress kIOMACAddress
247 #define kSCNetworkInterfaceIOPathMatch kIOPathMatchKey
248
249
250 #define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
251 static CFBundleRef bundle = NULL;
252
253
254 static CFTypeID __kSCNetworkInterfaceTypeID = _kCFRuntimeNotATypeID;
255
256
257 static const CFRuntimeClass __SCNetworkInterfaceClass = {
258 0, // version
259 "SCNetworkInterface", // className
260 NULL, // init
261 NULL, // copy
262 __SCNetworkInterfaceDeallocate, // dealloc
263 __SCNetworkInterfaceEqual, // equal
264 __SCNetworkInterfaceHash, // hash
265 __SCNetworkInterfaceCopyFormattingDescription, // copyFormattingDesc
266 __SCNetworkInterfaceCopyDescription // copyDebugDesc
267 };
268
269
270 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
271 static pthread_once_t iokit_quiet = PTHREAD_ONCE_INIT;
272 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
273
274
275 static mach_port_t masterPort = MACH_PORT_NULL;
276
277 static CFStringRef
278 __SCNetworkInterfaceCopyDescription(CFTypeRef cf)
279 {
280 return __SCNetworkInterfaceCopyFormattingDescription(cf, NULL);
281 }
282
283 static CFStringRef
284 __SCNetworkInterfaceCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions)
285 {
286 CFAllocatorRef allocator = CFGetAllocator(cf);
287 CFMutableStringRef result;
288 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
289
290 result = CFStringCreateMutable(allocator, 0);
291 CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkInterface %p [%p]> {"), cf, allocator);
292 CFStringAppendFormat(result, NULL, CFSTR("type = %@"), interfacePrivate->interface_type);
293 CFStringAppendFormat(result, NULL, CFSTR(", entity_device = %@"), interfacePrivate->entity_device);
294 if (interfacePrivate->entity_device_unique != NULL) {
295 CFStringAppendFormat(result, NULL, CFSTR("+%@"), interfacePrivate->entity_device_unique);
296 }
297 CFStringAppendFormat(result, NULL, CFSTR(", entity_type = %@"), interfacePrivate->entity_type);
298 if (interfacePrivate->entity_subtype != NULL) {
299 CFStringAppendFormat(result, NULL, CFSTR(" / %@"), interfacePrivate->entity_subtype);
300 }
301 if (interfacePrivate->name != NULL) {
302 CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), interfacePrivate->name);
303 }
304 if (interfacePrivate->localized_name != NULL) {
305 CFStringAppendFormat(result, NULL, CFSTR(", name(l) = %@"), interfacePrivate->localized_name);
306 } else {
307 if (interfacePrivate->localized_key != NULL) {
308 CFStringAppendFormat(result, NULL, CFSTR(", name(k) = \"%@\""), interfacePrivate->localized_key);
309 if (interfacePrivate->localized_arg1 != NULL) {
310 CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg1);
311 }
312 if (interfacePrivate->localized_arg2 != NULL) {
313 CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg2);
314 }
315 }
316 }
317 if (interfacePrivate->address != NULL) {
318 const uint8_t *data;
319 CFIndex dataLen;
320 CFIndex i;
321
322 CFStringAppendFormat(result, NULL, CFSTR(", address = "));
323
324 data = CFDataGetBytePtr(interfacePrivate->address);
325 dataLen = CFDataGetLength(interfacePrivate->address);
326 for (i = 0; i < dataLen; i++) {
327 CFStringAppendFormat(result, NULL, CFSTR("%s%02x"),
328 (i > 0) ? ":" : "",
329 data[i]);
330 }
331 }
332 CFStringAppendFormat(result, NULL, CFSTR(", builtin = %s"), interfacePrivate->builtin ? "TRUE" : "FALSE");
333 if (interfacePrivate->hidden) {
334 CFStringAppendFormat(result, NULL, CFSTR(", hidden = TRUE"));
335 }
336 if (interfacePrivate->location != NULL) {
337 CFStringAppendFormat(result, NULL, CFSTR(", location = %@"), interfacePrivate->location);
338 }
339 if (interfacePrivate->path != NULL) {
340 CFStringAppendFormat(result, NULL, CFSTR(", path = %@"), interfacePrivate->path);
341 }
342 if (interfacePrivate->entryID != 0) {
343 CFStringAppendFormat(result, NULL, CFSTR(", entryID = 0x%llx"), interfacePrivate->entryID);
344 }
345 if (interfacePrivate->type != NULL) {
346 CFStringAppendFormat(result, NULL, CFSTR(", type = %@"), interfacePrivate->type);
347 }
348 if (interfacePrivate->unit != NULL) {
349 CFStringAppendFormat(result, NULL, CFSTR(", unit = %@"), interfacePrivate->unit);
350 }
351 if (interfacePrivate->family != NULL) {
352 CFStringAppendFormat(result, NULL, CFSTR(", family = %@"), interfacePrivate->family);
353 }
354 if (interfacePrivate->subfamily != NULL) {
355 CFStringAppendFormat(result, NULL, CFSTR(", subfamily = %@"), interfacePrivate->subfamily);
356 }
357 if ((interfacePrivate->usb.vid != NULL) || (interfacePrivate->usb.pid != NULL)) {
358 int pid = 0;
359 int vid = 0;
360
361 if (!isA_CFNumber(interfacePrivate->usb.pid) ||
362 !CFNumberGetValue(interfacePrivate->usb.pid, kCFNumberIntType, &pid)) {
363 pid = 0;
364 }
365 if (!isA_CFNumber(interfacePrivate->usb.vid) ||
366 !CFNumberGetValue(interfacePrivate->usb.vid, kCFNumberIntType, &vid)) {
367 vid = 0;
368 }
369
370 if (interfacePrivate->usb.name != NULL) {
371 CFStringAppendFormat(result, NULL, CFSTR(", USB name = %@"),
372 interfacePrivate->usb.name);
373 }
374
375 CFStringAppendFormat(result, NULL, CFSTR(", USB vid/pid = 0x%0x/0x%0x"),
376 vid,
377 pid);
378 }
379 if (interfacePrivate->configurationAction != NULL) {
380 CFStringAppendFormat(result, NULL, CFSTR(", action = %@"), interfacePrivate->configurationAction);
381 }
382 if (interfacePrivate->overrides != NULL) {
383 CFStringAppendFormat(result, formatOptions, CFSTR(", overrides = %p"), interfacePrivate->overrides);
384 }
385 CFStringAppendFormat(result, NULL, CFSTR(", order = %d"), interfacePrivate->sort_order);
386 if (interfacePrivate->prefs != NULL) {
387 CFStringAppendFormat(result, NULL, CFSTR(", prefs = %p"), interfacePrivate->prefs);
388 }
389 if (interfacePrivate->serviceID != NULL) {
390 CFStringAppendFormat(result, NULL, CFSTR(", service = %@"), interfacePrivate->serviceID);
391 }
392 if (interfacePrivate->interface != NULL) {
393 CFStringAppendFormat(result, NULL, CFSTR(", interface = %@"), interfacePrivate->interface);
394 }
395 if (interfacePrivate->unsaved != NULL) {
396 CFStringAppendFormat(result, formatOptions, CFSTR(", unsaved = %@"), interfacePrivate->unsaved);
397 }
398
399 if (interfacePrivate->bond.interfaces != NULL) {
400 CFIndex i;
401 CFIndex n;
402
403 n = CFArrayGetCount(interfacePrivate->bond.interfaces);
404 for (i = 0; i < n; i++) {
405 SCNetworkInterfaceRef member;
406
407 member = CFArrayGetValueAtIndex(interfacePrivate->bond.interfaces, i);
408 CFStringAppendFormat(result, NULL,
409 CFSTR("%s%@"),
410 (i == 0) ? ", interfaces = " : ",",
411 SCNetworkInterfaceGetBSDName(member));
412 }
413 }
414 if (interfacePrivate->bond.mode != NULL) {
415 CFStringAppendFormat(result, NULL, CFSTR(", mode = %@"), interfacePrivate->bond.mode);
416 }
417 if (interfacePrivate->bond.options != NULL) {
418 CFStringRef str;
419
420 str = _SCCopyDescription(interfacePrivate->bond.options, formatOptions);
421 CFStringAppendFormat(result, formatOptions, CFSTR(", options = %@"), str);
422 CFRelease(str);
423 }
424
425 if (interfacePrivate->bridge.interfaces != NULL) {
426 CFIndex i;
427 CFIndex n;
428
429 n = CFArrayGetCount(interfacePrivate->bridge.interfaces);
430 for (i = 0; i < n; i++) {
431 SCNetworkInterfaceRef member;
432
433 member = CFArrayGetValueAtIndex(interfacePrivate->bridge.interfaces, i);
434 CFStringAppendFormat(result, NULL,
435 CFSTR("%s%@"),
436 (i == 0) ? ", interfaces = " : ",",
437 SCNetworkInterfaceGetBSDName(member));
438 }
439 }
440 if (interfacePrivate->bridge.options != NULL) {
441 CFStringRef str;
442
443 str = _SCCopyDescription(interfacePrivate->bridge.options, formatOptions);
444 CFStringAppendFormat(result, formatOptions, CFSTR(", options = %@"), str);
445 CFRelease(str);
446 }
447
448 if (interfacePrivate->vlan.interface != NULL) {
449 CFStringAppendFormat(result, NULL,
450 CFSTR(", interface = %@"),
451 SCNetworkInterfaceGetBSDName(interfacePrivate->vlan.interface));
452 }
453 if (interfacePrivate->vlan.tag != NULL) {
454 CFStringAppendFormat(result, NULL, CFSTR(", tag = %@"), interfacePrivate->vlan.tag);
455 }
456 if (interfacePrivate->vlan.options != NULL) {
457 CFStringRef str;
458
459 str = _SCCopyDescription(interfacePrivate->vlan.options, formatOptions);
460 CFStringAppendFormat(result, formatOptions, CFSTR(", options = %@"), str);
461 CFRelease(str);
462 }
463
464 CFStringAppendFormat(result, NULL, CFSTR("}"));
465
466 return result;
467 }
468
469
470 static void
471 __SCNetworkInterfaceDeallocate(CFTypeRef cf)
472 {
473 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
474
475 /* release resources */
476
477 if (interfacePrivate->name != NULL)
478 CFRelease(interfacePrivate->name);
479
480 if (interfacePrivate->localized_name != NULL)
481 CFRelease(interfacePrivate->localized_name);
482
483 if (interfacePrivate->localized_arg1 != NULL)
484 CFRelease(interfacePrivate->localized_arg1);
485
486 if (interfacePrivate->localized_arg2 != NULL)
487 CFRelease(interfacePrivate->localized_arg2);
488
489 if (interfacePrivate->interface != NULL)
490 CFRelease(interfacePrivate->interface);
491
492 if (interfacePrivate->prefs != NULL)
493 CFRelease(interfacePrivate->prefs);
494
495 if (interfacePrivate->store != NULL)
496 CFRelease(interfacePrivate->store);
497
498 if (interfacePrivate->serviceID != NULL)
499 CFRelease(interfacePrivate->serviceID);
500
501 if (interfacePrivate->unsaved != NULL)
502 CFRelease(interfacePrivate->unsaved);
503
504 if (interfacePrivate->entity_device != NULL)
505 CFRelease(interfacePrivate->entity_device);
506
507 if (interfacePrivate->entity_device_unique != NULL)
508 CFRelease(interfacePrivate->entity_device_unique);
509
510 if (interfacePrivate->supported_interface_types != NULL)
511 CFRelease(interfacePrivate->supported_interface_types);
512
513 if (interfacePrivate->supported_protocol_types != NULL)
514 CFRelease(interfacePrivate->supported_protocol_types);
515
516 if (interfacePrivate->address != NULL)
517 CFRelease(interfacePrivate->address);
518
519 if (interfacePrivate->addressString != NULL)
520 CFRelease(interfacePrivate->addressString);
521
522 if (interfacePrivate->configurationAction != NULL)
523 CFRelease(interfacePrivate->configurationAction);
524
525 if (interfacePrivate->location != NULL)
526 CFRelease(interfacePrivate->location);
527
528 if (interfacePrivate->path != NULL)
529 CFRelease(interfacePrivate->path);
530
531 if (interfacePrivate->overrides != NULL)
532 CFRelease(interfacePrivate->overrides);
533
534 if (interfacePrivate->prefix != NULL)
535 CFRelease(interfacePrivate->prefix);
536
537 if (interfacePrivate->type != NULL)
538 CFRelease(interfacePrivate->type);
539
540 if (interfacePrivate->unit != NULL)
541 CFRelease(interfacePrivate->unit);
542
543 if (interfacePrivate->family != NULL)
544 CFRelease(interfacePrivate->family);
545
546 if (interfacePrivate->subfamily != NULL)
547 CFRelease(interfacePrivate->subfamily);
548
549 if (interfacePrivate->usb.name != NULL)
550 CFRelease(interfacePrivate->usb.name);
551
552 if (interfacePrivate->usb.pid != NULL)
553 CFRelease(interfacePrivate->usb.pid);
554
555 if (interfacePrivate->usb.vid != NULL)
556 CFRelease(interfacePrivate->usb.vid);
557
558 if (interfacePrivate->bond.interfaces != NULL)
559 CFRelease(interfacePrivate->bond.interfaces);
560
561 if (interfacePrivate->bond.mode != NULL)
562 CFRelease(interfacePrivate->bond.mode);
563
564 if (interfacePrivate->bond.options != NULL)
565 CFRelease(interfacePrivate->bond.options);
566
567 if (interfacePrivate->bridge.interfaces != NULL)
568 CFRelease(interfacePrivate->bridge.interfaces);
569
570 if (interfacePrivate->bridge.options != NULL)
571 CFRelease(interfacePrivate->bridge.options);
572
573 if (interfacePrivate->vlan.interface != NULL)
574 CFRelease(interfacePrivate->vlan.interface);
575
576 if (interfacePrivate->vlan.tag != NULL)
577 CFRelease(interfacePrivate->vlan.tag);
578
579 if (interfacePrivate->vlan.options != NULL)
580 CFRelease(interfacePrivate->vlan.options);
581 #if !TARGET_OS_SIMULATOR
582 if (interfacePrivate->IPMonitorControl != NULL)
583 CFRelease(interfacePrivate->IPMonitorControl);
584 #endif // !TARGET_OS_SIMULATOR
585 return;
586 }
587
588
589 static Boolean
590 __SCNetworkInterfaceEqual(CFTypeRef cf1, CFTypeRef cf2)
591 {
592 SCNetworkInterfacePrivateRef if1 = (SCNetworkInterfacePrivateRef)cf1;
593 SCNetworkInterfacePrivateRef if2 = (SCNetworkInterfacePrivateRef)cf2;
594
595 if (if1 == if2)
596 return TRUE;
597
598 if (!CFEqual(if1->interface_type, if2->interface_type)) {
599 return FALSE; // if not the same interface type
600 }
601
602 if (!_SC_CFEqual(if1->entity_device, if2->entity_device)) {
603 return FALSE; // if not the same device
604 }
605
606 if ((if1->entity_device_unique != NULL) && (if2->entity_device_unique != NULL)) {
607 if (!_SC_CFEqual(if1->entity_device_unique, if2->entity_device_unique)) {
608 return FALSE; // if not the same device unique identifier
609 }
610 } else if ((if1->entity_device_unique != NULL) || (if2->entity_device_unique != NULL)) {
611 CFStringRef name1;
612 CFStringRef name2;
613
614 name1 = __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef)if1);
615 name2 = __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef)if2);
616 if ((name1 != NULL) && (name2 != NULL) && !_SC_CFEqual(name1, name2)) {
617 return FALSE; // if same device but not the same display name
618 }
619 }
620
621 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeBond)) {
622 if (!_SC_CFEqual(if1->bond.interfaces, if2->bond.interfaces)) {
623 return FALSE; // if not the same interfaces
624 }
625 if (!_SC_CFEqual(if1->bond.mode, if2->bond.mode)) {
626 return FALSE; // if not the same mode
627 }
628 }
629
630 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeBridge)) {
631 if (!_SC_CFEqual(if1->bridge.interfaces, if2->bridge.interfaces)) {
632 return FALSE; // if not the same interfaces
633 }
634 }
635
636 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeVLAN)) {
637 if (!_SC_CFEqual(if1->vlan.interface, if2->vlan.interface)) {
638 return FALSE; // if not the same physical interface
639 }
640 if (!_SC_CFEqual(if1->vlan.tag, if2->vlan.tag)) {
641 return FALSE; // if not the same tag
642 }
643 }
644
645 if (!_SC_CFEqual(if1->interface, if2->interface)) {
646 return FALSE; // if not the same layering
647 }
648
649 return TRUE;
650 }
651
652
653 static CFHashCode
654 __SCNetworkInterfaceHash(CFTypeRef cf)
655 {
656 CFHashCode hash = 0;
657 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
658
659 if (interfacePrivate->entity_device != NULL) {
660 if (interfacePrivate->entity_device_unique == NULL) {
661 hash = CFHash(interfacePrivate->entity_device);
662 } else {
663 CFStringRef str;
664
665 str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@+%@"),
666 interfacePrivate->entity_device,
667 interfacePrivate->entity_device_unique);
668 hash = CFHash(str);
669 CFRelease(str);
670 }
671 }
672
673 return hash;
674 }
675
676
677 static void
678 __SCNetworkInterfaceInitialize(void)
679 {
680 kern_return_t kr;
681
682 // register w/CF
683 __kSCNetworkInterfaceTypeID = _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass);
684
685 // initialize __kSCNetworkInterfaceIPv4
686 _CFRuntimeInitStaticInstance(&__kSCNetworkInterfaceIPv4, __kSCNetworkInterfaceTypeID);
687 __kSCNetworkInterfaceIPv4.interface_type = kSCNetworkInterfaceTypeIPv4;
688 __kSCNetworkInterfaceIPv4.localized_key = CFSTR("ipv4");
689
690 // initialize __kSCNetworkInterfaceLoopback
691 _CFRuntimeInitStaticInstance(&__kSCNetworkInterfaceLoopback, __kSCNetworkInterfaceTypeID);
692 __kSCNetworkInterfaceLoopback.interface_type = kSCNetworkInterfaceTypeLoopback;
693 __kSCNetworkInterfaceLoopback.localized_key = CFSTR("loopback");
694 __kSCNetworkInterfaceLoopback.entity_device = CFRetain(CFSTR("lo0"));
695 __kSCNetworkInterfaceLoopback.entity_type = kSCValNetInterfaceTypeLoopback;
696
697 // get CFBundleRef for SystemConfiguration.framework
698 bundle = _SC_CFBundleGet();
699
700 // get mach port used to communication with IOKit
701 kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
702 if (kr != kIOReturnSuccess) {
703 SC_log(LOG_NOTICE, "could not get IOMasterPort, kr = 0x%x", kr);
704 }
705
706 return;
707 }
708
709
710 __private_extern__
711 SCNetworkInterfacePrivateRef
712 __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator,
713 SCNetworkInterfaceRef interface,
714 SCPreferencesRef prefs,
715 CFStringRef serviceID)
716 {
717 SCNetworkInterfacePrivateRef interfacePrivate;
718 uint32_t size;
719
720 /* initialize runtime */
721 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
722
723 /* allocate target */
724 size = sizeof(SCNetworkInterfacePrivate) - sizeof(CFRuntimeBase);
725 interfacePrivate = (SCNetworkInterfacePrivateRef)_CFRuntimeCreateInstance(allocator,
726 __kSCNetworkInterfaceTypeID,
727 size,
728 NULL);
729 if (interfacePrivate == NULL) {
730 return NULL;
731 }
732
733 /* initialize non-zero/NULL members */
734 interfacePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL;
735 interfacePrivate->prefs = (prefs != NULL) ? CFRetain(prefs) : NULL;
736 interfacePrivate->serviceID = (serviceID != NULL) ? CFRetain(serviceID) : NULL;
737 interfacePrivate->sort_order = kSortUnknown;
738
739 return interfacePrivate;
740 }
741
742
743 __private_extern__
744 Boolean
745 __SCNetworkInterfaceSupportsVLAN(CFStringRef bsd_if)
746 {
747 char * buf = NULL;
748 size_t buf_len = 0;
749 struct if_msghdr * ifm;
750 char * if_name = NULL;
751 unsigned int if_index;
752 int mib[6];
753 Boolean vlanOK = FALSE;
754
755 // get the interface index
756 if_name = _SC_cfstring_to_cstring(bsd_if, NULL, 0, kCFStringEncodingASCII);
757 if (if_name == NULL) {
758 return FALSE; // if conversion error
759 }
760 if_index = if_nametoindex(if_name);
761 if (if_index == 0) {
762 goto done; // if unknown interface
763 }
764
765 // get information for the specified interface
766 mib[0] = CTL_NET;
767 mib[1] = PF_ROUTE;
768 mib[2] = 0;
769 mib[3] = AF_LINK;
770 mib[4] = NET_RT_IFLIST;
771 mib[5] = if_index; /* ask for exactly one interface */
772
773 if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) == -1) {
774 SC_log(LOG_NOTICE, "sysctl() size failed: %s", strerror(errno));
775 goto done;
776 }
777 buf = CFAllocatorAllocate(NULL, buf_len, 0);
778 if (sysctl(mib, 6, buf, &buf_len, NULL, 0) == -1) {
779 SC_log(LOG_NOTICE, "sysctl() failed: %s", strerror(errno));
780 goto done;
781 }
782
783 // check the link type and hwassist flags
784 // ALIGN: buf is aligned
785 ifm = (struct if_msghdr *)(void *)buf;
786 switch (ifm->ifm_type) {
787 case RTM_IFINFO : {
788 #if defined(IF_HWASSIST_VLAN_TAGGING) && defined(IF_HWASSIST_VLAN_MTU)
789 struct if_data *if_data = &ifm->ifm_data;
790
791 if (if_data->ifi_hwassist & (IF_HWASSIST_VLAN_TAGGING | IF_HWASSIST_VLAN_MTU)) {
792 vlanOK = TRUE;
793 }
794 #endif
795 break;
796 }
797 }
798
799 done :
800
801 if (if_name != NULL) CFAllocatorDeallocate(NULL, if_name);
802 if (buf != NULL) CFAllocatorDeallocate(NULL, buf);
803
804 return vlanOK;
805 }
806
807
808 static CFDataRef
809 __SCCopyMacAddress(CFStringRef ifname)
810 {
811 struct ifaddrs *ifap;
812 char ifname_c[IFNAMSIZ];
813 struct ifaddrs *ifp;
814 CFDataRef macAddress = NULL;
815
816 if(_SC_cfstring_to_cstring(ifname,
817 ifname_c,
818 sizeof(ifname_c),
819 kCFStringEncodingUTF8) == NULL) {
820 return NULL;
821 }
822
823 if (getifaddrs(&ifap) == -1) {
824 _SCErrorSet(errno);
825 SC_log(LOG_NOTICE, "getifaddrs() failed: %s", strerror(errno));
826 return NULL;
827 }
828
829 for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) {
830 struct sockaddr_dl *sdl;
831
832 if(strcmp(ifname_c, ifp->ifa_name) != 0) {
833 continue;
834 }
835
836 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
837 sdl = (struct sockaddr_dl *)(void *)ifp->ifa_addr;
838 if (sdl->sdl_family != AF_LINK) {
839 continue;
840 }
841
842 macAddress = CFDataCreate(NULL, (UInt8 *)LLADDR(sdl), sdl->sdl_alen);
843 break;
844 }
845 freeifaddrs(ifap);
846 return macAddress;
847 }
848
849
850 __private_extern__
851 SCNetworkInterfacePrivateRef
852 _SCBondInterfaceCreatePrivate(CFAllocatorRef allocator,
853 CFStringRef bond_if)
854 {
855 SCNetworkInterfacePrivateRef interfacePrivate;
856
857 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL);
858 if (interfacePrivate == NULL) {
859 return NULL;
860 }
861
862 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBond;
863 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
864 interfacePrivate->entity_device = CFStringCreateCopy(allocator, bond_if);
865 interfacePrivate->address = __SCCopyMacAddress(interfacePrivate->entity_device);
866 interfacePrivate->builtin = TRUE;
867 interfacePrivate->supportsVLAN = __SCNetworkInterfaceSupportsVLAN(bond_if);
868 interfacePrivate->sort_order = kSortBond;
869
870 interfacePrivate->localized_key = CFSTR("bond");
871 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
872
873 interfacePrivate->bond.interfaces = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
874 // interfacePrivate->bond.mode = NULL;
875 // interfacePrivate->bond.options = NULL;
876
877 return interfacePrivate;
878 }
879
880
881 __private_extern__
882 SCNetworkInterfacePrivateRef
883 _SCBridgeInterfaceCreatePrivate(CFAllocatorRef allocator,
884 CFStringRef bridge_if)
885 {
886 SCNetworkInterfacePrivateRef interfacePrivate;
887
888 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL);
889 if (interfacePrivate == NULL) {
890 return NULL;
891 }
892
893 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBridge;
894 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
895 interfacePrivate->entity_device = CFStringCreateCopy(allocator, bridge_if);
896 interfacePrivate->address = __SCCopyMacAddress(interfacePrivate->entity_device);
897 interfacePrivate->builtin = TRUE;
898 interfacePrivate->supportsVLAN = __SCNetworkInterfaceSupportsVLAN(bridge_if);
899 interfacePrivate->sort_order = kSortBridge;
900
901 interfacePrivate->localized_key = CFSTR("bridge");
902 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
903
904 interfacePrivate->bridge.interfaces = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
905 // interfacePrivate->bridge.options = NULL;
906
907 return interfacePrivate;
908 }
909
910
911 __private_extern__
912 SCNetworkInterfacePrivateRef
913 _SCVLANInterfaceCreatePrivate(CFAllocatorRef allocator,
914 CFStringRef vlan_if)
915 {
916 SCNetworkInterfacePrivateRef interfacePrivate;
917
918 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL);
919 if (interfacePrivate == NULL) {
920 return NULL;
921 }
922
923 interfacePrivate->interface_type = kSCNetworkInterfaceTypeVLAN;
924 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
925 interfacePrivate->entity_device = CFStringCreateCopy(allocator, vlan_if);
926 interfacePrivate->address = __SCCopyMacAddress(interfacePrivate->entity_device);
927 interfacePrivate->builtin = TRUE;
928 interfacePrivate->sort_order = kSortVLAN;
929
930 interfacePrivate->localized_key = CFSTR("vlan");
931 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
932
933 // interfacePrivate->vlan.interface = NULL;
934 // interfacePrivate->vlan.tag = NULL;
935 // interfacePrivate->vlan.options = NULL;
936
937 return interfacePrivate;
938 }
939
940
941 #pragma mark -
942 #pragma mark Interface ordering
943
944
945 static CF_RETURNS_RETAINED CFArrayRef
946 split_path(CFStringRef path)
947 {
948 CFArrayRef components;
949 CFMutableStringRef nPath;
950
951 // turn '@'s into '/'s
952 nPath = CFStringCreateMutableCopy(NULL, 0, path);
953 (void) CFStringFindAndReplace(nPath,
954 CFSTR("@"),
955 CFSTR("/"),
956 CFRangeMake(0, CFStringGetLength(nPath)),
957 0);
958
959 // split path into components to be compared
960 components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
961 CFRelease(nPath);
962
963 return components;
964 }
965
966
967 CFComparisonResult
968 _SCNetworkInterfaceCompare(const void *val1, const void *val2, void *context)
969 {
970 #pragma unused(context)
971 SCNetworkInterfacePrivateRef dev1 = (SCNetworkInterfacePrivateRef)val1;
972 SCNetworkInterfacePrivateRef dev2 = (SCNetworkInterfacePrivateRef)val2;
973 CFComparisonResult res = kCFCompareEqualTo;
974
975 /* sort by interface type */
976 if (dev1->sort_order != dev2->sort_order) {
977 if (dev1->sort_order < dev2->sort_order) {
978 res = kCFCompareLessThan;
979 } else {
980 res = kCFCompareGreaterThan;
981 }
982 return (res);
983 }
984
985 /* built-in interfaces sort first */
986 if (dev1->builtin != dev2->builtin) {
987 if (dev1->builtin) {
988 res = kCFCompareLessThan;
989 } else {
990 res = kCFCompareGreaterThan;
991 }
992 return (res);
993 }
994
995 /* ... and then, sort built-in interfaces by "location" */
996 if (dev1->builtin) {
997 if (dev1->location != dev2->location) {
998 if (isA_CFString(dev1->location)) {
999 if (isA_CFString(dev2->location)) {
1000 res = CFStringCompare(dev1->location, dev2->location, 0);
1001 } else {
1002 res = kCFCompareLessThan;
1003 }
1004 } else {
1005 res = kCFCompareGreaterThan;
1006 }
1007
1008 if (res != kCFCompareEqualTo) {
1009 return (res);
1010 }
1011 }
1012 }
1013
1014 /* ... and, then sort by IOPathMatch */
1015 if ((dev1->path != NULL) && (dev2->path != NULL)) {
1016 CFArrayRef elements1;
1017 CFArrayRef elements2;
1018 CFIndex i;
1019 CFIndex n;
1020 CFIndex n1;
1021 CFIndex n2;
1022
1023 elements1 = split_path(dev1->path);
1024 n1 = CFArrayGetCount(elements1);
1025
1026 elements2 = split_path(dev2->path);
1027 n2 = CFArrayGetCount(elements2);
1028
1029 n = (n1 <= n2) ? n1 : n2;
1030 for (i = 0; i < n; i++) {
1031 CFStringRef e1;
1032 CFStringRef e2;
1033 char *end;
1034 quad_t q1;
1035 quad_t q2;
1036 char *str;
1037 Boolean isNum;
1038
1039 e1 = CFArrayGetValueAtIndex(elements1, i);
1040 e2 = CFArrayGetValueAtIndex(elements2, i);
1041
1042 str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingUTF8);
1043 errno = 0;
1044 q1 = strtoq(str, &end, 16);
1045 isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
1046 CFAllocatorDeallocate(NULL, str);
1047
1048 if (isNum) {
1049 // if e1 is a valid numeric string
1050 str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingUTF8);
1051 errno = 0;
1052 q2 = strtoq(str, &end, 16);
1053 isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
1054 CFAllocatorDeallocate(NULL, str);
1055
1056 if (isNum) {
1057 // if e2 is also a valid numeric string
1058
1059 if (q1 == q2) {
1060 res = kCFCompareEqualTo;
1061 continue;
1062 } else if (q1 < q2) {
1063 res = kCFCompareLessThan;
1064 } else {
1065 res = kCFCompareGreaterThan;
1066 }
1067 break;
1068 }
1069 }
1070
1071 res = CFStringCompare(e1, e2, 0);
1072 if (res != kCFCompareEqualTo) {
1073 break;
1074 }
1075 }
1076
1077 if (res == kCFCompareEqualTo) {
1078 if (n1 < n2) {
1079 res = kCFCompareLessThan;
1080 } else if (n1 < n2) {
1081 res = kCFCompareGreaterThan;
1082 }
1083 }
1084
1085 CFRelease(elements1);
1086 CFRelease(elements2);
1087
1088 if (res != kCFCompareEqualTo) {
1089 return (res);
1090 }
1091 }
1092
1093 /* ... and, then sort by BSD interface name */
1094 if ((dev1->entity_device != NULL) && (dev2->entity_device != NULL)) {
1095 res = CFStringCompare(dev1->entity_device, dev2->entity_device, 0);
1096 if (res != kCFCompareEqualTo) {
1097 return (res);
1098 }
1099 }
1100
1101 /* ... and lastly, sort by BSD interface unique identifier */
1102 if ((dev1->entity_device_unique != NULL) && (dev2->entity_device_unique != NULL)) {
1103 res = CFStringCompare(dev1->entity_device_unique, dev2->entity_device_unique, 0);
1104 // if (res != kCFCompareEqualTo) {
1105 // return (res);
1106 // }
1107 }
1108
1109 return res;
1110 }
1111
1112
1113 static void
1114 sort_interfaces(CFMutableArrayRef all_interfaces)
1115 {
1116 CFIndex n;
1117
1118 n = CFArrayGetCount(all_interfaces);
1119 if (n < 2) {
1120 return;
1121 }
1122
1123 CFArraySortValues(all_interfaces, CFRangeMake(0, n), _SCNetworkInterfaceCompare, NULL);
1124 return;
1125 }
1126
1127
1128 __private_extern__
1129 int
1130 __SCNetworkInterfaceOrder(SCNetworkInterfaceRef interface)
1131 {
1132 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
1133
1134 return interfacePrivate->sort_order;
1135 }
1136
1137
1138 #pragma mark -
1139 #pragma mark Interface details
1140
1141
1142 static CFStringRef
1143 IOCopyCFStringValue(CFTypeRef ioVal)
1144 {
1145 if (isA_CFString(ioVal)) {
1146 return CFStringCreateCopy(NULL, ioVal);
1147 }
1148
1149 if (isA_CFData(ioVal)) {
1150 return CFStringCreateWithCString(NULL,
1151 (const char *)CFDataGetBytePtr(ioVal),
1152 kCFStringEncodingUTF8);
1153 }
1154
1155 return NULL;
1156 }
1157
1158
1159 static CFStringRef
1160 IODictionaryCopyBSDName(CFDictionaryRef io_dict)
1161 {
1162 CFStringRef if_bsdName;
1163 CFStringRef if_prefix;
1164 CFNumberRef if_unit;
1165
1166 if_bsdName = CFDictionaryGetValue(io_dict, CFSTR(kIOBSDNameKey));
1167 if (if_bsdName != NULL) {
1168 return IOCopyCFStringValue(if_bsdName);
1169 }
1170
1171 // no BSD name, get interface prefix and unit
1172 if_prefix = CFDictionaryGetValue(io_dict, CFSTR(kIOInterfaceNamePrefix));
1173 if_unit = CFDictionaryGetValue(io_dict, CFSTR(kIOInterfaceUnit));
1174 if (isA_CFString(if_prefix) && isA_CFNumber(if_unit)) {
1175 // if both prefix and unit available, construct BSD name
1176 if_bsdName = CFStringCreateWithFormat(NULL,
1177 NULL,
1178 CFSTR("%@%@"),
1179 if_prefix,
1180 if_unit);
1181 }
1182
1183 return if_bsdName;
1184 };
1185
1186
1187 static CFStringRef
1188 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict, CFStringRef io_key)
1189 {
1190 CFTypeRef ioVal;
1191
1192 ioVal = CFDictionaryGetValue(io_dict, io_key);
1193 return IOCopyCFStringValue(ioVal);
1194 }
1195
1196
1197 static Boolean
1198 IOStringValueHasPrefix(CFTypeRef ioVal, CFStringRef prefix)
1199 {
1200 Boolean match = FALSE;
1201 CFIndex prefixLen = CFStringGetLength(prefix);
1202 CFStringRef str = NULL;
1203
1204 if (!isA_CFString(ioVal)) {
1205 if (isA_CFData(ioVal)) {
1206 str = CFStringCreateWithCStringNoCopy(NULL,
1207 (const char *)CFDataGetBytePtr(ioVal),
1208 kCFStringEncodingUTF8,
1209 kCFAllocatorNull);
1210 ioVal = str;
1211 } else {
1212 return FALSE;
1213 }
1214 }
1215
1216 if ((ioVal != NULL) &&
1217 (CFStringGetLength(ioVal) >= prefixLen) &&
1218 (CFStringCompareWithOptions(ioVal,
1219 prefix,
1220 CFRangeMake(0, prefixLen),
1221 kCFCompareCaseInsensitive) == kCFCompareEqualTo)) {
1222 match = TRUE;
1223 }
1224
1225 if (str != NULL) CFRelease(str);
1226 return match;
1227 }
1228
1229
1230 static const struct {
1231 const CFStringRef name;
1232 const CFStringRef slot;
1233 } slot_mappings[] = {
1234 // Beige G3
1235 { CFSTR("A1") , CFSTR("1") },
1236 { CFSTR("B1") , CFSTR("2") },
1237 { CFSTR("C1") , CFSTR("3") },
1238
1239 // Blue&White G3, Yikes G4
1240 { CFSTR("J12"), CFSTR("1") },
1241 { CFSTR("J11"), CFSTR("2") },
1242 { CFSTR("J10"), CFSTR("3") },
1243 { CFSTR("J9"), CFSTR("4") },
1244
1245 // AGP G4
1246 { CFSTR("A") , CFSTR("1") },
1247 { CFSTR("B") , CFSTR("2") },
1248 { CFSTR("C") , CFSTR("3") },
1249 { CFSTR("D") , CFSTR("4") },
1250
1251 // Digital Audio G4 (and later models)
1252 { CFSTR("1") , CFSTR("1") },
1253 { CFSTR("2") , CFSTR("2") },
1254 { CFSTR("3") , CFSTR("3") },
1255 { CFSTR("4") , CFSTR("4") },
1256 { CFSTR("5") , CFSTR("5") }
1257 };
1258
1259
1260 static const CFStringRef slot_prefixes[] = {
1261 CFSTR("thunderbolt slot "),
1262 CFSTR("pci slot "),
1263 CFSTR("slot-"),
1264 };
1265
1266
1267 static CF_RETURNS_RETAINED CFStringRef
1268 pci_slot(io_registry_entry_t interface, CFTypeRef *pci_slot_name)
1269 {
1270 kern_return_t kr;
1271 io_registry_entry_t parent;
1272 CFMutableStringRef slot;
1273 CFTypeRef slot_name;
1274
1275 slot = NULL;
1276 if (pci_slot_name != NULL) *pci_slot_name = NULL;
1277
1278 slot_name = IORegistryEntryCreateCFProperty(interface, CFSTR("AAPL,slot-name"), NULL, 0);
1279 if (slot_name != NULL) {
1280 slot = CFStringCreateMutable(NULL, 0);
1281 if (isA_CFString(slot_name)) {
1282 if (pci_slot_name != NULL) *pci_slot_name = CFStringCreateCopy(NULL, slot_name);
1283 CFStringAppend(slot, slot_name);
1284 } else if (isA_CFData(slot_name)) {
1285 if (pci_slot_name != NULL) *pci_slot_name = CFDataCreateCopy(NULL, slot_name);
1286 CFStringAppendCString(slot,
1287 (const char *)CFDataGetBytePtr(slot_name),
1288 kCFStringEncodingUTF8);
1289 }
1290
1291 for (size_t i = 0; i < sizeof(slot_prefixes)/sizeof(slot_prefixes[0]); i++) {
1292 CFIndex len;
1293
1294 len = CFStringGetLength(slot_prefixes[i]);
1295 if (CFStringGetLength(slot) > len) {
1296 (void) CFStringFindAndReplace(slot,
1297 slot_prefixes[i],
1298 CFSTR(""),
1299 CFRangeMake(0, len),
1300 kCFCompareCaseInsensitive|kCFCompareAnchored);
1301 }
1302 }
1303
1304 for (size_t i = 0; i < sizeof(slot_mappings)/sizeof(slot_mappings[0]); i++) {
1305 if (CFStringCompare(slot,
1306 slot_mappings[i].name,
1307 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
1308 CFRelease(slot);
1309 slot = (CFMutableStringRef)CFRetain(slot_mappings[i].slot);
1310 break;
1311 }
1312 }
1313
1314 CFRelease(slot_name);
1315 }
1316
1317 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &parent);
1318 switch (kr) {
1319 case kIOReturnSuccess : {
1320 CFTypeRef parent_pci_slot_name = NULL;
1321 CFStringRef parent_slot;
1322
1323 parent_slot = pci_slot(parent, &parent_pci_slot_name);
1324 if (parent_slot != NULL) {
1325 if (slot != NULL) CFRelease(slot);
1326 slot = (CFMutableStringRef)parent_slot;
1327
1328 if (pci_slot_name != NULL) {
1329 if (*pci_slot_name != NULL) CFRelease(*pci_slot_name);
1330 *pci_slot_name = parent_pci_slot_name;
1331 } else {
1332 CFRelease(parent_pci_slot_name);
1333 }
1334 }
1335
1336 IOObjectRelease(parent);
1337 break;
1338 }
1339 case kIOReturnNoDevice :
1340 // if we have hit the root node
1341 break;
1342 default :
1343 SC_log(LOG_INFO, "IORegistryEntryGetParentEntry() failed, kr = 0x%x", kr);
1344 break;
1345 }
1346
1347 return slot;
1348 }
1349
1350
1351 static CFComparisonResult
1352 compare_bsdNames(const void *val1, const void *val2, void *context)
1353 {
1354 #pragma unused(context)
1355 CFStringRef bsd1 = (CFStringRef)val1;
1356 CFStringRef bsd2 = (CFStringRef)val2;
1357
1358 return CFStringCompare(bsd1, bsd2, 0);
1359 }
1360
1361
1362 static CF_RETURNS_RETAINED CFStringRef
1363 pci_port(CFTypeRef slot_name, int ift, CFStringRef bsdName)
1364 {
1365 CFIndex n;
1366 CFStringRef port_name = NULL;
1367 CFMutableArrayRef port_names;
1368
1369 kern_return_t kr;
1370 CFStringRef match_keys[2];
1371 CFTypeRef match_vals[2];
1372 CFDictionaryRef match_dict;
1373 CFDictionaryRef matching;
1374 io_registry_entry_t slot;
1375 io_iterator_t slot_iterator = MACH_PORT_NULL;
1376
1377 match_keys[0] = CFSTR("AAPL,slot-name");
1378 match_vals[0] = slot_name;
1379
1380 match_dict = CFDictionaryCreate(NULL,
1381 (const void **)match_keys,
1382 (const void **)match_vals,
1383 1,
1384 &kCFTypeDictionaryKeyCallBacks,
1385 &kCFTypeDictionaryValueCallBacks);
1386
1387 match_keys[0] = CFSTR(kIOProviderClassKey);
1388 match_vals[0] = CFSTR("IOPCIDevice");
1389
1390 match_keys[1] = CFSTR(kIOPropertyMatchKey);
1391 match_vals[1] = match_dict;
1392
1393 // note: the "matching" dictionary will be consumed by the following
1394 matching = CFDictionaryCreate(NULL,
1395 (const void **)match_keys,
1396 (const void **)match_vals,
1397 sizeof(match_keys)/sizeof(match_keys[0]),
1398 &kCFTypeDictionaryKeyCallBacks,
1399 &kCFTypeDictionaryValueCallBacks);
1400 CFRelease(match_dict);
1401
1402 kr = IOServiceGetMatchingServices(masterPort, matching, &slot_iterator);
1403 if (kr != kIOReturnSuccess) {
1404 SC_log(LOG_INFO, "IOServiceGetMatchingServices() failed, kr = 0x%x", kr);
1405 return MACH_PORT_NULL;
1406 }
1407
1408 port_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1409
1410 while ((slot = IOIteratorNext(slot_iterator)) != MACH_PORT_NULL) {
1411 io_registry_entry_t child;
1412 io_iterator_t child_iterator = MACH_PORT_NULL;
1413
1414 kr = IORegistryEntryCreateIterator(slot,
1415 kIOServicePlane,
1416 kIORegistryIterateRecursively,
1417 &child_iterator);
1418 if (kr != kIOReturnSuccess) {
1419 SC_log(LOG_INFO, "IORegistryEntryCreateIterator() failed, kr = 0x%x", kr);
1420 CFRelease(port_names);
1421 return MACH_PORT_NULL;
1422 }
1423
1424 while ((child = IOIteratorNext(child_iterator)) != MACH_PORT_NULL) {
1425 if (IOObjectConformsTo(child, kIONetworkInterfaceClass)) {
1426 CFMutableDictionaryRef interface_dict = NULL;
1427
1428 (void) IORegistryEntryCreateCFProperties(child, &interface_dict, NULL, kNilOptions);
1429 if (interface_dict != NULL) {
1430 CFNumberRef child_if_type;
1431 int child_ift = ift;
1432
1433 child_if_type = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType));
1434 if (child_if_type != NULL) {
1435 if (!isA_CFNumber(child_if_type) ||
1436 !CFNumberGetValue(child_if_type, kCFNumberIntType, &child_ift)) {
1437 // assume that it's a match
1438 child_ift = ift;
1439 }
1440 }
1441
1442 if (ift == child_ift) {
1443 CFStringRef if_bsdName;
1444
1445 if_bsdName = IODictionaryCopyBSDName(interface_dict);
1446 if (if_bsdName != NULL) {
1447 CFArrayAppendValue(port_names, if_bsdName);
1448 CFRelease(if_bsdName);
1449 }
1450 }
1451
1452 CFRelease(interface_dict);
1453 }
1454 }
1455 IOObjectRelease(child);
1456 }
1457 IOObjectRelease(child_iterator);
1458 IOObjectRelease(slot);
1459 }
1460 IOObjectRelease(slot_iterator);
1461
1462 n = CFArrayGetCount(port_names);
1463 if (n > 1) {
1464 CFArraySortValues(port_names, CFRangeMake(0, n), compare_bsdNames, NULL);
1465 n = CFArrayGetFirstIndexOfValue(port_names, CFRangeMake(0, n), bsdName);
1466 if (n != kCFNotFound) {
1467 port_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"), n + 1);
1468 }
1469 }
1470
1471 CFRelease(port_names);
1472 return port_name;
1473 }
1474
1475
1476 static Boolean
1477 pci_slot_info(io_registry_entry_t interface, int ift, CFStringRef *slot_name, CFStringRef *port_name)
1478 {
1479 CFStringRef bsd_name = NULL;
1480 CFMutableDictionaryRef interface_dict = NULL;
1481 Boolean ok = FALSE;
1482 CFTypeRef pci_slot_name;
1483
1484 *slot_name = NULL;
1485 *port_name = NULL;
1486
1487 (void) IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions);
1488 if (interface_dict != NULL) {
1489 bsd_name = IODictionaryCopyBSDName(interface_dict);
1490 CFRelease(interface_dict);
1491 }
1492
1493 if (bsd_name == NULL) {
1494 return FALSE;
1495 }
1496
1497 *slot_name = pci_slot(interface, &pci_slot_name);
1498 if (*slot_name != NULL) {
1499 if (pci_slot_name != NULL) {
1500 *port_name = pci_port(pci_slot_name, ift, bsd_name);
1501 CFRelease(pci_slot_name);
1502 }
1503 ok = TRUE;
1504 }
1505
1506 CFRelease(bsd_name);
1507 return ok;
1508 }
1509
1510
1511 static Boolean
1512 isBuiltin(io_registry_entry_t interface)
1513 {
1514 CFStringRef slot;
1515
1516 slot = pci_slot(interface, NULL);
1517 if (slot != NULL) {
1518 // interfaces which have a "slot" are not built-in
1519 CFRelease(slot);
1520 return FALSE;
1521 }
1522
1523 return TRUE;
1524 }
1525
1526
1527 static Boolean
1528 isBluetoothBuiltin(Boolean *haveController)
1529 {
1530 Boolean builtin = FALSE;
1531 io_object_t hciController;
1532 io_iterator_t iter = MACH_PORT_NULL;
1533 kern_return_t kr;
1534
1535 kr = IOServiceGetMatchingServices(masterPort,
1536 IOServiceMatching("IOBluetoothHCIController"),
1537 &iter);
1538 if ((kr != kIOReturnSuccess) || (iter == MACH_PORT_NULL)) {
1539 if (kr != kIOReturnSuccess) {
1540 SC_log(LOG_INFO, "IOServiceGetMatchingServices() failed, kr = 0x%x", kr);
1541 }
1542 *haveController = FALSE;
1543 return FALSE;
1544 }
1545 *haveController = TRUE;
1546
1547 hciController = IOIteratorNext(iter);
1548 IOObjectRelease(iter);
1549 if(hciController != MACH_PORT_NULL) {
1550 #if !TARGET_OS_SIMULATOR
1551 CFNumberRef idVendor;
1552
1553 idVendor = IORegistryEntryCreateCFProperty(hciController, CFSTR(kUSBVendorID), NULL, 0);
1554 if (idVendor != NULL) {
1555 int idVendorVal;
1556
1557 if (isA_CFNumber(idVendor) &&
1558 CFNumberGetValue(idVendor, kCFNumberIntType, &idVendorVal) &&
1559 (idVendorVal == kIOUSBVendorIDAppleComputer)) {
1560 builtin = TRUE;
1561 }
1562
1563 CFRelease(idVendor);
1564 }
1565 #endif // !TARGET_OS_SIMULATOR
1566
1567 IOObjectRelease(hciController);
1568 }
1569
1570 return builtin;
1571 }
1572
1573
1574 static Boolean
1575 isThunderbolt(io_registry_entry_t interface)
1576 {
1577 CFTypeRef val;
1578
1579 val = IORegistryEntrySearchCFProperty(interface,
1580 kIOServicePlane,
1581 CFSTR(kPCIThunderboltString),
1582 NULL,
1583 kIORegistryIterateRecursively | kIORegistryIterateParents);
1584 if (val != NULL) {
1585 CFRelease(val);
1586 return TRUE;
1587 }
1588
1589 return FALSE;
1590 }
1591
1592
1593 static void
1594 processUSBInterface(SCNetworkInterfacePrivateRef interfacePrivate,
1595 io_registry_entry_t interface,
1596 CFDictionaryRef interface_dict,
1597 io_registry_entry_t controller,
1598 CFDictionaryRef controller_dict,
1599 io_registry_entry_t bus,
1600 CFDictionaryRef bus_dict)
1601 {
1602 #if TARGET_OS_SIMULATOR
1603 #pragma unused(interfacePrivate)
1604 #pragma unused(interface)
1605 #endif // TARGET_OS_SIMULATOR
1606 #pragma unused(interface_dict)
1607 #pragma unused(controller)
1608 #pragma unused(controller_dict)
1609 #pragma unused(bus)
1610 #pragma unused(bus_dict)
1611 #if !TARGET_OS_SIMULATOR
1612 // capture USB info
1613 if (interfacePrivate->usb.name == NULL) {
1614 interfacePrivate->usb.name = IORegistryEntrySearchCFProperty(interface,
1615 kIOServicePlane,
1616 CFSTR(kUSBProductString),
1617 NULL,
1618 kIORegistryIterateRecursively | kIORegistryIterateParents);
1619 }
1620 if (interfacePrivate->usb.vid == NULL) {
1621 interfacePrivate->usb.vid = IORegistryEntrySearchCFProperty(interface,
1622 kIOServicePlane,
1623 CFSTR(kUSBVendorID),
1624 NULL,
1625 kIORegistryIterateRecursively | kIORegistryIterateParents);
1626 }
1627 if (interfacePrivate->usb.pid == NULL) {
1628 interfacePrivate->usb.pid = IORegistryEntrySearchCFProperty(interface,
1629 kIOServicePlane,
1630 CFSTR(kUSBProductID),
1631 NULL,
1632 kIORegistryIterateRecursively | kIORegistryIterateParents);
1633 }
1634 #endif // !TARGET_OS_SIMULATOR
1635
1636 return;
1637 }
1638
1639
1640 static Boolean
1641 update_interface_name(SCNetworkInterfacePrivateRef interfacePrivate,
1642 io_registry_entry_t interface,
1643 Boolean useUSBInfo)
1644 {
1645 Boolean updated = FALSE;
1646 CFTypeRef val;
1647
1648 // check if a "Product Name" has been provided
1649 val = IORegistryEntrySearchCFProperty(interface,
1650 kIOServicePlane,
1651 CFSTR(kIOPropertyProductNameKey),
1652 NULL,
1653 kIORegistryIterateRecursively | kIORegistryIterateParents);
1654 if ((val == NULL) && useUSBInfo && (interfacePrivate->usb.name != NULL)) {
1655 // else, use "USB Product Name" if available
1656 val = CFRetain(interfacePrivate->usb.name);
1657 }
1658 if (val != NULL) {
1659 CFStringRef productName;
1660
1661 productName = IOCopyCFStringValue(val);
1662 CFRelease(val);
1663
1664 if (productName != NULL) {
1665 if (CFStringGetLength(productName) > 0) {
1666 // if we have a [somewhat reasonable?] product name
1667 if (interfacePrivate->name != NULL) {
1668 CFRelease(interfacePrivate->name);
1669 }
1670 interfacePrivate->name = CFRetain(productName);
1671 if (interfacePrivate->localized_name != NULL) {
1672 CFRelease(interfacePrivate->localized_name);
1673 interfacePrivate->localized_name = NULL;
1674 }
1675 if (bundle != NULL) {
1676 interfacePrivate->localized_name = copy_interface_string(bundle, productName, TRUE);
1677 }
1678
1679 updated = TRUE;
1680 }
1681
1682 CFRelease(productName);
1683 }
1684 }
1685
1686 return updated;
1687 }
1688
1689
1690 #pragma mark -
1691 #pragma mark Interface enumeration
1692
1693
1694 typedef Boolean (*processInterface)(SCNetworkInterfacePrivateRef interfacePrivate,
1695 io_registry_entry_t interface,
1696 CFDictionaryRef interface_dict,
1697 io_registry_entry_t controller,
1698 CFDictionaryRef controller_dict,
1699 io_registry_entry_t bus,
1700 CFDictionaryRef bus_dict);
1701
1702
1703 static void
1704 merge_override(SCNetworkInterfacePrivateRef interfacePrivate,
1705 io_registry_entry_t interface,
1706 CFStringRef override)
1707 {
1708 CFStringRef key;
1709 CFTypeRef val;
1710
1711 key = CFStringCreateWithFormat(NULL, NULL, CFSTR("Device%@Overrides"), override);
1712 val = IORegistryEntrySearchCFProperty(interface,
1713 kIOServicePlane,
1714 key,
1715 NULL,
1716 kIORegistryIterateRecursively | kIORegistryIterateParents);
1717 CFRelease(key);
1718 if (val != NULL) {
1719 if (isA_CFDictionary(val)) {
1720 if (interfacePrivate->overrides == NULL) {
1721 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1722 0,
1723 &kCFTypeDictionaryKeyCallBacks,
1724 &kCFTypeDictionaryValueCallBacks);
1725 }
1726 CFDictionarySetValue(interfacePrivate->overrides, override, val);
1727 }
1728 CFRelease(val);
1729 }
1730
1731 return;
1732 }
1733
1734
1735 static Boolean
1736 processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate,
1737 io_registry_entry_t interface,
1738 CFDictionaryRef interface_dict,
1739 io_registry_entry_t controller,
1740 CFDictionaryRef controller_dict,
1741 io_registry_entry_t bus,
1742 CFDictionaryRef bus_dict)
1743 {
1744 CFDataRef data;
1745 int ift = -1;
1746 int iVal;
1747 CFNumberRef num;
1748 CFStringRef str;
1749 CFBooleanRef val;
1750
1751 // interface type
1752 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType));
1753 if (isA_CFNumber(num) &&
1754 CFNumberGetValue(num, kCFNumberIntType, &ift)) {
1755 interfacePrivate->type = CFRetain(num);
1756 } else {
1757 SC_log(LOG_INFO, "no interface type: %@", interface_dict);
1758 return FALSE;
1759 }
1760
1761 switch (ift) {
1762 case IFT_ETHER :
1763 // Type, Hardware
1764
1765 if (IOObjectConformsTo(controller, "IO80211Controller") ||
1766 IOObjectConformsTo(controller, "AirPortPCI" ) ||
1767 IOObjectConformsTo(controller, "AirPortDriver" )) {
1768 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
1769 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1770 interfacePrivate->sort_order = kSortAirPort;
1771 } else if (IOObjectConformsTo(controller, "AppleThunderboltIPPort")) {
1772 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1773 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1774 interfacePrivate->sort_order = kSortThunderbolt;
1775 } else if (IOObjectConformsTo(controller, "IOBluetoothBNEPDriver")) {
1776 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1777 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1778 interfacePrivate->sort_order = kSortBluetoothPAN_GN;
1779 } else if (IOObjectConformsTo(controller, "AppleUSBEthernetHost")) {
1780 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1781 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1782 interfacePrivate->sort_order = kSortTethered;
1783 } else if (IOObjectConformsTo(controller, "AppleUSBCDCECMData")) {
1784 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1785 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1786 interfacePrivate->sort_order = kSortWWANEthernet;
1787 }
1788
1789 if (interfacePrivate->interface_type == NULL) {
1790 val = IORegistryEntrySearchCFProperty(interface,
1791 kIOServicePlane,
1792 CFSTR(kIOUserEthernetInterfaceRoleKey),
1793 NULL,
1794 kIORegistryIterateRecursively | kIORegistryIterateParents);
1795 if (val != NULL) {
1796 if (isA_CFString(val)) {
1797 if (CFEqual(val, CFSTR(BT_PAN_NAME))) {
1798 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1799 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1800 interfacePrivate->sort_order = kSortBluetoothPAN_GN;
1801 } else if (CFEqual(val, CFSTR("Bluetooth PAN-NAP"))) {
1802 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1803 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1804 interfacePrivate->sort_order = kSortBluetoothPAN_NAP;
1805 } else if (CFEqual(val, CFSTR("Bluetooth P2P"))) {
1806 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1807 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1808 interfacePrivate->sort_order = kSortBluetoothPAN_U;
1809 }
1810 }
1811
1812 CFRelease(val);
1813 }
1814 }
1815
1816 if (interfacePrivate->interface_type == NULL) {
1817 str = IODictionaryCopyCFStringValue(bus_dict, CFSTR("name"));
1818 if (str != NULL) {
1819 if (CFEqual(str, CFSTR("radio"))) {
1820 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; // ??
1821 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1822 interfacePrivate->sort_order = kSortOtherWireless;
1823 }
1824
1825 CFRelease(str);
1826 }
1827 }
1828
1829 if (interfacePrivate->interface_type == NULL) {
1830 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1831 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet;
1832 interfacePrivate->sort_order = kSortEthernet;
1833
1834 // BOND support only enabled for ethernet devices
1835 interfacePrivate->supportsBond = TRUE;
1836 }
1837
1838 // enable Bridge support
1839 interfacePrivate->supportsBridge = TRUE;
1840
1841 // built-in
1842 val = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOBuiltin)));
1843 if (val == NULL) {
1844 val = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOPrimaryInterface)));
1845 }
1846 if (val != NULL) {
1847 interfacePrivate->builtin = CFBooleanGetValue(val);
1848 } else {
1849 interfacePrivate->builtin = isBuiltin(interface);
1850 }
1851
1852 if (!interfacePrivate->builtin &&
1853 CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) {
1854 // always treat AirPort interfaces as built-in
1855 interfacePrivate->builtin = TRUE;
1856 }
1857
1858 // location
1859 interfacePrivate->location = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOLocation));
1860 if ((interfacePrivate->location != NULL) &&
1861 (CFStringGetLength(interfacePrivate->location) == 0)) {
1862 CFRelease(interfacePrivate->location);
1863 interfacePrivate->location = NULL;
1864 }
1865
1866 // VLAN support
1867 num = CFDictionaryGetValue(controller_dict, CFSTR(kIOFeatures));
1868 if (isA_CFNumber(num) &&
1869 CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
1870 if (iVal & (kIONetworkFeatureHardwareVlan | kIONetworkFeatureSoftwareVlan)) {
1871 interfacePrivate->supportsVLAN = TRUE;
1872 }
1873 }
1874
1875 // localized name
1876 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) {
1877 interfacePrivate->localized_key = CFSTR("airport");
1878 } else if (interfacePrivate->sort_order == kSortThunderbolt) {
1879 if ((interfacePrivate->location == NULL) ||
1880 (CFStringGetLength(interfacePrivate->location) == 0)) {
1881 interfacePrivate->localized_key = CFSTR("thunderbolt");
1882 } else {
1883 interfacePrivate->localized_key = CFSTR("multithunderbolt");
1884 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location);
1885 }
1886 } else if (interfacePrivate->sort_order == kSortBluetoothPAN_GN) {
1887 interfacePrivate->localized_key = CFSTR("bluetooth-pan-gn");
1888 } else if (interfacePrivate->sort_order == kSortBluetoothPAN_NAP) {
1889 interfacePrivate->localized_key = CFSTR("bluetooth-pan-nap");
1890 } else if (interfacePrivate->sort_order == kSortBluetoothPAN_U) {
1891 interfacePrivate->localized_key = CFSTR("bluetooth-pan-u");
1892 } else if (interfacePrivate->sort_order == kSortOtherWireless) {
1893 interfacePrivate->localized_key = CFSTR("wireless");
1894 interfacePrivate->localized_arg1 = CFRetain(CFSTR("")); // ??
1895 } else if (interfacePrivate->builtin) {
1896 if ((interfacePrivate->location == NULL) ||
1897 (CFStringGetLength(interfacePrivate->location) == 0)) {
1898 interfacePrivate->localized_key = CFSTR("ether");
1899 } else {
1900 interfacePrivate->localized_key = CFSTR("multiether");
1901 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location);
1902 }
1903 } else {
1904 CFStringRef provider;
1905
1906 // check provider class
1907 provider = IORegistryEntrySearchCFProperty(interface,
1908 kIOServicePlane,
1909 CFSTR(kIOProviderClassKey),
1910 NULL,
1911 kIORegistryIterateRecursively | kIORegistryIterateParents);
1912 if (provider != NULL) {
1913 if (CFEqual(provider, CFSTR("IOPCIDevice"))) {
1914 CFStringRef port_name;
1915 CFStringRef slot_name;
1916
1917 // set interface "name"
1918 if (!update_interface_name(interfacePrivate, interface, FALSE) &&
1919 pci_slot_info(interface, ift, &slot_name, &port_name)) {
1920 if (isThunderbolt(interface)) {
1921 if (port_name == NULL) {
1922 interfacePrivate->localized_key = CFSTR("thunderbolt-ether");
1923 interfacePrivate->localized_arg1 = slot_name;
1924 } else {
1925 interfacePrivate->localized_key = CFSTR("thunderbolt-multiether");
1926 interfacePrivate->localized_arg1 = slot_name;
1927 interfacePrivate->localized_arg2 = port_name;
1928 }
1929
1930 } else {
1931 if (port_name == NULL) {
1932 interfacePrivate->localized_key = CFSTR("pci-ether");
1933 interfacePrivate->localized_arg1 = slot_name;
1934 } else {
1935 interfacePrivate->localized_key = CFSTR("pci-multiether");
1936 interfacePrivate->localized_arg1 = slot_name;
1937 interfacePrivate->localized_arg2 = port_name;
1938 }
1939 }
1940 }
1941 } else {
1942 io_registry_entry_t node = interface;
1943
1944 while (provider != NULL) {
1945 #if !TARGET_OS_SIMULATOR
1946 if (CFEqual(provider, CFSTR(kIOUSBDeviceClassName)) ||
1947 CFEqual(provider, CFSTR(kIOUSBInterfaceClassName)) ||
1948 CFEqual(provider, CFSTR(kIOUSBHostInterfaceClassName))) {
1949 // get USB info (if available)
1950 processUSBInterface(interfacePrivate,
1951 interface,
1952 interface_dict,
1953 controller,
1954 controller_dict,
1955 bus,
1956 bus_dict);
1957
1958 // set interface "name"
1959 if (!update_interface_name(interfacePrivate, interface, TRUE)) {
1960 interfacePrivate->localized_key = CFSTR("usb-ether");
1961 interfacePrivate->localized_arg1 = IODictionaryCopyBSDName(interface_dict);
1962 }
1963 break;
1964 }
1965 #endif // !TARGET_OS_SIMULATOR
1966
1967 if (node == interface) {
1968 node = controller;
1969 } else if (node == controller ) {
1970 node = bus;
1971 } else {
1972 break;
1973 }
1974
1975 CFRelease(provider);
1976 provider = IORegistryEntrySearchCFProperty(node,
1977 kIOServicePlane,
1978 CFSTR(kIOProviderClassKey),
1979 NULL,
1980 kIORegistryIterateRecursively | kIORegistryIterateParents);
1981 }
1982
1983 if (interfacePrivate->localized_key == NULL) {
1984 update_interface_name(interfacePrivate, interface, FALSE);
1985 }
1986 }
1987
1988 if (provider != NULL) CFRelease(provider);
1989 }
1990
1991 if (interfacePrivate->localized_key == NULL) {
1992 // if no provider, not a PCI device, or no slot information
1993 interfacePrivate->localized_key = CFSTR("generic-ether");
1994 interfacePrivate->localized_arg1 = IODictionaryCopyBSDName(interface_dict);
1995 }
1996 }
1997
1998 break;
1999 case IFT_IEEE1394 :
2000 // Type
2001 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
2002
2003 // Entity
2004 interfacePrivate->entity_type = kSCValNetInterfaceTypeFireWire;
2005
2006 // built-in
2007 interfacePrivate->builtin = isBuiltin(interface);
2008
2009 // sort order
2010 interfacePrivate->sort_order = kSortFireWire;
2011
2012 // localized name
2013 if (interfacePrivate->builtin) {
2014 interfacePrivate->localized_key = CFSTR("firewire");
2015 } else {
2016 CFStringRef port_name;
2017 CFStringRef slot_name;
2018
2019 // set interface "name"
2020 if (!update_interface_name(interfacePrivate, interface, FALSE) &&
2021 pci_slot_info(interface, ift, &slot_name, &port_name)) {
2022 if (isThunderbolt(interface)) {
2023 if (port_name == NULL) {
2024 interfacePrivate->localized_key = CFSTR("thunderbolt-firewire");
2025 interfacePrivate->localized_arg1 = slot_name;
2026 } else {
2027 interfacePrivate->localized_key = CFSTR("thunderbolt-multifirewire");
2028 interfacePrivate->localized_arg1 = slot_name;
2029 interfacePrivate->localized_arg2 = port_name;
2030 }
2031 } else {
2032 if (port_name == NULL) {
2033 interfacePrivate->localized_key = CFSTR("pci-firewire");
2034 interfacePrivate->localized_arg1 = slot_name;
2035 } else {
2036 interfacePrivate->localized_key = CFSTR("pci-multifirewire");
2037 interfacePrivate->localized_arg1 = slot_name;
2038 interfacePrivate->localized_arg2 = port_name;
2039 }
2040 }
2041 }
2042 }
2043
2044 break;
2045 default :
2046 SC_log(LOG_INFO, "unknown interface type = %d", ift);
2047 return FALSE;
2048 }
2049
2050 // Device
2051 interfacePrivate->entity_device = IODictionaryCopyBSDName(interface_dict);
2052
2053 // Hardware (MAC) address
2054 data = CFDictionaryGetValue(controller_dict, CFSTR(kIOMACAddress));
2055 if (isA_CFData(data)) {
2056 interfacePrivate->address = CFRetain(data);
2057 }
2058
2059 // interface prefix
2060 str = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceNamePrefix));
2061 if (isA_CFString(str)) {
2062 interfacePrivate->prefix = CFRetain(str);
2063 }
2064
2065 // interface unit
2066 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceUnit));
2067 if (isA_CFNumber(num) &&
2068 CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
2069 interfacePrivate->unit = CFRetain(num);
2070 }
2071
2072 // configuration [PPP] template override (now deprecated, use NetworkConfigurationOverrides)
2073 merge_override(interfacePrivate, interface, kSCNetworkInterfaceTypePPP);
2074
2075 return TRUE;
2076 }
2077
2078
2079 static void
2080 set_connection_script(SCNetworkInterfacePrivateRef interfacePrivate, CFStringRef script)
2081 {
2082 CFDictionaryRef dict;
2083 CFMutableDictionaryRef newDict;
2084
2085 if (interfacePrivate->overrides == NULL) {
2086 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
2087 0,
2088 &kCFTypeDictionaryKeyCallBacks,
2089 &kCFTypeDictionaryValueCallBacks);
2090 }
2091
2092 dict = CFDictionaryGetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
2093 if (dict != NULL) {
2094 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
2095 } else {
2096 newDict = CFDictionaryCreateMutable(NULL,
2097 0,
2098 &kCFTypeDictionaryKeyCallBacks,
2099 &kCFTypeDictionaryValueCallBacks);
2100 }
2101 if (script != NULL) {
2102 CFDictionarySetValue(newDict, kSCPropNetModemConnectionScript, script);
2103 } else {
2104 CFDictionaryRemoveValue(newDict, kSCPropNetModemConnectionScript);
2105 }
2106 if (CFDictionaryGetCount(newDict) > 0) {
2107 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem, newDict);
2108 } else {
2109 CFDictionaryRemoveValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
2110 }
2111 CFRelease(newDict);
2112
2113 if (CFDictionaryGetCount(interfacePrivate->overrides) == 0) {
2114 CFRelease(interfacePrivate->overrides);
2115 interfacePrivate->overrides = NULL;
2116 }
2117 return;
2118 }
2119
2120
2121 static Boolean
2122 is_valid_connection_script(CFStringRef script)
2123 {
2124 char ccl[MAXPATHLEN];
2125 char path[MAXPATHLEN];
2126 sysdir_search_path_enumeration_state state;
2127
2128 (void) _SC_cfstring_to_cstring(script,
2129 ccl,
2130 sizeof(ccl),
2131 kCFStringEncodingUTF8);
2132
2133 state = sysdir_start_search_path_enumeration(SYSDIR_DIRECTORY_LIBRARY,
2134 SYSDIR_DOMAIN_MASK_LOCAL|SYSDIR_DOMAIN_MASK_SYSTEM);
2135 while ((state = sysdir_get_next_search_path_enumeration(state, path))) {
2136 size_t n;
2137 struct stat statBuf;
2138
2139 if (ccl[0] == '/') {
2140 path[0] = '\0'; // if modemCCL is a full path
2141 } else {
2142 strlcat(path, "/Modem Scripts/", sizeof(path));
2143 }
2144 strlcat(path, ccl, sizeof(path));
2145
2146 if (stat(path, &statBuf) != 0) {
2147 if (errno == ENOENT) {
2148 goto bundle;
2149 }
2150
2151 SC_log(LOG_INFO, "stat() failed: %s", strerror(errno));
2152 continue;
2153 }
2154 if (S_ISREG(statBuf.st_mode)) {
2155 // if we have a valid CCL script
2156 return TRUE;
2157 }
2158
2159 #define BUNDLE_EXT ".ccl"
2160 #define BUNDLE_EXT_LEN sizeof(BUNDLE_EXT) - 1
2161
2162 bundle :
2163
2164 n = strlen(path);
2165 if ((n <= BUNDLE_EXT_LEN) ||
2166 (strstr(&path[n - BUNDLE_EXT_LEN], BUNDLE_EXT) == NULL)) {
2167 strlcat(path, BUNDLE_EXT, sizeof(path));
2168 if (stat(path, &statBuf) != 0) {
2169 if (errno == ENOENT) {
2170 continue;
2171 }
2172
2173 SC_log(LOG_INFO, "stat() failed: %s", strerror(errno));
2174 continue;
2175 }
2176 }
2177 if (S_ISDIR(statBuf.st_mode)) {
2178 // if we have a valid CCL bundle
2179 return TRUE;
2180 }
2181 }
2182
2183 return FALSE;
2184 }
2185
2186
2187 static Boolean
2188 processSerialInterface(SCNetworkInterfacePrivateRef interfacePrivate,
2189 io_registry_entry_t interface,
2190 CFDictionaryRef interface_dict,
2191 io_registry_entry_t controller,
2192 CFDictionaryRef controller_dict,
2193 io_registry_entry_t bus,
2194 CFDictionaryRef bus_dict)
2195 {
2196 CFStringRef base = NULL;
2197 CFStringRef ift;
2198 Boolean isModem = FALSE;
2199 Boolean isWWAN = FALSE;
2200 CFStringRef modemCCL = NULL;
2201 Boolean ok = FALSE;
2202 CFTypeRef val;
2203
2204 // check if initializing
2205 val = IORegistryEntrySearchCFProperty(interface,
2206 kIOServicePlane,
2207 kSCNetworkInterfaceInitializingKey,
2208 NULL,
2209 kIORegistryIterateRecursively | kIORegistryIterateParents);
2210 if (val != NULL) {
2211 Boolean initializing;
2212
2213 initializing = isA_CFBoolean(val) && CFBooleanGetValue(val);
2214 CFRelease(val);
2215 if (initializing) {
2216 return FALSE; // if this interface is still initializing
2217 }
2218 }
2219
2220 // check if WWAN
2221 val = IORegistryEntrySearchCFProperty(interface,
2222 kIOServicePlane,
2223 CFSTR("WWAN"),
2224 NULL,
2225 kIORegistryIterateRecursively | kIORegistryIterateParents);
2226 if (val != NULL) {
2227 isWWAN = isA_CFBoolean(val) && CFBooleanGetValue(val);
2228 CFRelease(val);
2229 }
2230
2231 // Entity (Device)
2232 interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYDeviceKey));
2233 if (interfacePrivate->entity_device == NULL) {
2234 return FALSE;
2235 }
2236
2237 base = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYBaseNameKey));
2238 if (base == NULL) {
2239 base = CFRetain(interfacePrivate->entity_device);
2240 }
2241
2242 /*
2243 * From MoreSCF:
2244 *
2245 * Exclude ports named "irda" because otherwise the IrDA ports on the
2246 * original iMac (rev's A through D) show up as serial ports. Given
2247 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
2248 * even support it, these ports definitely shouldn't be listed.
2249 */
2250 if (CFStringCompare(base,
2251 CFSTR("irda"),
2252 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
2253 goto done;
2254 }
2255
2256 if (IOStringValueHasPrefix(base, CFSTR("bluetooth"))) {
2257 Boolean haveController = FALSE;
2258
2259 // Bluetooth
2260 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
2261 interfacePrivate->sort_order = kSortBluetooth;
2262 interfacePrivate->builtin = isBluetoothBuiltin(&haveController);
2263 if (!haveController) {
2264 // if device with no controller present
2265 goto done;
2266 }
2267 } else if (IOStringValueHasPrefix(base, CFSTR("irda-ircomm"))) {
2268 // IrDA
2269 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
2270 interfacePrivate->sort_order = kSortIrDA;
2271 } else if (isWWAN) {
2272 // WWAN
2273 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN;
2274 interfacePrivate->sort_order = kSortWWAN;
2275 } else {
2276 // Modem
2277 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
2278 interfacePrivate->sort_order = kSortModem;
2279 }
2280
2281 // Entity (Type)
2282 interfacePrivate->entity_type = kSCEntNetModem;
2283
2284 // Entity (Hardware)
2285 ift = CFDictionaryGetValue(interface_dict, CFSTR(kIOSerialBSDTypeKey));
2286 if (!isA_CFString(ift)) {
2287 goto done;
2288 }
2289
2290 if (CFEqual(ift, CFSTR(kIOSerialBSDModemType))) {
2291 // if modem
2292 isModem = TRUE;
2293
2294 if (CFEqual(base, CFSTR("modem"))) {
2295 interfacePrivate->builtin = TRUE;
2296 interfacePrivate->sort_order = kSortInternalModem;
2297 } else if (CFEqual(base, CFSTR("usbmodem"))) {
2298 interfacePrivate->sort_order = kSortUSBModem;
2299 }
2300 } else if (CFEqual(ift, CFSTR(kIOSerialBSDRS232Type))) {
2301 // if serial port
2302 interfacePrivate->sort_order = kSortSerialPort;
2303 } else {
2304 goto done;
2305 }
2306
2307 // configuration [PPP] template override (now deprecated, use NetworkConfigurationOverrides)
2308 merge_override(interfacePrivate, interface, kSCNetworkInterfaceTypePPP);
2309
2310 // configuration [Modem] template override (now deprecated, use NetworkConfigurationOverrides)
2311 merge_override(interfacePrivate, interface, kSCNetworkInterfaceTypeModem);
2312
2313 // look for modem CCL, unique identifier
2314 if (interfacePrivate->overrides != NULL) {
2315 val = CFDictionaryGetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
2316 if (val != NULL) {
2317 CFStringRef uniqueID;
2318
2319 modemCCL = CFDictionaryGetValue(val, kSCPropNetModemConnectionScript);
2320 modemCCL = isA_CFString(modemCCL);
2321
2322 uniqueID = CFDictionaryGetValue(val, CFSTR("UniqueIdentifier"));
2323 uniqueID = isA_CFString(uniqueID);
2324 if (uniqueID != NULL) {
2325 // retain the device's base name and the unique id
2326 CFRelease(interfacePrivate->entity_device);
2327 interfacePrivate->entity_device = CFRetain(base);
2328 interfacePrivate->entity_device_unique = CFStringCreateCopy(NULL, uniqueID);
2329 }
2330 }
2331 }
2332
2333 // if not part of the NetworkConfigurationOverrides/DeviceModemOverrides, look
2334 // a bit harder for the modem CCL
2335 if (modemCCL == NULL) {
2336 val = IORegistryEntrySearchCFProperty(interface,
2337 kIOServicePlane,
2338 CFSTR("ModemCCL"),
2339 NULL,
2340 kIORegistryIterateRecursively | kIORegistryIterateParents);
2341 if (val != NULL) {
2342 modemCCL = IOCopyCFStringValue(val);
2343 if (modemCCL != NULL) {
2344 set_connection_script(interfacePrivate, modemCCL);
2345 CFRelease(modemCCL);
2346 }
2347
2348 CFRelease(val);
2349 }
2350 }
2351
2352 // localized name
2353 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIrDA)) {
2354 interfacePrivate->localized_key = CFSTR("irda");
2355 } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBluetooth)) {
2356 interfacePrivate->localized_key = CFSTR("bluetooth");
2357 } else {
2358 CFStringRef localized = NULL;
2359 CFStringRef name = NULL;
2360 CFMutableStringRef port;
2361
2362 port = CFStringCreateMutableCopy(NULL, 0, base);
2363 CFStringLowercase(port, NULL);
2364
2365 if (!isModem) {
2366 CFStringAppend(port, CFSTR("-port"));
2367 }
2368
2369 // set non-localized name
2370 if (bundle != NULL) {
2371 name = copy_interface_string(bundle, port, FALSE);
2372 }
2373 if (name != NULL) {
2374 if (!CFEqual(port, name)) {
2375 // if [English] localization available
2376 interfacePrivate->name = name;
2377 } else {
2378 // if no [English] localization available, use TTY base name
2379 CFRelease(name);
2380 interfacePrivate->name = CFStringCreateCopy(NULL, base);
2381 }
2382 } else {
2383 interfacePrivate->name = CFStringCreateCopy(NULL, base);
2384 }
2385
2386 // set localized name
2387 if (bundle != NULL) {
2388 localized = copy_interface_string(bundle, port, TRUE);
2389 }
2390 if (localized != NULL) {
2391 if (!CFEqual(port, localized)) {
2392 // if localization available
2393 interfacePrivate->localized_name = localized;
2394 } else {
2395 // if no localization available, use TTY base name
2396 CFRelease(localized);
2397 interfacePrivate->localized_name = CFStringCreateCopy(NULL, base);
2398 }
2399 } else {
2400 interfacePrivate->localized_name = CFStringCreateCopy(NULL, base);
2401 }
2402
2403 if (!isModem || !CFEqual(base, CFSTR("modem"))) {
2404 // get USB info (if available)
2405 processUSBInterface(interfacePrivate,
2406 interface,
2407 interface_dict,
2408 controller,
2409 controller_dict,
2410 bus,
2411 bus_dict);
2412
2413 // set interface "name"
2414 if (update_interface_name(interfacePrivate, interface, TRUE)) {
2415 // if "ModemCCL" not provided, also check if the product/interface
2416 // name matches a CCL script
2417 if ((modemCCL == NULL) &&
2418 is_valid_connection_script(interfacePrivate->name)) {
2419 set_connection_script(interfacePrivate, interfacePrivate->name);
2420 }
2421 }
2422 }
2423
2424 CFRelease(port);
2425 }
2426
2427 ok = TRUE;
2428
2429 done :
2430
2431 if (!ok && (interfacePrivate->entity_device != NULL)) {
2432 CFRelease(interfacePrivate->entity_device);
2433 interfacePrivate->entity_device = NULL;
2434 }
2435 if (base != NULL) CFRelease(base);
2436
2437 return ok;
2438 }
2439
2440
2441 static CFStringRef
2442 __SC_IORegistryEntryCopyPath(io_registry_entry_t entry, const io_name_t plane)
2443 {
2444 /*
2445 * Create a path for a registry entry.
2446 */
2447 io_string_t path;
2448 IOReturn status;
2449 CFStringRef str = NULL;
2450
2451 status = IORegistryEntryGetPath(entry, plane, path);
2452 if (status == kIOReturnSuccess) {
2453 str = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
2454 } else if (status == kIOReturnBadArgument) {
2455 io_registry_entry_t parent;
2456
2457 status = IORegistryEntryGetParentEntry(entry, plane, &parent);
2458 if (status == kIOReturnSuccess) {
2459 CFStringRef str_parent;
2460
2461 str_parent = __SC_IORegistryEntryCopyPath(parent, plane);
2462 if (str_parent != NULL) {
2463 io_name_t name;
2464
2465 status = IORegistryEntryGetNameInPlane(entry, plane, name);
2466 if (status == kIOReturnSuccess) {
2467 io_name_t location;
2468
2469 status = IORegistryEntryGetLocationInPlane(entry, plane, location);
2470 if (status == kIOReturnSuccess) {
2471 str = CFStringCreateWithFormat(NULL,
2472 NULL,
2473 CFSTR("%@/%s@%s"),
2474 str_parent,
2475 name,
2476 location);
2477 } else {
2478 str = CFStringCreateWithFormat(NULL,
2479 NULL,
2480 CFSTR("%@/%s"),
2481 str_parent,
2482 name);
2483 }
2484 }
2485
2486 CFRelease(str_parent);
2487 }
2488
2489 IOObjectRelease(parent);
2490 }
2491 }
2492
2493 return str;
2494 }
2495
2496 static CFMutableDictionaryRef
2497 copyIORegistryProperties(io_registry_entry_t reg_ent, const CFStringRef *reg_keys, CFIndex numKeys)
2498 {
2499 CFIndex idx = 0;
2500 CFMutableDictionaryRef reg_dict = NULL;
2501 CFTypeRef value = NULL;
2502
2503 reg_dict = CFDictionaryCreateMutable(NULL,
2504 0,
2505 &kCFTypeDictionaryKeyCallBacks ,
2506 &kCFTypeDictionaryValueCallBacks);
2507
2508 for (; idx < numKeys; idx++) {
2509 value = IORegistryEntryCreateCFProperty(reg_ent, reg_keys[idx], NULL, 0);
2510 if (value != NULL) {
2511 CFDictionaryAddValue(reg_dict, reg_keys[idx], value);
2512 CFRelease(value);
2513 }
2514 }
2515
2516 return reg_dict;
2517 }
2518
2519 static SCNetworkInterfaceRef
2520 createInterface(io_registry_entry_t interface, processInterface func,
2521 CFStringRef hidden_key)
2522 {
2523 io_registry_entry_t bus = MACH_PORT_NULL;
2524 CFMutableDictionaryRef bus_dict = NULL;
2525 io_registry_entry_t controller = MACH_PORT_NULL;
2526 CFMutableDictionaryRef controller_dict = NULL;
2527 uint64_t entryID = 0;
2528 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
2529 CFMutableDictionaryRef interface_dict = NULL;
2530 kern_return_t kr;
2531 CFTypeRef val;
2532
2533 // Keys of interest
2534 #if TARGET_OS_SIMULATOR || 1 // while waiting for rdar://19431723
2535 #else
2536 const CFStringRef interface_dict_keys[] = {
2537 CFSTR(kIOInterfaceType),
2538 CFSTR(kIOBuiltin),
2539 CFSTR(kIOBSDNameKey),
2540 CFSTR(kIOPrimaryInterface),
2541 CFSTR(kIOInterfaceNamePrefix),
2542 CFSTR(kIOInterfaceUnit),
2543 CFSTR(kIOTTYDeviceKey),
2544 CFSTR(kIOTTYBaseNameKey),
2545 CFSTR(kIOSerialBSDTypeKey),
2546 CFSTR(kIOLocation)
2547 };
2548 #endif // !TARGET_OS_SIMULATOR
2549
2550 const CFStringRef controller_dict_keys[] = {
2551 CFSTR(kIOFeatures),
2552 CFSTR(kIOMACAddress)
2553 };
2554
2555 const CFStringRef bus_dict_keys[] = {
2556 CFSTR("name")
2557 };
2558
2559 if (hidden_key != NULL) {
2560 // check if hidden
2561 val = IORegistryEntrySearchCFProperty(interface,
2562 kIOServicePlane,
2563 hidden_key,
2564 NULL,
2565 kIORegistryIterateRecursively | kIORegistryIterateParents);
2566 if (val != NULL) {
2567 CFRelease(val);
2568 goto done; // if this interface should not be exposed
2569 }
2570 }
2571
2572 #if TARGET_OS_SIMULATOR || 1 // while waiting for rdar://19431723
2573 // get the dictionary associated with the [interface] node
2574 kr = IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions);
2575 if (kr != kIOReturnSuccess) {
2576 SC_log(LOG_INFO, "IORegistryEntryCreateCFProperties() failed, kr = 0x%x", kr);
2577 goto done;
2578 }
2579 #else
2580 interface_dict = copyIORegistryProperties(interface,
2581 interface_dict_keys,
2582 sizeof(interface_dict_keys)/sizeof(interface_dict_keys[0]));
2583 #endif // !TARGET_OS_SIMULATOR
2584
2585 // get the controller node
2586 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &controller);
2587 if (kr != kIOReturnSuccess) {
2588 SC_log(LOG_INFO, "IORegistryEntryGetParentEntry() failed, kr = 0x%x", kr);
2589 goto done;
2590 }
2591
2592 controller_dict = copyIORegistryProperties(controller,
2593 controller_dict_keys,
2594 sizeof(controller_dict_keys)/sizeof(controller_dict_keys[0]));
2595
2596 // get the bus node
2597 kr = IORegistryEntryGetParentEntry(controller, kIOServicePlane, &bus);
2598 if (kr != kIOReturnSuccess) {
2599 SC_log(LOG_INFO, "IORegistryEntryGetParentEntry() failed, kr = 0x%x", kr);
2600 goto done;
2601 }
2602
2603 bus_dict = copyIORegistryProperties(bus,
2604 bus_dict_keys,
2605 sizeof(bus_dict_keys)/sizeof(bus_dict_keys[0]));
2606
2607 // get the registry entry ID
2608 kr = IORegistryEntryGetRegistryEntryID(interface, &entryID);
2609 if (kr != kIOReturnSuccess) {
2610 SC_log(LOG_INFO, "IORegistryEntryGetRegistryEntryID() failed, kr = 0x%x", kr);
2611 goto done;
2612 }
2613
2614 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
2615 assert(interfacePrivate != NULL);
2616 interfacePrivate->path = __SC_IORegistryEntryCopyPath(interface, kIOServicePlane);
2617 interfacePrivate->entryID = entryID;
2618
2619 // configuration [PPP, Modem, DNS, IPv4, IPv6, Proxies, SMB] template overrides
2620 val = IORegistryEntrySearchCFProperty(interface,
2621 kIOServicePlane,
2622 kSCNetworkInterfaceNetworkConfigurationOverridesKey,
2623 NULL,
2624 kIORegistryIterateRecursively | kIORegistryIterateParents);
2625 if (val != NULL) {
2626 if (isA_CFDictionary(val)) {
2627 interfacePrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, val);
2628 }
2629 CFRelease(val);
2630 }
2631
2632 if ((*func)(interfacePrivate, interface, interface_dict, controller, controller_dict, bus, bus_dict)) {
2633 // get user-notification / auto-configuration preference
2634 val = IORegistryEntrySearchCFProperty(interface,
2635 kIOServicePlane,
2636 kSCNetworkInterfaceConfigurationActionKey,
2637 NULL,
2638 kIORegistryIterateRecursively | kIORegistryIterateParents);
2639 if (val != NULL) {
2640 if (isA_CFString(val)) {
2641 interfacePrivate->configurationAction = CFRetain(val);
2642 }
2643 CFRelease(val);
2644 }
2645
2646 // get HiddenConfiguration preference
2647 val = IORegistryEntrySearchCFProperty(interface,
2648 kIOServicePlane,
2649 kSCNetworkInterfaceHiddenConfigurationKey,
2650 NULL,
2651 kIORegistryIterateRecursively | kIORegistryIterateParents);
2652 if (val != NULL) {
2653 interfacePrivate->hidden = TRUE;
2654 CFRelease(val);
2655 }
2656 } else {
2657 CFRelease(interfacePrivate);
2658 interfacePrivate = NULL;
2659 }
2660
2661 done :
2662
2663 if (interface_dict != NULL) CFRelease(interface_dict);
2664
2665 if (controller != MACH_PORT_NULL) IOObjectRelease(controller);
2666 if (controller_dict != NULL) CFRelease(controller_dict);
2667
2668 if (bus != MACH_PORT_NULL) IOObjectRelease(bus);
2669 if (bus_dict != NULL) CFRelease(bus_dict);
2670
2671 return (SCNetworkInterfaceRef)interfacePrivate;
2672 }
2673
2674
2675 static CF_RETURNS_RETAINED CFArrayRef
2676 findMatchingInterfaces(CFDictionaryRef matching,
2677 processInterface func,
2678 CFStringRef hidden_key,
2679 Boolean keep_pre_configured)
2680 {
2681 CFMutableArrayRef interfaces;
2682 io_registry_entry_t interface;
2683 kern_return_t kr;
2684 io_iterator_t iterator = MACH_PORT_NULL;
2685
2686 /*
2687 * A reference to the "matching" dictionary will be consumed by the
2688 * the call to IOServiceGetMatchingServices so we bump up the retain
2689 * count.
2690 */
2691 CFRetain(matching);
2692
2693 kr = IOServiceGetMatchingServices(masterPort, matching, &iterator);
2694 if (kr != kIOReturnSuccess) {
2695 SC_log(LOG_INFO, "IOServiceGetMatchingServices() failed, kr = 0x%x", kr);
2696 return NULL;
2697 }
2698
2699 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2700
2701 while ((interface = IOIteratorNext(iterator)) != MACH_PORT_NULL) {
2702 SCNetworkInterfaceRef match;
2703
2704 match = createInterface(interface, func, hidden_key);
2705 if (match != NULL) {
2706 if (keep_pre_configured || !_SCNetworkInterfaceIsApplePreconfigured(match)) {
2707 CFArrayAppendValue(interfaces, match);
2708 }
2709 CFRelease(match);
2710 }
2711
2712 IOObjectRelease(interface);
2713 }
2714
2715 IOObjectRelease(iterator);
2716
2717 return interfaces;
2718 }
2719
2720
2721 #pragma mark -
2722 #pragma mark helper functions
2723
2724
2725 static CFIndex
2726 findConfiguration(CFStringRef interface_type)
2727 {
2728 for (size_t i = 0; i < sizeof(configurations)/sizeof(configurations[0]); i++) {
2729 if (CFEqual(interface_type, *configurations[i].interface_type)) {
2730 return i;
2731 }
2732 }
2733
2734 return kCFNotFound;
2735 }
2736
2737
2738 __private_extern__
2739 CFStringRef
2740 __SCNetworkInterfaceGetDefaultConfigurationType(SCNetworkInterfaceRef interface)
2741 {
2742 CFIndex interfaceIndex;
2743 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2744
2745 if (interfacePrivate->serviceID == NULL) {
2746 // if not associated with a service (yet)
2747 _SCErrorSet(kSCStatusInvalidArgument);
2748 return NULL;
2749 }
2750
2751 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2752 if (interfaceIndex == kCFNotFound) {
2753 // unknown interface type, use per-service configuration preferences
2754 return interfacePrivate->interface_type; // entity
2755 }
2756
2757 if (configurations[interfaceIndex].entity_hardware != NULL) {
2758 // if configuration information can be associated with this interface type
2759 return *configurations[interfaceIndex].entity_hardware;
2760 }
2761
2762 _SCErrorSet(kSCStatusInvalidArgument);
2763 return NULL;
2764 }
2765
2766
2767 __private_extern__
2768 Boolean
2769 __SCNetworkInterfaceIsValidExtendedConfigurationType(SCNetworkInterfaceRef interface,
2770 CFStringRef extendedType,
2771 Boolean requirePerInterface)
2772 {
2773 CFStringRef defaultType;
2774 CFIndex extendedIndex;
2775 CFIndex interfaceIndex;
2776 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2777 Boolean isL2TP = FALSE;
2778 Boolean ok = FALSE;
2779
2780 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
2781 if (defaultType == NULL) {
2782 goto done;
2783 }
2784
2785 if (CFEqual(extendedType, defaultType)) {
2786 // extended and default configuration types cannot conflict
2787 goto done;
2788 }
2789
2790 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2791 if (interfaceIndex == kCFNotFound) {
2792 // configuration information for unknown interface type's
2793 // are stored along with the service and we don't allow
2794 // per-service extended configurations
2795 goto done;
2796 }
2797
2798 if (CFEqual(extendedType, kSCEntNetIPSec)) {
2799 CFStringRef interfaceType;
2800
2801 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
2802 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
2803 SCNetworkInterfaceRef child;
2804
2805 child = SCNetworkInterfaceGetInterface(interface);
2806 if (child != NULL) {
2807 interfaceType = SCNetworkInterfaceGetInterfaceType(child);
2808 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
2809 isL2TP = TRUE;
2810 }
2811 }
2812 }
2813 }
2814
2815 if (requirePerInterface &&
2816 !configurations[interfaceIndex].per_interface_config &&
2817 !isL2TP) {
2818 // we don't allow per-service extended configurations (except
2819 // that we do allow IPSec as an extended type for PPP->L2TP)
2820 goto done;
2821 }
2822
2823 extendedIndex = findConfiguration(extendedType);
2824 if ((extendedIndex != kCFNotFound) && !isL2TP) {
2825 // extended type cannot match a known interface type (except
2826 // that we do allow IPSec as an extended type for PPP->L2TP)
2827 goto done;
2828 }
2829
2830 /*
2831 * ???
2832 * Should we check/match and specifically allow known extended
2833 * configuration types (e.g. EAPOL)?
2834 *
2835 * Should we check/match and specifically block known internal
2836 * configuration types (e.g. QoSMarking)?
2837 *
2838 * Lastly, should we ensure that any non-standard extended configuration
2839 * types be of the form com.myCompany.myType?
2840 * ???
2841 */
2842
2843 ok = TRUE;
2844
2845 done :
2846
2847 if (!ok) {
2848 _SCErrorSet(kSCStatusInvalidArgument);
2849 }
2850 return ok;
2851 }
2852
2853
2854 typedef struct {
2855 CFStringRef defaultType;
2856 CFMutableArrayRef types;
2857 } extendedConfiguration, *extendedConfigurationRef;
2858
2859
2860 static void
2861 __addExtendedConfigurationType(const void *key, const void *value, void *context)
2862 {
2863 #pragma unused(value)
2864 CFStringRef extendedType = (CFStringRef)key;
2865 extendedConfigurationRef myContextRef = (extendedConfigurationRef)context;
2866
2867 if (CFEqual(extendedType, myContextRef->defaultType)) {
2868 // do not include the default configuration type
2869 return;
2870 }
2871
2872 if (CFArrayContainsValue(myContextRef->types,
2873 CFRangeMake(0, CFArrayGetCount(myContextRef->types)),
2874 extendedType)) {
2875 // if extendedType already has already been added
2876 return;
2877 }
2878
2879 CFArrayAppendValue(myContextRef->types, extendedType);
2880
2881 return;
2882 }
2883
2884
2885 static CFIndex
2886 findPerInterfaceConfiguration(SCNetworkInterfaceRef interface)
2887 {
2888 CFIndex interfaceIndex;
2889 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2890
2891 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2892 if (interfaceIndex == kCFNotFound) {
2893 // if per-service (not per interface) configuration
2894 return kCFNotFound;
2895 }
2896
2897 if (!configurations[interfaceIndex].per_interface_config) {
2898 // if per-interface configuration not allowed
2899 return kCFNotFound;
2900 }
2901
2902 return interfaceIndex;
2903 }
2904
2905
2906 static CF_RETURNS_RETAINED CFArrayRef
2907 extendedConfigurationTypes(SCNetworkInterfaceRef interface)
2908 {
2909 CFIndex i;
2910 CFIndex interfaceIndex;
2911 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2912 extendedConfiguration myContext;
2913 SCNetworkServiceRef service;
2914 CFArrayRef sets;
2915 CFIndex n;
2916
2917 myContext.defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
2918 if (myContext.defaultType == NULL) {
2919 myContext.types = NULL;
2920 goto done;
2921 }
2922
2923 myContext.types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2924
2925 if (interfacePrivate->serviceID == NULL) {
2926 // if not associated with a service (yet)
2927 goto done;
2928 }
2929
2930 interfaceIndex = findPerInterfaceConfiguration(interface);
2931 if (interfaceIndex == kCFNotFound) {
2932 // if no per-interface configuration
2933 goto done;
2934 }
2935
2936 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
2937 interfacePrivate->prefs,
2938 interfacePrivate->serviceID,
2939 interface);
2940
2941 sets = SCNetworkSetCopyAll(interfacePrivate->prefs);
2942 n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
2943
2944 for (i = 0; i < n; i++) {
2945 CFDictionaryRef configs;
2946 Boolean found;
2947 CFStringRef path;
2948 CFArrayRef services;
2949 SCNetworkSetRef set;
2950
2951 set = CFArrayGetValueAtIndex(sets, i);
2952 services = SCNetworkSetCopyServices(set);
2953 found = CFArrayContainsValue(services,
2954 CFRangeMake(0, CFArrayGetCount(services)),
2955 service);
2956 CFRelease(services);
2957
2958 if (!found) {
2959 continue;
2960 }
2961
2962 // add stored extended configuration types
2963 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
2964 SCNetworkSetGetSetID(set), // set
2965 interfacePrivate->entity_device, // service
2966 NULL); // entity
2967 configs = __getPrefsConfiguration(interfacePrivate->prefs, path);
2968 CFRelease(path);
2969 if (isA_CFDictionary(configs)) {
2970 CFDictionaryApplyFunction(configs,
2971 __addExtendedConfigurationType,
2972 &myContext);
2973 }
2974
2975 // add not-yet-stored extended configuration types
2976 if (interfacePrivate->unsaved != NULL) {
2977 CFDictionaryApplyFunction(interfacePrivate->unsaved,
2978 __addExtendedConfigurationType,
2979 &myContext);
2980 }
2981
2982 break;
2983 }
2984
2985 CFRelease(service);
2986 if (sets != NULL) CFRelease(sets);
2987
2988 done :
2989
2990 return myContext.types;
2991 }
2992
2993 static CFArrayRef
2994 stringCreateArray(CFStringRef str)
2995 {
2996 return (CFArrayCreate(NULL, (const void **)&str, 1, &kCFTypeArrayCallBacks));
2997 }
2998
2999 static CFArrayRef
3000 copyPerInterfaceConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate,
3001 CFStringRef extendedType)
3002 {
3003 CFMutableArrayRef array = NULL;
3004 CFIndex i;
3005 CFIndex n;
3006 CFStringRef path;
3007 SCNetworkServiceRef service;
3008 CFArrayRef sets;
3009
3010 // known interface type, per-interface configuration preferences
3011 //
3012 // 1. look for all sets which contain the associated service
3013 // 2. add a per-set path for the interface configuration for
3014 // each set.
3015
3016 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
3017 interfacePrivate->prefs,
3018 interfacePrivate->serviceID,
3019 (SCNetworkInterfaceRef)interfacePrivate);
3020
3021 sets = SCNetworkSetCopyAll(interfacePrivate->prefs);
3022 n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
3023
3024 for (i = 0; i < n; i++) {
3025 CFArrayRef services;
3026 SCNetworkSetRef set;
3027
3028 set = CFArrayGetValueAtIndex(sets, i);
3029 services = SCNetworkSetCopyServices(set);
3030 if (CFArrayContainsValue(services,
3031 CFRangeMake(0, CFArrayGetCount(services)),
3032 service)) {
3033 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
3034 SCNetworkSetGetSetID(set), // set
3035 interfacePrivate->entity_device, // service
3036 extendedType); // entity
3037 if (array == NULL) {
3038 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3039 }
3040 CFArrayAppendValue(array, path);
3041 CFRelease(path);
3042 }
3043 CFRelease(services);
3044 }
3045
3046 CFRelease(service);
3047 if (sets != NULL) CFRelease(sets);
3048 return array;
3049
3050 }
3051
3052 static CFArrayRef
3053 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate,
3054 CFStringRef extendedType)
3055 {
3056 CFArrayRef array = NULL;
3057 CFIndex interfaceIndex;
3058 CFStringRef path;
3059
3060 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
3061 if (interfaceIndex == kCFNotFound) {
3062 // unknown interface type, use per-service configuration preferences
3063 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
3064 interfacePrivate->serviceID, // service
3065 extendedType); // entity
3066 array = stringCreateArray(path);
3067 CFRelease(path);
3068 }
3069
3070 else if (!configurations[interfaceIndex].per_interface_config) {
3071 // known interface type, per-service configuration preferences
3072 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
3073 interfacePrivate->serviceID, // service
3074 extendedType); // entity
3075 array = stringCreateArray(path);
3076 CFRelease(path);
3077 }
3078
3079 else if (interfacePrivate->serviceID != NULL) {
3080 array = copyPerInterfaceConfigurationPaths(interfacePrivate, extendedType);
3081 }
3082
3083 return (array);
3084 }
3085
3086
3087 #pragma mark -
3088 #pragma mark SCNetworkInterface <--> preferences entity
3089
3090
3091 __private_extern__
3092 CFDictionaryRef
3093 __SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface)
3094 {
3095 CFMutableDictionaryRef entity;
3096 CFIndex interfaceIndex;
3097 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3098
3099 entity = CFDictionaryCreateMutable(NULL,
3100 0,
3101 &kCFTypeDictionaryKeyCallBacks,
3102 &kCFTypeDictionaryValueCallBacks);
3103 if (interfacePrivate->entity_type != NULL) {
3104 CFDictionarySetValue(entity,
3105 kSCPropNetInterfaceType,
3106 interfacePrivate->entity_type);
3107 }
3108 if (interfacePrivate->entity_subtype != NULL) {
3109 CFDictionarySetValue(entity,
3110 kSCPropNetInterfaceSubType,
3111 interfacePrivate->entity_subtype);
3112 }
3113 if (interfacePrivate->entity_device != NULL) {
3114 CFDictionarySetValue(entity,
3115 kSCPropNetInterfaceDeviceName,
3116 interfacePrivate->entity_device);
3117 }
3118 if (interfacePrivate->entity_device_unique != NULL) {
3119 CFDictionarySetValue(entity,
3120 CFSTR("DeviceUniqueIdentifier"),
3121 interfacePrivate->entity_device_unique);
3122 }
3123 if (interfacePrivate->hidden) {
3124 CFDictionarySetValue(entity,
3125 kSCNetworkInterfaceHiddenConfigurationKey,
3126 kCFBooleanTrue);
3127 }
3128
3129 // match the "hardware" with the lowest layer
3130 while (TRUE) {
3131 SCNetworkInterfaceRef nextInterface;
3132
3133 nextInterface = SCNetworkInterfaceGetInterface(interface);
3134 if (nextInterface == NULL) {
3135 break;
3136 }
3137
3138 interface = nextInterface;
3139 }
3140 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3141
3142 if (CFEqual(interface, kSCNetworkInterfaceIPv4)) {
3143 return entity;
3144 }
3145
3146 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
3147 if (interfaceIndex != kCFNotFound) {
3148 if (configurations[interfaceIndex].entity_hardware != NULL) {
3149 CFDictionarySetValue(entity,
3150 kSCPropNetInterfaceHardware,
3151 *configurations[interfaceIndex].entity_hardware);
3152 }
3153 } else {
3154 CFDictionarySetValue(entity,
3155 kSCPropNetInterfaceHardware,
3156 interfacePrivate->interface_type);
3157 }
3158
3159 // add the localized display name (which will only be used when/if the
3160 // interface is removed from the system)
3161 CFDictionarySetValue(entity,
3162 kSCPropUserDefinedName,
3163 SCNetworkInterfaceGetLocalizedDisplayName(interface));
3164
3165 return entity;
3166 }
3167
3168
3169 static SCNetworkInterfaceRef
3170 findInterface(CFArrayRef interfaces, CFStringRef match_if)
3171 {
3172 CFIndex i;
3173 CFIndex n;
3174
3175 n = CFArrayGetCount(interfaces);
3176 for (i = 0; i < n; i++) {
3177 SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(interfaces, i);
3178 CFStringRef interfaceName;
3179
3180 interfaceName = SCNetworkInterfaceGetBSDName(interface);
3181 if ((interfaceName != NULL) && CFEqual(interfaceName, match_if)) {
3182 CFRetain(interface);
3183 return interface;
3184 }
3185 }
3186
3187 return NULL;
3188 }
3189
3190 #if !TARGET_OS_IPHONE
3191 static SCNetworkInterfaceRef
3192 findBondInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
3193 {
3194 CFArrayRef bonds;
3195 SCNetworkInterfaceRef interface = NULL;
3196
3197 if (prefs == NULL) {
3198 return (NULL);
3199 }
3200
3201 // check if the interface is an Ethernet Bond
3202 bonds = SCBondInterfaceCopyAll(prefs);
3203 if (bonds != NULL) {
3204 interface = findInterface(bonds, ifDevice);
3205 CFRelease(bonds);
3206 }
3207 return interface;
3208 }
3209 #endif // !TARGET_OS_IPHONE
3210
3211 static SCNetworkInterfaceRef
3212 findBridgeInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
3213 {
3214 CFArrayRef bridges;
3215 SCNetworkInterfaceRef interface = NULL;
3216
3217 if (prefs == NULL) {
3218 return (NULL);
3219 }
3220
3221 // check if the interface is an bridge
3222 bridges = SCBridgeInterfaceCopyAll(prefs);
3223 if (bridges != NULL) {
3224 interface = findInterface(bridges, ifDevice);
3225 CFRelease(bridges);
3226 }
3227 return interface;
3228 }
3229
3230 static SCNetworkInterfaceRef
3231 findVLANInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
3232 {
3233 SCNetworkInterfaceRef interface = NULL;
3234 CFArrayRef vlans;
3235
3236 if (prefs == NULL) {
3237 return (NULL);
3238 }
3239
3240 // check if the interface is a VLAN
3241 vlans = SCVLANInterfaceCopyAll(prefs);
3242 if (vlans != NULL) {
3243 interface = findInterface(vlans, ifDevice);
3244 CFRelease(vlans);
3245 }
3246 return interface;
3247 }
3248
3249
3250 #define N_QUICK 32
3251
3252
3253 static CFMutableDictionaryRef
3254 copy_ppp_entity(CFStringRef bsdName)
3255 {
3256 CFMutableDictionaryRef entity = NULL;
3257 CFStringRef pattern;
3258 CFMutableArrayRef patterns;
3259 CFDictionaryRef dict;
3260
3261 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3262 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetPPP);
3263 CFArrayAppendValue(patterns, pattern);
3264 CFRelease(pattern);
3265 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface);
3266 CFArrayAppendValue(patterns, pattern);
3267 CFRelease(pattern);
3268 dict = SCDynamicStoreCopyMultiple(NULL, NULL, patterns);
3269 CFRelease(patterns);
3270 if (dict != NULL) {
3271 CFIndex i;
3272 const void * keys_q[N_QUICK];
3273 const void ** keys = keys_q;
3274 CFIndex n;
3275 const void * vals_q[N_QUICK];
3276 const void ** vals = vals_q;
3277
3278 n = CFDictionaryGetCount(dict);
3279 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
3280 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
3281 vals = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
3282 }
3283 CFDictionaryGetKeysAndValues(dict, keys, vals);
3284 for (i = 0; i < n; i++) {
3285 CFArrayRef components;
3286 CFStringRef interfaceKey;
3287 CFDictionaryRef interfaceVal;
3288 CFStringRef ifName;
3289 CFStringRef pppKey = (CFStringRef)keys[i];
3290 CFDictionaryRef pppVal = (CFDictionaryRef)vals[i];
3291 CFStringRef serviceID;
3292
3293 if (!CFStringHasSuffix(pppKey, kSCEntNetPPP) ||
3294 !CFDictionaryGetValueIfPresent(pppVal, kSCPropInterfaceName, (const void **)&ifName) ||
3295 !CFEqual(bsdName, ifName)) {
3296 // if not matching PPP interface
3297 continue;
3298 }
3299
3300 components = CFStringCreateArrayBySeparatingStrings(NULL, pppKey, CFSTR("/"));
3301 serviceID = CFArrayGetValueAtIndex(components, 3);
3302 interfaceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, kSCEntNetInterface);
3303 interfaceVal = CFDictionaryGetValue(dict, interfaceKey);
3304 CFRelease(interfaceKey);
3305 CFRelease(components);
3306 if (interfaceVal != NULL) {
3307 entity = CFDictionaryCreateMutableCopy(NULL, 0, interfaceVal);
3308 break;
3309 }
3310 }
3311 if (keys != keys_q) {
3312 CFAllocatorDeallocate(NULL, keys);
3313 CFAllocatorDeallocate(NULL, vals);
3314 }
3315
3316 CFRelease(dict);
3317 }
3318
3319 return entity;
3320 }
3321
3322
3323 SCNetworkInterfaceRef
3324 _SCNetworkInterfaceCreateWithBSDName(CFAllocatorRef allocator,
3325 CFStringRef bsdName,
3326 UInt32 flags)
3327 {
3328 #pragma unused(allocator)
3329 CFMutableDictionaryRef entity = NULL;
3330 struct ifreq ifr;
3331 SCNetworkInterfaceRef interface;
3332
3333 bzero(&ifr, sizeof(ifr));
3334 if (_SC_cfstring_to_cstring(bsdName, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII) != NULL) {
3335 int s;
3336
3337 s = socket(AF_INET, SOCK_DGRAM, 0);
3338 if (s != -1) {
3339 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) == -1) {
3340 ifr.ifr_flags = 0;
3341 }
3342 close(s);
3343 }
3344
3345 if ((ifr.ifr_flags & IFF_POINTOPOINT) != 0) {
3346 // if PPP
3347 entity = copy_ppp_entity(bsdName);
3348 }
3349 }
3350
3351 if (entity == NULL) {
3352 entity = CFDictionaryCreateMutable(NULL,
3353 0,
3354 &kCFTypeDictionaryKeyCallBacks,
3355 &kCFTypeDictionaryValueCallBacks);
3356 CFDictionarySetValue(entity, kSCPropNetInterfaceDeviceName, bsdName);
3357 }
3358
3359 #if !TARGET_OS_IPHONE
3360 if ((flags & kIncludeBondInterfaces) == 0) {
3361 CFDictionarySetValue(entity, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue);
3362 }
3363 #endif // !TARGET_OS_IPHONE
3364
3365 if ((flags & kIncludeBridgeInterfaces) == 0) {
3366 CFDictionarySetValue(entity, CFSTR("_NO_BRIDGE_INTERFACES_"), kCFBooleanTrue);
3367 }
3368
3369 if ((flags & kIncludeVLANInterfaces) == 0) {
3370 CFDictionarySetValue(entity, CFSTR("_NO_VLAN_INTERFACES_"), kCFBooleanTrue);
3371 }
3372
3373 interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL);
3374 CFRelease(entity);
3375
3376 return interface;
3377 }
3378
3379
3380 static CFStringRef
3381 _SCNetworkInterfaceCopyPrefixFromBSDName(CFStringRef bsdName)
3382 {
3383 CFMutableStringRef interfacePrefix = NULL;
3384 UniChar lastChar;
3385 CFIndex length = 0;
3386
3387 if (isA_CFString(bsdName) == NULL) {
3388 SC_log(LOG_DEBUG, "no BSD name");
3389 goto done;
3390 }
3391
3392 interfacePrefix = CFStringCreateMutableCopy(NULL, 0, bsdName);
3393 length = CFStringGetLength(interfacePrefix);
3394
3395 while (length > 0) {
3396 lastChar = CFStringGetCharacterAtIndex(interfacePrefix, length - 1);
3397 if (lastChar >= '0' && lastChar <= '9') {
3398 CFStringDelete(interfacePrefix,
3399 CFRangeMake(length-1, 1));
3400 }
3401 else {
3402 break;
3403 }
3404 length = CFStringGetLength(interfacePrefix);
3405 }
3406 done:
3407 return interfacePrefix;
3408 }
3409
3410
3411 static void
3412 __SCNetworkInterfaceSetIOInterfacePrefix(SCNetworkInterfaceRef interface,
3413 CFStringRef prefix);
3414
3415
3416 static Boolean
3417 __SCNetworkInterfaceUpdateBSDName(SCNetworkInterfaceRef interface, CFStringRef currentBSDName, CFStringRef newBSDName)
3418 {
3419 Boolean success = FALSE;
3420 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3421
3422 if (isA_SCNetworkInterface(interface) == NULL) {
3423 SC_log(LOG_INFO, "No interface");
3424 goto done;
3425 }
3426
3427 if (CFEqual(currentBSDName, newBSDName)) {
3428 // if no change
3429 goto done;
3430 }
3431
3432 if (interfacePrivate->entity_device != NULL) {
3433 CFRelease(interfacePrivate->entity_device);
3434 }
3435 interfacePrivate->entity_device = CFRetain(newBSDName);
3436 success = TRUE;
3437 done:
3438 return success;
3439 }
3440
3441
3442 static Boolean
3443 __SCNetworkInterfaceUpdateIOPath(SCNetworkInterfaceRef interface)
3444 {
3445 Boolean success = FALSE;
3446 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3447 CFStringRef oldPath = NULL;
3448 CFStringRef newPath = NULL;
3449
3450 // Using the BSD Name update the path
3451 oldPath = interfacePrivate->path;
3452 if (isA_CFString(oldPath) == NULL) {
3453 goto done;
3454 }
3455 newPath = CFStringCreateWithFormat(NULL, NULL, CFSTR("Migrated_From: %@"), oldPath);
3456 if (interfacePrivate->path != NULL) {
3457 CFRelease(interfacePrivate->path);
3458 }
3459 interfacePrivate->path = CFRetain(newPath);
3460 success = TRUE;
3461
3462 done:
3463 if (newPath != NULL) {
3464 CFRelease(newPath);
3465 }
3466 return success;
3467 }
3468
3469
3470 static void
3471 __SCNetworkInterfaceSetIOInterfacePrefix (SCNetworkInterfaceRef interface,
3472 CFStringRef prefix)
3473 {
3474 SCNetworkInterfacePrivateRef interfacePrivate;
3475
3476 if (isA_CFString(prefix) == NULL) {
3477 return;
3478 }
3479
3480 interfacePrivate = (SCNetworkInterfacePrivateRef) interface;
3481
3482 CFRetain(prefix);
3483
3484 if (interfacePrivate->prefix != NULL) {
3485 CFRelease(interfacePrivate->prefix);
3486 }
3487
3488 interfacePrivate->prefix = prefix;
3489 return;
3490 }
3491
3492
3493 __private_extern__
3494 void
3495 __SCNetworkInterfaceSetIOInterfaceUnit(SCNetworkInterfaceRef interface,
3496 CFNumberRef unit)
3497 {
3498 SCNetworkInterfacePrivateRef interfacePrivate;
3499 CFStringRef newBSDName = NULL;
3500 CFStringRef oldBSDName = NULL;
3501
3502 if (isA_CFNumber(unit) == NULL) {
3503 return;
3504 }
3505 interfacePrivate = (SCNetworkInterfacePrivateRef) interface;
3506
3507 oldBSDName = SCNetworkInterfaceGetBSDName(interface);
3508
3509 if (interfacePrivate->prefix == NULL) {
3510 if (isA_CFString(interfacePrivate->entity_device) != NULL) {
3511 CFStringRef interfaceNamePrefix = _SCNetworkInterfaceCopyPrefixFromBSDName(interfacePrivate->entity_device);
3512 if (interfaceNamePrefix == NULL) {
3513 SC_log(LOG_INFO, "interfaceNamePrefix is NULL");
3514 }
3515 else {
3516 __SCNetworkInterfaceSetIOInterfacePrefix(interface, interfaceNamePrefix);
3517 CFRelease(interfaceNamePrefix);
3518 }
3519 }
3520 }
3521
3522 if (interfacePrivate->prefix != NULL) {
3523 newBSDName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), interfacePrivate->prefix, unit);
3524 }
3525
3526 // Update the BSD Name
3527 if ((newBSDName == NULL) ||
3528 (!__SCNetworkInterfaceUpdateBSDName(interface, oldBSDName, newBSDName))) {
3529 SC_log(LOG_INFO, "BSD name update failed");
3530 }
3531
3532 // Update the path
3533 if (!__SCNetworkInterfaceUpdateIOPath(interface)) {
3534 SC_log(LOG_INFO, "IOPath update failed");
3535 }
3536
3537 CFRetain(unit);
3538 if (interfacePrivate->unit != NULL) {
3539 CFRelease(interfacePrivate->unit);
3540 }
3541 interfacePrivate->unit = unit;
3542
3543
3544 if (newBSDName != NULL) {
3545 CFRelease(newBSDName);
3546 }
3547 return;
3548 }
3549
3550
3551 __private_extern__
3552 CFDictionaryRef
3553 __SCNetworkInterfaceCopyStorageEntity(SCNetworkInterfaceRef interface)
3554 {
3555 CFMutableDictionaryRef interface_entity = NULL;
3556 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3557 CFBooleanRef active = NULL;
3558 CFStringRef bsdName = NULL;
3559 CFBooleanRef builtin = NULL;
3560 CFStringRef interfaceNamePrefix = NULL;
3561 CFNumberRef interfaceType = NULL;
3562 CFNumberRef interfaceUnit = NULL;
3563 CFDataRef macAddress = NULL;
3564 CFStringRef pathMatch = NULL;
3565 CFDictionaryRef info = NULL;
3566 CFStringRef type = NULL;
3567
3568 if (interfacePrivate->active) {
3569 active = kCFBooleanTrue;
3570 }
3571
3572 bsdName = SCNetworkInterfaceGetBSDName(interface);
3573 if (!isA_CFString(bsdName)) {
3574 goto done;
3575 }
3576
3577 builtin = interfacePrivate->builtin ? kCFBooleanTrue : kCFBooleanFalse;
3578 interfaceNamePrefix = _SCNetworkInterfaceGetIOInterfaceNamePrefix(interface);
3579 if (!isA_CFString(interfaceNamePrefix)) {
3580 goto done;
3581 }
3582
3583 interfaceType = _SCNetworkInterfaceGetIOInterfaceType(interface);
3584 if (!isA_CFNumber(interfaceType)) {
3585 goto done;
3586 }
3587
3588 interfaceUnit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
3589 if (!isA_CFNumber(interfaceUnit)) {
3590 goto done;
3591 }
3592
3593 macAddress = _SCNetworkInterfaceGetHardwareAddress(interface);
3594 if (!isA_CFData(macAddress)) {
3595 goto done;
3596 }
3597
3598 pathMatch = _SCNetworkInterfaceGetIOPath(interface);
3599 if (!isA_CFString(pathMatch)) {
3600 goto done;
3601 }
3602
3603 info = _SCNetworkInterfaceCopyInterfaceInfo(interface);
3604 if (!isA_CFDictionary(info)) {
3605 goto done;
3606 }
3607
3608 type = SCNetworkInterfaceGetInterfaceType(interface);
3609 if (!isA_CFString(type)) {
3610 goto done;
3611 }
3612
3613 interface_entity = CFDictionaryCreateMutable(NULL, 0,
3614 &kCFTypeDictionaryKeyCallBacks,
3615 &kCFTypeDictionaryValueCallBacks);
3616
3617 if (isA_CFBoolean(active) != NULL) {
3618 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceActive), active);
3619 }
3620
3621 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceBSDName), bsdName);
3622 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOBuiltin), builtin);
3623 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceNamePrefix), interfaceNamePrefix);
3624 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceType), interfaceType);
3625 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceUnit), interfaceUnit);
3626 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOMACAddress), macAddress);
3627 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOPathMatch), pathMatch);
3628 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceInfo), info);
3629 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceType), type);
3630 done:
3631 if (info != NULL) {
3632 CFRelease(info);
3633 }
3634 return interface_entity;
3635 }
3636
3637
3638 static void
3639 __SCNetworkInterfaceSetService(SCNetworkInterfaceRef interface,
3640 SCNetworkServiceRef service)
3641 {
3642 SCNetworkInterfacePrivateRef interfacePrivate;
3643 SCNetworkServicePrivateRef servicePrivate;
3644
3645 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3646 if (interfacePrivate->prefs != NULL) {
3647 CFRelease(interfacePrivate->prefs);
3648 interfacePrivate->prefs = NULL;
3649 }
3650 if (interfacePrivate->serviceID != NULL) {
3651 CFRelease(interfacePrivate->serviceID);
3652 interfacePrivate->serviceID = NULL;
3653 }
3654
3655 servicePrivate = (SCNetworkServicePrivateRef)service;
3656 if (servicePrivate->prefs != NULL) {
3657 interfacePrivate->prefs = CFRetain(servicePrivate->prefs);
3658 }
3659 if (servicePrivate->serviceID != NULL) {
3660 interfacePrivate->serviceID = CFRetain(servicePrivate->serviceID);
3661 }
3662
3663 return;
3664 }
3665
3666
3667 __private_extern__
3668 Boolean
3669 __SCNetworkInterfaceMatchesName(CFStringRef name, CFStringRef key)
3670 {
3671 Boolean match;
3672 CFStringRef str;
3673
3674 if (bundle == NULL) {
3675 SC_log(LOG_NOTICE, "no bundle information to compare interface names");
3676 return FALSE;
3677 }
3678
3679 if (!isA_CFString(name)) {
3680 // if no interface "name"
3681 return FALSE;
3682 }
3683
3684 // check non-localized name for a match
3685 str = copy_interface_string(bundle, key, FALSE);
3686 if (str != NULL) {
3687 match = CFEqual(name, str);
3688 CFRelease(str);
3689 if (match) {
3690 return TRUE;
3691 }
3692 }
3693
3694 // check localized name for a match
3695 str = copy_interface_string(bundle, key, TRUE);
3696 if (str != NULL) {
3697 match = CFEqual(name, str);
3698 CFRelease(str);
3699 if (match) {
3700 return TRUE;
3701 }
3702 }
3703
3704 return FALSE;
3705 }
3706
3707
3708 #define kInterfaceTypeEthernetValue 6
3709 #define kInterfaceTypeFirewireValue 144
3710
3711
3712 static SCNetworkInterfaceRef
3713 __SCNetworkInterfaceCreateWithStorageEntity(CFAllocatorRef allocator,
3714 CFDictionaryRef interface_entity)
3715 {
3716 #pragma unused(allocator)
3717 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
3718 CFBooleanRef active = NULL;
3719 CFStringRef bsdName = NULL;
3720 CFBooleanRef ioBuiltin = NULL;
3721 CFStringRef ioInterfaceNamePrefix = NULL;
3722 CFNumberRef ioInterfaceType = NULL;
3723 int ioInterfaceTypeNum;
3724 CFNumberRef ioInterfaceUnit = NULL;
3725 CFDataRef ioMACAddress = NULL;
3726 CFStringRef ioPathMatch = NULL;
3727 CFDictionaryRef SCNetworkInterfaceInfo = NULL;
3728 CFStringRef userDefinedName = NULL;
3729 CFStringRef usbProductName = NULL;
3730 CFNumberRef idProduct = NULL;
3731 CFNumberRef idVendor = NULL;
3732 CFStringRef type = NULL;
3733
3734 /* initialize runtime */
3735 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3736
3737 if (isA_CFDictionary(interface_entity) == NULL) {
3738 SC_log(LOG_INFO, "No interface entity");
3739 goto done;
3740 }
3741 active = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceActive));
3742 if (isA_CFBoolean(active) == NULL) {
3743 active = kCFBooleanFalse;
3744 }
3745 bsdName = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceBSDName));
3746 if (isA_CFString(bsdName) == NULL) {
3747 SC_log(LOG_INFO, "No BSD name");
3748 goto done;
3749 }
3750 ioBuiltin = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOBuiltin));
3751 if (isA_CFBoolean(ioBuiltin) == NULL) {
3752 SC_log(LOG_INFO, "No IOBuiltin property");
3753 goto done;
3754 }
3755 ioInterfaceNamePrefix = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceNamePrefix));
3756 if (isA_CFString(ioInterfaceNamePrefix) == NULL) {
3757 ioInterfaceNamePrefix = _SCNetworkInterfaceCopyPrefixFromBSDName(bsdName);
3758 if (ioInterfaceNamePrefix == NULL) {
3759 SC_log(LOG_INFO, "No BSD interface name prefix");
3760 goto done;
3761 }
3762 } else {
3763 CFRetain(ioInterfaceNamePrefix);
3764 }
3765 ioInterfaceType = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceType));
3766 if (isA_CFNumber(ioInterfaceType) == NULL) {
3767 SC_log(LOG_INFO, "No IOInterfaceType");
3768 goto done;
3769 }
3770 if (!CFNumberGetValue(ioInterfaceType, kCFNumberIntType, &ioInterfaceTypeNum)) {
3771 SC_log(LOG_NOTICE, "Count not extract value from ioInterfaceType");
3772 }
3773 ioInterfaceUnit = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceUnit));
3774 if (isA_CFNumber(ioInterfaceUnit) == NULL) {
3775 SC_log(LOG_INFO, "No IOInterfaceUnit");
3776
3777 goto done;
3778 }
3779 ioMACAddress = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOMACAddress));
3780 if (isA_CFData(ioMACAddress) == NULL) {
3781 SC_log(LOG_INFO, "No IOMACAddress");
3782 goto done;
3783 }
3784 ioPathMatch = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOPathMatch));
3785 if (isA_CFString(ioPathMatch) == NULL) {
3786 SC_log(LOG_INFO, "No IOPathMatch");
3787 goto done;
3788 } else {
3789 // Check if Path contains the BSD Name in the end
3790 }
3791 SCNetworkInterfaceInfo = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceInfo));
3792 if (isA_CFDictionary(SCNetworkInterfaceInfo) == NULL) {
3793 SC_log(LOG_INFO, "No SCNetworkInterfaceInfo");
3794 goto done;
3795 }
3796 userDefinedName = CFDictionaryGetValue(SCNetworkInterfaceInfo, kSCPropUserDefinedName);
3797 #if !TARGET_OS_SIMULATOR
3798 usbProductName = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBProductString));
3799 idProduct = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBProductID));
3800 idVendor = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBVendorID));
3801 #endif // !TARGET_OS_SIMULATOR
3802
3803 type = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceType));
3804 if (isA_CFString(type) == NULL) {
3805 SC_log(LOG_INFO, "No SCNetworkInterfaceType");
3806 goto done;
3807 }
3808
3809 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
3810 interfacePrivate->active = CFBooleanGetValue(active);
3811 interfacePrivate->entity_device = CFRetain(bsdName);
3812 interfacePrivate->builtin = CFBooleanGetValue(ioBuiltin);
3813 interfacePrivate->prefix = CFRetain(ioInterfaceNamePrefix);
3814 interfacePrivate->type = CFRetain(ioInterfaceType);
3815 interfacePrivate->unit = CFRetain(ioInterfaceUnit);
3816 interfacePrivate->address = CFRetain(ioMACAddress);
3817 interfacePrivate->path = CFRetain(ioPathMatch);
3818 interfacePrivate->name = ((userDefinedName != NULL) ? CFRetain(userDefinedName) : NULL);
3819 interfacePrivate->localized_name = ((userDefinedName != NULL) ? CFRetain(userDefinedName) : NULL);
3820 interfacePrivate->usb.name = ((usbProductName != NULL) ? CFRetain(usbProductName) : NULL);
3821 interfacePrivate->usb.pid = ((idProduct != NULL) ? CFRetain(idProduct) : NULL);
3822 interfacePrivate->usb.vid = ((idVendor != NULL) ? CFRetain(idVendor) : NULL);
3823
3824 // Handling interface types to be seen in NetworkInterfaces.plist
3825 CFIndex interfaceIndex;
3826
3827 interfaceIndex = findConfiguration(type);
3828 if (interfaceIndex != kCFNotFound) {
3829 interfacePrivate->interface_type = *configurations[interfaceIndex].interface_type;
3830 } else {
3831 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
3832 }
3833
3834 // Extracting entity type from value of interface type
3835 if (ioInterfaceTypeNum == kInterfaceTypeEthernetValue) {
3836 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; // kSCNetworkInterfaceTypeEthernet;
3837 } else if (ioInterfaceTypeNum == kInterfaceTypeFirewireValue) {
3838 interfacePrivate->entity_type = kSCValNetInterfaceTypeFireWire;
3839 }
3840 done:
3841 if (ioInterfaceNamePrefix != NULL) {
3842 CFRelease(ioInterfaceNamePrefix);
3843 }
3844
3845 return (SCNetworkInterfaceRef)interfacePrivate;
3846 }
3847
3848
3849 void
3850 _SCNetworkInterfaceCacheOpen()
3851 {
3852 if (!__SCNetworkInterfaceCacheIsOpen()) {
3853 S_interface_cache = CFDictionaryCreateMutable(NULL,
3854 0,
3855 &kCFTypeDictionaryKeyCallBacks,
3856 &kCFTypeDictionaryValueCallBacks);
3857 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): open", S_interface_cache);
3858 }
3859 }
3860
3861
3862 void
3863 _SCNetworkInterfaceCacheClose()
3864 {
3865 if (__SCNetworkInterfaceCacheIsOpen()) {
3866 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): close", S_interface_cache);
3867 CFRelease(S_interface_cache);
3868 S_interface_cache = NULL;
3869 }
3870 }
3871
3872
3873 static void
3874 __SCNetworkInterfaceCacheAdd(CFStringRef bsdName, CFArrayRef matchingInterfaces)
3875 {
3876 if (__SCNetworkInterfaceCacheIsOpen() &&
3877 bsdName != NULL &&
3878 matchingInterfaces != NULL) {
3879 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): add %@", S_interface_cache, bsdName);
3880 CFDictionaryAddValue(S_interface_cache, bsdName, matchingInterfaces);
3881 }
3882 }
3883
3884
3885 static inline Boolean
3886 __SCNetworkInterfaceCacheIsOpen()
3887 {
3888 return (S_interface_cache != NULL);
3889 }
3890
3891
3892 static CFArrayRef
3893 __SCNetworkInterfaceCacheCopy(CFStringRef bsdName)
3894 {
3895 if (__SCNetworkInterfaceCacheIsOpen() &&
3896 bsdName != NULL) {
3897 CFArrayRef matchingInterfaces = CFDictionaryGetValue(S_interface_cache, bsdName);
3898 if (matchingInterfaces) {
3899 CFRetain(matchingInterfaces);
3900 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): copy w/ match for %@", S_interface_cache, bsdName);
3901 } else {
3902 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): copy w/ no match for %@", S_interface_cache, bsdName);
3903 }
3904
3905 return matchingInterfaces;
3906 }
3907
3908 return NULL;
3909 }
3910
3911
3912 SCNetworkInterfaceRef
3913 _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator,
3914 CFDictionaryRef interface_entity,
3915 SCNetworkServiceRef service)
3916 {
3917 #pragma unused(allocator)
3918 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
3919 CFStringRef ifDevice;
3920 CFStringRef ifName = NULL;
3921 CFStringRef ifSubType;
3922 CFStringRef ifType;
3923 CFStringRef ifUnique;
3924 CFArrayRef matching_interfaces = NULL;
3925 SCPreferencesRef servicePref = NULL;
3926 Boolean useSystemInterfaces = TRUE;
3927
3928 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3929 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3930
3931 if (service != NULL) {
3932 servicePref = ((SCNetworkServicePrivateRef)service)->prefs;
3933 useSystemInterfaces = ((__SCPreferencesUsingDefaultPrefs(servicePref)) &&
3934 (!__SCPreferencesGetLimitSCNetworkConfiguration(servicePref)));
3935 }
3936
3937 ifType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceType);
3938 if (ifType == NULL) {
3939 /*
3940 * The interface "Type" was not specified. We'll make an
3941 * assumption that this is an "Ethernet" interface. If a
3942 * real interface exists with the provided interface name
3943 * then the actual type will be set accordingly. If not, we'll
3944 * end up crafting an "Ethernet" SCNetworkInterface that
3945 * will keep the rest of the configuration APIs happy.
3946 */
3947 ifType = kSCValNetInterfaceTypeEthernet;
3948 }
3949
3950 if (!isA_CFString(ifType)) {
3951 return NULL;
3952 }
3953
3954 ifSubType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceSubType);
3955 if (CFEqual(ifType, kSCValNetInterfaceTypePPP) ||
3956 CFEqual(ifType, kSCValNetInterfaceTypeVPN)) {
3957 if (!isA_CFString(ifSubType)) {
3958 return NULL;
3959 }
3960 }
3961
3962 ifDevice = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceDeviceName);
3963 ifUnique = CFDictionaryGetValue(interface_entity, CFSTR("DeviceUniqueIdentifier"));
3964
3965 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet) ||
3966 CFEqual(ifType, kSCValNetInterfaceTypeFireWire) ||
3967 (CFEqual(ifType, kSCValNetInterfaceTypePPP) && CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE))) {
3968 char bsdName[IFNAMSIZ];
3969 CFMutableDictionaryRef matching;
3970
3971 if (!isA_CFString(ifDevice)) {
3972 return NULL;
3973 }
3974
3975 if (CFEqual(ifDevice, CFSTR("lo0"))) { // for _SCNetworkInterfaceCreateWithBSDName
3976 interfacePrivate = __SCNetworkInterfaceCreateCopy(NULL, kSCNetworkInterfaceLoopback, NULL, NULL);
3977 goto done;
3978 }
3979 if (useSystemInterfaces) {
3980 // Check to see if we already have the info in the cache
3981 matching_interfaces = __SCNetworkInterfaceCacheCopy(ifDevice);
3982 if (matching_interfaces == NULL) {
3983 if (_SC_cfstring_to_cstring(ifDevice, bsdName, sizeof(bsdName), kCFStringEncodingASCII) == NULL) {
3984 goto done;
3985 }
3986
3987 matching = IOBSDNameMatching(masterPort, 0, bsdName);
3988 if (matching == NULL) {
3989 goto done;
3990 }
3991 matching_interfaces = findMatchingInterfaces(matching,
3992 processNetworkInterface,
3993 kSCNetworkInterfaceHiddenInterfaceKey,
3994 TRUE);
3995
3996 __SCNetworkInterfaceCacheAdd(ifDevice, matching_interfaces);
3997 CFRelease(matching);
3998 }
3999 }
4000 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
4001 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
4002 CFDictionaryRef matching;
4003 CFStringRef match_keys[2];
4004 CFStringRef match_vals[2];
4005
4006 if (!isA_CFString(ifDevice)) {
4007 return NULL;
4008 }
4009
4010 if (useSystemInterfaces) {
4011 match_keys[0] = CFSTR(kIOProviderClassKey);
4012 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
4013
4014 match_keys[1] = CFSTR(kIOTTYBaseNameKey);
4015 match_vals[1] = ifDevice;
4016
4017 matching = CFDictionaryCreate(NULL,
4018 (const void **)match_keys,
4019 (const void **)match_vals,
4020 sizeof(match_keys)/sizeof(match_keys[0]),
4021 &kCFTypeDictionaryKeyCallBacks,
4022 &kCFTypeDictionaryValueCallBacks);
4023 matching_interfaces = findMatchingInterfaces(matching,
4024 processSerialInterface,
4025 kSCNetworkInterfaceHiddenPortKey,
4026 TRUE);
4027 CFRelease(matching);
4028 }
4029 if (ifUnique == NULL) {
4030 CFIndex n;
4031 Boolean useDeviceName = TRUE;
4032
4033 n = (matching_interfaces != NULL) ? CFArrayGetCount(matching_interfaces) : 0;
4034 if (n > 0) {
4035 CFIndex i;
4036
4037 for (i = 0; i < n; i++) {
4038 SCNetworkInterfacePrivateRef scanPrivate;
4039
4040 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i);
4041 if (scanPrivate->entity_device_unique != NULL) {
4042 useDeviceName = FALSE;
4043 break;
4044 }
4045 }
4046 }
4047
4048 if (useDeviceName && useSystemInterfaces) {
4049 if (matching_interfaces != NULL) {
4050 CFRelease(matching_interfaces);
4051 }
4052
4053 match_keys[1] = CFSTR(kIOTTYDeviceKey);
4054 matching = CFDictionaryCreate(NULL,
4055 (const void **)match_keys,
4056 (const void **)match_vals,
4057 sizeof(match_keys)/sizeof(match_keys[0]),
4058 &kCFTypeDictionaryKeyCallBacks,
4059 &kCFTypeDictionaryValueCallBacks);
4060 matching_interfaces = findMatchingInterfaces(matching,
4061 processSerialInterface,
4062 kSCNetworkInterfaceHiddenPortKey,
4063 TRUE);
4064 CFRelease(matching);
4065 }
4066 }
4067 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypeL2TP)) {
4068 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4069 kSCNetworkInterfaceTypeL2TP);
4070 #pragma GCC diagnostic push
4071 #pragma GCC diagnostic ignored "-Wdeprecated"
4072 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPTP)) {
4073 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4074 kSCNetworkInterfaceTypePPTP);
4075 #pragma GCC diagnostic pop
4076 } else {
4077 // XXX do we allow non-Apple variants of PPP??? XXX
4078 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4079 ifSubType);
4080 }
4081 } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) {
4082 if (!isA_CFString(ifDevice)) {
4083 return NULL;
4084 }
4085
4086 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4087 kSCNetworkInterfaceType6to4);
4088 } else if (CFEqual(ifType, kSCValNetInterfaceTypeIPSec)) {
4089 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4090 kSCNetworkInterfaceTypeIPSec);
4091 } else if (CFEqual(ifType, kSCValNetInterfaceTypeLoopback)) {
4092 interfacePrivate = __SCNetworkInterfaceCreateCopy(NULL, kSCNetworkInterfaceLoopback, NULL, NULL);
4093 } else if (CFEqual(ifType, kSCValNetInterfaceTypeVPN)) {
4094 if (CFStringFind(ifSubType, CFSTR("."), 0).location != kCFNotFound) {
4095 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4096 ifSubType);
4097 }
4098 } else if ((CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) && (ifDevice == NULL)) {
4099 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4100 ifType);
4101 }
4102
4103 if (matching_interfaces != NULL) {
4104 CFIndex n;
4105 SCPreferencesRef prefs;
4106 Boolean temp_preferences = FALSE;
4107
4108 n = CFArrayGetCount(matching_interfaces);
4109 switch (n) {
4110 case 1 :
4111 interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0);
4112 if (_SC_CFEqual(ifUnique, interfacePrivate->entity_device_unique)) {
4113 // if the unique ID's match
4114 CFRetain(interfacePrivate);
4115 break;
4116 }
4117
4118 interfacePrivate = NULL;
4119 // fall through
4120 case 0 :
4121 if (!CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
4122 break;
4123 }
4124
4125 if (CFDictionaryGetValueIfPresent(interface_entity,
4126 kSCPropUserDefinedName,
4127 (const void **)&ifName) &&
4128 CFEqual(ifName, CFSTR(BT_PAN_NAME))) {
4129 break;
4130 }
4131
4132 prefs = (service != NULL) ? ((SCNetworkServicePrivateRef)service)->prefs : NULL;
4133 if (prefs == NULL) {
4134 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), NULL);
4135 if (prefs != NULL) {
4136 temp_preferences = TRUE;
4137 }
4138 }
4139 if (prefs == NULL) {
4140 break;
4141 }
4142 #if !TARGET_OS_IPHONE
4143 if (!CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BOND_INTERFACES_"))) {
4144 interfacePrivate = (SCNetworkInterfacePrivateRef)findBondInterface(prefs, ifDevice);
4145 }
4146 #endif // !TARGET_OS_IPHONE
4147 if ((interfacePrivate == NULL)
4148 && !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BRIDGE_INTERFACES_"))) {
4149 interfacePrivate = (SCNetworkInterfacePrivateRef)findBridgeInterface(prefs, ifDevice);
4150 }
4151
4152 if ((interfacePrivate == NULL)
4153 && !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_VLAN_INTERFACES_"))) {
4154 interfacePrivate = (SCNetworkInterfacePrivateRef)findVLANInterface(prefs, ifDevice);
4155 }
4156 if (temp_preferences) CFRelease(prefs);
4157 break;
4158 default :
4159 if (ifUnique != NULL) {
4160 CFIndex i;
4161
4162 // we are looking for an interface with a unique ID
4163 // so let's try to focus our choices
4164 for (i = 0; i < n; i++) {
4165 SCNetworkInterfacePrivateRef scanPrivate;
4166
4167 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i);
4168 if (_SC_CFEqual(ifUnique, scanPrivate->entity_device_unique)) {
4169 if (interfacePrivate != NULL) {
4170 // if we've matched more than one interface
4171 interfacePrivate = NULL;
4172 break;
4173 }
4174 interfacePrivate = scanPrivate;
4175 }
4176 }
4177 } else if (CFDictionaryGetValueIfPresent(interface_entity,
4178 kSCPropUserDefinedName,
4179 (const void **)&ifName)) {
4180 CFIndex i;
4181
4182 // we don't have a unique ID but do have an interface
4183 // name. If the matching interfaces do have IDs than
4184 // we can try to focus our choices using the name
4185 for (i = 0; i < n; i++) {
4186 SCNetworkInterfacePrivateRef scanPrivate;
4187
4188 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i);
4189 if (scanPrivate->entity_device_unique != NULL) {
4190 SCNetworkInterfaceRef scan = (SCNetworkInterfaceRef)scanPrivate;
4191 CFStringRef scanName;
4192
4193 scanName = __SCNetworkInterfaceGetNonLocalizedDisplayName(scan);
4194 if ((scanName != NULL) && !_SC_CFEqual(ifName, scanName)) {
4195 continue; // if not the same display name
4196 }
4197 }
4198
4199 if (interfacePrivate != NULL) {
4200 // if we've matched more than one interface
4201 interfacePrivate = NULL;
4202 break;
4203 }
4204 interfacePrivate = scanPrivate;
4205 }
4206 }
4207 if (interfacePrivate == NULL) {
4208 SC_log(LOG_NOTICE, "more than one interface matches %@", ifDevice);
4209 interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0);
4210 }
4211 CFRetain(interfacePrivate);
4212 break;
4213 }
4214 CFRelease(matching_interfaces);
4215 }
4216
4217 done :
4218
4219 if ((interfacePrivate == NULL) || !useSystemInterfaces) {
4220 /*
4221 * if device not present on this system
4222 */
4223 if (!useSystemInterfaces) {
4224 if (interfacePrivate != NULL) {
4225 CFRelease(interfacePrivate);
4226 }
4227 }
4228
4229 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
4230 interfacePrivate->entity_type = (ifType != NULL) ? ifType : NULL;
4231 interfacePrivate->entity_subtype = (ifSubType != NULL) ? ifSubType : NULL;
4232 interfacePrivate->entity_device = (ifDevice != NULL) ? CFStringCreateCopy(NULL, ifDevice) : NULL;
4233 interfacePrivate->entity_device_unique = (ifUnique != NULL) ? CFStringCreateCopy(NULL, ifUnique) : NULL;
4234
4235 // Using UserDefinedName to check the validity of preferences file
4236 // when useSystemInterfaces is FALSE
4237 if (!useSystemInterfaces) {
4238 CFStringRef userDefinedName = CFDictionaryGetValue(interface_entity, kSCPropUserDefinedName);
4239 if (isA_CFString(userDefinedName) != NULL) {
4240 CFRetain(userDefinedName);
4241 if (interfacePrivate->name != NULL) {
4242 CFRelease(interfacePrivate->name);
4243 }
4244 interfacePrivate->name = userDefinedName;
4245
4246 CFRetain(userDefinedName);
4247 if (interfacePrivate->localized_name != NULL) {
4248 CFRelease(interfacePrivate->localized_name);
4249 }
4250 interfacePrivate->localized_name = userDefinedName;
4251 }
4252 }
4253
4254 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
4255 CFStringRef entity_hardware;
4256 SCNetworkInterfaceRef virtualInterface;
4257
4258 if (!useSystemInterfaces &&
4259 (((virtualInterface = findBridgeInterface(servicePref, ifDevice)) != NULL) ||
4260 #if !TARGET_OS_IPHONE
4261 ((virtualInterface = findBondInterface(servicePref, ifDevice)) != NULL) ||
4262 #endif
4263 ((virtualInterface = findVLANInterface(servicePref, ifDevice)) != NULL))) {
4264 CFRelease(interfacePrivate);
4265 interfacePrivate = (SCNetworkInterfacePrivateRef)virtualInterface;
4266 } else {
4267 entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware);
4268 if (isA_CFString((entity_hardware)) &&
4269 CFEqual(entity_hardware, kSCEntNetAirPort)) {
4270 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
4271 interfacePrivate->localized_key = CFSTR("airport");
4272 interfacePrivate->sort_order = kSortAirPort;
4273 } else {
4274 CFStringRef name;
4275
4276 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
4277
4278 name = CFDictionaryGetValue(interface_entity, kSCPropUserDefinedName);
4279 if (__SCNetworkInterfaceMatchesName(name, CFSTR("iPhone"))) {
4280 interfacePrivate->localized_key = CFSTR("iPhone");
4281 interfacePrivate->sort_order = kSortTethered;
4282 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("iPad"))) {
4283 interfacePrivate->localized_key = CFSTR("iPad");
4284 interfacePrivate->sort_order = kSortTethered;
4285 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("thunderbolt"))) {
4286 interfacePrivate->localized_key = CFSTR("thunderbolt");
4287 interfacePrivate->sort_order = kSortThunderbolt;
4288 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("bluetooth-pan-gn"))) {
4289 interfacePrivate->localized_key = CFSTR("bluetooth-pan-gn");
4290 interfacePrivate->sort_order = kSortBluetoothPAN_GN;
4291 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("bluetooth-pan-nap"))) {
4292 interfacePrivate->localized_key = CFSTR("bluetooth-pan-nap");
4293 interfacePrivate->sort_order = kSortBluetoothPAN_NAP;
4294 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("bluetooth-pan-u"))) {
4295 interfacePrivate->localized_key = CFSTR("bluetooth-pan-u");
4296 interfacePrivate->sort_order = kSortBluetoothPAN_U;
4297 } else {
4298 interfacePrivate->sort_order = kSortEthernet;
4299 }
4300 }
4301 }
4302 } else if (CFEqual(ifType, kSCValNetInterfaceTypeFireWire)) {
4303 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
4304 interfacePrivate->sort_order = kSortFireWire;
4305 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP) && (ifSubType != NULL)) {
4306 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE)) {
4307 CFStringRef entity_hardware;
4308
4309 entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware);
4310 if (isA_CFString((entity_hardware)) &&
4311 CFEqual(entity_hardware, kSCEntNetAirPort)) {
4312 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
4313 interfacePrivate->sort_order = kSortAirPort;
4314 } else {
4315 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
4316 interfacePrivate->sort_order = kSortEthernet;
4317 }
4318 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
4319 if (CFStringHasPrefix(ifDevice, CFSTR("Bluetooth"))) {
4320 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
4321 interfacePrivate->sort_order = kSortBluetooth;
4322 } else if (CFStringHasPrefix(ifDevice, CFSTR("irda"))) {
4323 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
4324 interfacePrivate->sort_order = kSortIrDA;
4325 } else if (CFStringHasPrefix(ifDevice, CFSTR("wwan"))) {
4326 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN;
4327 interfacePrivate->sort_order = kSortWWAN;
4328 } else {
4329 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
4330 interfacePrivate->sort_order = kSortModem;
4331 }
4332 } else {
4333 SCNetworkInterfaceRef child;
4334 // PPTP, L2TP, ...
4335 CFRelease(interfacePrivate);
4336 child = SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, ifSubType);
4337 interfacePrivate = (SCNetworkInterfacePrivateRef)child;
4338 if (interfacePrivate == NULL) {
4339 return NULL;
4340 }
4341 }
4342 } else if (CFEqual(ifType, kSCValNetInterfaceTypeVPN) && (ifSubType != NULL)) {
4343 SCNetworkInterfaceRef child;
4344 CFRelease(interfacePrivate);
4345 child = SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, ifSubType);
4346 interfacePrivate = (SCNetworkInterfacePrivateRef)child;
4347 if (interfacePrivate == NULL) {
4348 return NULL;
4349 }
4350 } else if (CFEqual(ifType, kSCValNetInterfaceTypeIPSec)) {
4351 CFRelease(interfacePrivate);
4352 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4353 kSCNetworkInterfaceTypeIPSec);
4354 } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) {
4355 CFRelease(interfacePrivate);
4356 if (!isA_CFString(ifDevice)) {
4357 return NULL;
4358 }
4359 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
4360 kSCNetworkInterfaceType6to4);
4361 } else if (CFEqual(ifType, kSCValNetInterfaceTypeLoopback)) {
4362 CFRelease(interfacePrivate);
4363 interfacePrivate = __SCNetworkInterfaceCreateCopy(NULL, kSCNetworkInterfaceLoopback, NULL, NULL);
4364 } else if (CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) {
4365 // if vendor interface
4366 pthread_mutex_lock(&lock);
4367 if (vendor_interface_types == NULL) {
4368 vendor_interface_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
4369 }
4370 CFSetAddValue(vendor_interface_types, ifType);
4371 interfacePrivate->interface_type = CFSetGetValue(vendor_interface_types, ifType);
4372 pthread_mutex_unlock(&lock);
4373 } else {
4374 // if unknown interface
4375 CFRelease(interfacePrivate);
4376 interfacePrivate = NULL;
4377 return NULL;
4378 }
4379
4380 if (CFDictionaryContainsKey(interface_entity, kSCNetworkInterfaceHiddenConfigurationKey)) {
4381 interfacePrivate->hidden = TRUE;
4382 }
4383 }
4384
4385 if (service != NULL) {
4386 __SCNetworkInterfaceSetService((SCNetworkInterfaceRef)interfacePrivate,
4387 service);
4388
4389 #if !TARGET_OS_IPHONE
4390 // set prefs & serviceID to Bond member interfaces
4391 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBond)) {
4392 CFIndex i;
4393 CFArrayRef members;
4394 CFIndex n;
4395
4396 members = SCBondInterfaceGetMemberInterfaces((SCNetworkInterfaceRef)interfacePrivate);
4397 n = (members != NULL) ? CFArrayGetCount(members) : 0;
4398 for (i = 0; i < n; i++) {
4399 SCNetworkInterfaceRef member;
4400
4401 member = CFArrayGetValueAtIndex(members, i);
4402 __SCNetworkInterfaceSetService(member, service);
4403 }
4404 }
4405 #endif // !TARGET_OS_IPHONE
4406
4407 // set prefs & serviceID to Bridge member interfaces
4408 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBridge)) {
4409 CFIndex i;
4410 CFArrayRef members;
4411 CFIndex n;
4412
4413 members = SCBridgeInterfaceGetMemberInterfaces((SCNetworkInterfaceRef)interfacePrivate);
4414 n = (members != NULL) ? CFArrayGetCount(members) : 0;
4415 for (i = 0; i < n; i++) {
4416 SCNetworkInterfaceRef member;
4417
4418 member = CFArrayGetValueAtIndex(members, i);
4419 __SCNetworkInterfaceSetService(member, service);
4420 }
4421 }
4422 // set prefs & serviceID to VLAN pyhsical interface
4423 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeVLAN)) {
4424 SCNetworkInterfaceRef vlan_physical;
4425
4426 vlan_physical = SCVLANInterfaceGetPhysicalInterface((SCNetworkInterfaceRef)interfacePrivate);
4427 if (vlan_physical != NULL) {
4428 __SCNetworkInterfaceSetService(vlan_physical, service);
4429 }
4430 }
4431 }
4432
4433 if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
4434 SCNetworkInterfaceRef parent;
4435
4436 // create parent
4437 parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate,
4438 kSCNetworkInterfaceTypePPP);
4439 CFRelease(interfacePrivate);
4440 interfacePrivate = (SCNetworkInterfacePrivateRef)parent;
4441 } else if (CFEqual(ifType, kSCValNetInterfaceTypeVPN)) {
4442 SCNetworkInterfaceRef parent;
4443
4444 // create parent
4445 parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate,
4446 kSCNetworkInterfaceTypeVPN);
4447 CFRelease(interfacePrivate);
4448 interfacePrivate = (SCNetworkInterfacePrivateRef)parent;
4449 }
4450
4451 return (SCNetworkInterfaceRef)interfacePrivate;
4452 }
4453
4454
4455 #pragma mark -
4456 #pragma mark SCNetworkInterface APIs
4457
4458
4459 __private_extern__
4460 CFArrayRef
4461 __SCNetworkInterfaceCopyAll_IONetworkInterface(Boolean keep_pre_configured)
4462 {
4463 CFDictionaryRef matching;
4464 CFArrayRef new_interfaces;
4465
4466 // get Ethernet, Firewire, Thunderbolt, and AirPort interfaces
4467
4468 matching = IOServiceMatching(kIONetworkInterfaceClass);
4469 new_interfaces = findMatchingInterfaces(matching,
4470 processNetworkInterface,
4471 kSCNetworkInterfaceHiddenInterfaceKey,
4472 keep_pre_configured);
4473 CFRelease(matching);
4474
4475 return new_interfaces;
4476 }
4477
4478
4479 static
4480 CFArrayRef
4481 __SCNetworkInterfaceCopyAll_Modem()
4482 {
4483 CFDictionaryRef matching;
4484 CFStringRef match_keys[2];
4485 CFStringRef match_vals[2];
4486 CFArrayRef new_interfaces;
4487
4488 match_keys[0] = CFSTR(kIOProviderClassKey);
4489 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
4490
4491 match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
4492 match_vals[1] = CFSTR(kIOSerialBSDModemType);
4493
4494 matching = CFDictionaryCreate(NULL,
4495 (const void **)match_keys,
4496 (const void **)match_vals,
4497 sizeof(match_keys)/sizeof(match_keys[0]),
4498 &kCFTypeDictionaryKeyCallBacks,
4499 &kCFTypeDictionaryValueCallBacks);
4500 new_interfaces = findMatchingInterfaces(matching,
4501 processSerialInterface,
4502 kSCNetworkInterfaceHiddenPortKey,
4503 FALSE);
4504 CFRelease(matching);
4505
4506 return new_interfaces;
4507 }
4508
4509
4510 static
4511 CFArrayRef
4512 __SCNetworkInterfaceCopyAll_RS232()
4513 {
4514 CFDictionaryRef matching;
4515 CFStringRef match_keys[2];
4516 CFStringRef match_vals[2];
4517 CFArrayRef new_interfaces;
4518
4519 match_keys[0] = CFSTR(kIOProviderClassKey);
4520 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
4521
4522 match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
4523 match_vals[1] = CFSTR(kIOSerialBSDRS232Type);
4524
4525 matching = CFDictionaryCreate(NULL,
4526 (const void **)match_keys,
4527 (const void **)match_vals,
4528 sizeof(match_keys)/sizeof(match_keys[0]),
4529 &kCFTypeDictionaryKeyCallBacks,
4530 &kCFTypeDictionaryValueCallBacks);
4531 new_interfaces = findMatchingInterfaces(matching,
4532 processSerialInterface,
4533 kSCNetworkInterfaceHiddenPortKey,
4534 FALSE);
4535 CFRelease(matching);
4536
4537 return new_interfaces;
4538 }
4539
4540
4541 #if !TARGET_OS_IPHONE
4542 static void
4543 addBTPANInterface(CFMutableArrayRef all_interfaces)
4544 {
4545 CFIndex i;
4546 SCNetworkInterfaceRef interface;
4547 CFIndex n;
4548
4549 n = CFArrayGetCount(all_interfaces);
4550 for (i = 0; i < n; i++) {
4551 SCNetworkInterfaceRef interface;
4552
4553 interface = CFArrayGetValueAtIndex(all_interfaces, i);
4554 if (_SCNetworkInterfaceIsBluetoothPAN(interface)) {
4555 // if we already have a BT-PAN interface
4556 return;
4557 }
4558 }
4559
4560 interface = _SCNetworkInterfaceCopyBTPANInterface();
4561 if (interface != NULL) {
4562 // include BT-PAN interface
4563 CFArrayAppendValue(all_interfaces, interface);
4564 CFRelease(interface);
4565 }
4566
4567 return;
4568 }
4569 #endif // !TARGET_OS_IPHONE
4570
4571
4572 static void
4573 add_interfaces(CFMutableArrayRef all_interfaces, CFArrayRef new_interfaces)
4574 {
4575 CFIndex i;
4576 CFIndex n;
4577
4578 n = CFArrayGetCount(new_interfaces);
4579 for (i = 0; i < n; i++) {
4580 CFStringRef bsdName;
4581 SCNetworkInterfaceRef interface;
4582
4583 interface = CFArrayGetValueAtIndex(new_interfaces, i);
4584 bsdName = SCNetworkInterfaceGetBSDName(interface);
4585 if (bsdName != NULL) {
4586 CFArrayAppendValue(all_interfaces, interface);
4587 }
4588 }
4589
4590 return;
4591 }
4592
4593
4594 static void
4595 __waitForInterfaces()
4596 {
4597 CFStringRef key;
4598 CFArrayRef keys;
4599 Boolean ok;
4600 SCDynamicStoreRef store;
4601
4602 store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL, NULL);
4603 if (store == NULL) {
4604 return;
4605 }
4606
4607 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin);
4608 keys = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
4609 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
4610 CFRelease(keys);
4611 if (!ok) {
4612 SC_log(LOG_NOTICE, "SCDynamicStoreSetNotificationKeys() failed: %s", SCErrorString(SCError()));
4613 goto done;
4614 }
4615
4616 while (TRUE) {
4617 CFArrayRef changedKeys;
4618 CFDictionaryRef dict;
4619 Boolean quiet = FALSE;
4620
4621 // check if quiet
4622 dict = SCDynamicStoreCopyValue(store, key);
4623 if (dict != NULL) {
4624 if (isA_CFDictionary(dict) &&
4625 (CFDictionaryContainsKey(dict, kInterfaceNamerKey_Quiet) ||
4626 CFDictionaryContainsKey(dict, kInterfaceNamerKey_Timeout))) {
4627 quiet = TRUE;
4628 }
4629 CFRelease(dict);
4630 }
4631 if (quiet) {
4632 break;
4633 }
4634
4635 ok = SCDynamicStoreNotifyWait(store);
4636 if (!ok) {
4637 SC_log(LOG_NOTICE, "SCDynamicStoreNotifyWait() failed: %s", SCErrorString(SCError()));
4638 goto done;
4639 }
4640
4641 changedKeys = SCDynamicStoreCopyNotifiedKeys(store);
4642 if (changedKeys != NULL) {
4643 CFRelease(changedKeys);
4644 }
4645 }
4646
4647 done :
4648
4649 CFRelease(key);
4650 CFRelease(store);
4651 return;
4652 }
4653
4654
4655 CFArrayRef /* of SCNetworkInterfaceRef's */
4656 _SCNetworkInterfaceCopyAllWithPreferences(SCPreferencesRef prefs)
4657 {
4658 CFMutableArrayRef all_interfaces;
4659 CFArrayRef new_interfaces;
4660 Boolean temp_preferences = FALSE;
4661
4662 /* initialize runtime */
4663 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
4664
4665 /* wait for IOKit to quiesce */
4666 pthread_once(&iokit_quiet, __waitForInterfaces);
4667
4668 all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
4669
4670 // get Ethernet, Firewire, Thunderbolt, and AirPort interfaces
4671 new_interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE);
4672 if (new_interfaces != NULL) {
4673 add_interfaces(all_interfaces, new_interfaces);
4674 CFRelease(new_interfaces);
4675 }
4676
4677 // get Modem interfaces
4678 new_interfaces = __SCNetworkInterfaceCopyAll_Modem();
4679 if (new_interfaces != NULL) {
4680 add_interfaces(all_interfaces, new_interfaces);
4681 CFRelease(new_interfaces);
4682 }
4683
4684 // get serial (RS232) interfaces
4685 new_interfaces = __SCNetworkInterfaceCopyAll_RS232();
4686 if (new_interfaces != NULL) {
4687 add_interfaces(all_interfaces, new_interfaces);
4688 CFRelease(new_interfaces);
4689 }
4690
4691 // get virtual network interfaces (Bond, Bridge, VLAN)
4692 if (prefs == NULL) {
4693 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL);
4694 if (prefs != NULL) {
4695 temp_preferences = TRUE;
4696 }
4697 }
4698 if (prefs != NULL) {
4699 #if !TARGET_OS_IPHONE
4700 new_interfaces = SCBondInterfaceCopyAll(prefs);
4701 if (new_interfaces != NULL) {
4702 add_interfaces(all_interfaces, new_interfaces);
4703 CFRelease(new_interfaces);
4704 }
4705 #endif // !TARGET_OS_IPHONE
4706
4707 new_interfaces = SCBridgeInterfaceCopyAll(prefs);
4708 if (new_interfaces != NULL) {
4709 add_interfaces(all_interfaces, new_interfaces);
4710 CFRelease(new_interfaces);
4711 }
4712
4713 new_interfaces = SCVLANInterfaceCopyAll(prefs);
4714 if (new_interfaces != NULL) {
4715 add_interfaces(all_interfaces, new_interfaces);
4716 CFRelease(new_interfaces);
4717 }
4718
4719 #if !TARGET_OS_IPHONE
4720 // add BT-PAN interface
4721 addBTPANInterface(all_interfaces);
4722 #endif // !TARGET_OS_IPHONE
4723
4724 if (temp_preferences) CFRelease(prefs);
4725 }
4726
4727 // all interfaces have been identified, order and return
4728 sort_interfaces(all_interfaces);
4729
4730 return all_interfaces;
4731 }
4732
4733
4734 CFArrayRef /* of SCNetworkInterfaceRef's */
4735 SCNetworkInterfaceCopyAll()
4736 {
4737 CFArrayRef all_interfaces;
4738
4739 all_interfaces = _SCNetworkInterfaceCopyAllWithPreferences(NULL);
4740 return all_interfaces;
4741 }
4742
4743
4744 CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */
4745 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface)
4746 {
4747 CFIndex i;
4748 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4749
4750 if (!isA_SCNetworkInterface(interface)) {
4751 _SCErrorSet(kSCStatusInvalidArgument);
4752 return NULL;
4753 }
4754
4755 if (interfacePrivate->supported_interface_types != NULL) {
4756 goto done;
4757 }
4758
4759 i = findConfiguration(interfacePrivate->interface_type);
4760 if (i != kCFNotFound) {
4761 if (configurations[i].supported_interfaces != doNone) {
4762 interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
4763 if (configurations[i].supported_interfaces & do6to4) {
4764 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceType6to4);
4765 }
4766 if (configurations[i].supported_interfaces & doL2TP) {
4767 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeL2TP);
4768 }
4769 if (configurations[i].supported_interfaces & doPPP) {
4770 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPP);
4771 }
4772 if (configurations[i].supported_interfaces & doIPSec) {
4773 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeIPSec);
4774 }
4775 }
4776 } else {
4777 SCNetworkInterfaceRef child;
4778
4779 child = SCNetworkInterfaceGetInterface(interface);
4780 if ((child != NULL) && CFEqual(child, kSCNetworkInterfaceIPv4)) {
4781 interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
4782 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeVPN);
4783 }
4784 }
4785
4786 done :
4787
4788 return interfacePrivate->supported_interface_types;
4789 }
4790
4791
4792 CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */
4793 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface)
4794 {
4795 CFIndex i;
4796 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4797
4798 if (!isA_SCNetworkInterface(interface)) {
4799 _SCErrorSet(kSCStatusInvalidArgument);
4800 return NULL;
4801 }
4802
4803 if (interfacePrivate->supported_protocol_types != NULL) {
4804 goto done;
4805 }
4806
4807 i = findConfiguration(interfacePrivate->interface_type);
4808 if (i != kCFNotFound) {
4809 if (configurations[i].supported_protocols != doNone) {
4810 interfacePrivate->supported_protocol_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
4811 if (configurations[i].supported_protocols & doDNS) {
4812 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeDNS);
4813 }
4814 if (configurations[i].supported_protocols & doIPv4) {
4815 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv4);
4816 }
4817 if (configurations[i].supported_protocols & doIPv6) {
4818 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv6);
4819 }
4820 if (configurations[i].supported_protocols & doProxies) {
4821 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeProxies);
4822 }
4823 #if !TARGET_OS_IPHONE
4824 if (configurations[i].supported_protocols & doSMB) {
4825 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeSMB);
4826 }
4827 #endif // !TARGET_OS_IPHONE
4828 }
4829 }
4830
4831 done :
4832
4833 return interfacePrivate->supported_protocol_types;
4834 }
4835
4836
4837 SCNetworkInterfaceRef
4838 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child, CFStringRef interfaceType)
4839 {
4840 SCNetworkInterfacePrivateRef childPrivate = (SCNetworkInterfacePrivateRef)child;
4841 CFIndex childIndex;
4842 SCNetworkInterfacePrivateRef parentPrivate;
4843
4844 if (!isA_SCNetworkInterface(child)) {
4845 _SCErrorSet(kSCStatusInvalidArgument);
4846 return NULL;
4847 }
4848
4849 if (!isA_CFString(interfaceType)) {
4850 _SCErrorSet(kSCStatusInvalidArgument);
4851 return NULL;
4852 }
4853
4854 if (CFEqual(child, kSCNetworkInterfaceLoopback)) {
4855 // can't layer on top of loopback
4856 _SCErrorSet(kSCStatusInvalidArgument);
4857 return NULL;
4858 }
4859
4860 childIndex = findConfiguration(childPrivate->interface_type);
4861
4862 parentPrivate = __SCNetworkInterfaceCreatePrivate(NULL,
4863 child,
4864 childPrivate->prefs,
4865 childPrivate->serviceID);
4866 if (parentPrivate == NULL) {
4867 _SCErrorSet(kSCStatusFailed);
4868 return NULL;
4869 }
4870
4871 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
4872 parentPrivate->interface_type = kSCNetworkInterfaceTypePPP;
4873 parentPrivate->entity_type = kSCValNetInterfaceTypePPP;
4874
4875 // entity subtype
4876 if (childIndex != kCFNotFound) {
4877 if (configurations[childIndex].ppp_subtype != NULL) {
4878 parentPrivate->entity_subtype = *configurations[childIndex].ppp_subtype;
4879 } else {
4880 // sorry, the child interface does not support PPP
4881 goto fail;
4882 }
4883 } else {
4884 // if the child's interface type not known, use the child entities "Type"
4885 parentPrivate->entity_subtype = childPrivate->entity_type;
4886 }
4887
4888 if (childPrivate->entity_device != NULL) {
4889 parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device);
4890 }
4891
4892 if (childPrivate->entity_device_unique != NULL) {
4893 parentPrivate->entity_device_unique = CFStringCreateCopy(NULL, childPrivate->entity_device_unique);
4894 }
4895 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
4896 if ((childIndex == kCFNotFound) ||
4897 ((configurations[childIndex].supported_interfaces & doL2TP) != doL2TP)) {
4898 // if the child interface does not support L2TP
4899 goto fail;
4900 }
4901 parentPrivate->interface_type = kSCNetworkInterfaceTypeL2TP;
4902 parentPrivate->localized_key = CFSTR("l2tp");
4903 parentPrivate->entity_type = kSCEntNetL2TP; // interface config goes into "L2TP"
4904 #pragma GCC diagnostic push
4905 #pragma GCC diagnostic ignored "-Wdeprecated"
4906 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) {
4907 if ((childIndex == kCFNotFound) ||
4908 ((configurations[childIndex].supported_interfaces & doPPTP) != doPPTP)) {
4909 // if the child interface does not support PPTP
4910 goto fail;
4911 }
4912 parentPrivate->interface_type = kSCNetworkInterfaceTypePPTP;
4913 parentPrivate->localized_key = CFSTR("pptp");
4914 parentPrivate->entity_type = kSCEntNetPPTP; // interface config goes into "PPTP"
4915 #pragma GCC diagnostic pop
4916 } else if (CFEqual(interfaceType, kSCNetworkInterfaceType6to4)) {
4917 if ((childIndex == kCFNotFound) ||
4918 ((configurations[childIndex].supported_interfaces & do6to4) != do6to4)) {
4919 // if the child interface does not support 6to4
4920 goto fail;
4921 }
4922
4923 parentPrivate->interface_type = kSCNetworkInterfaceType6to4;
4924 parentPrivate->localized_key = CFSTR("6to4");
4925 parentPrivate->entity_type = kSCValNetInterfaceType6to4;
4926 parentPrivate->entity_device = CFRetain(CFSTR("stf0"));
4927 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) {
4928 if ((childIndex == kCFNotFound) ||
4929 ((configurations[childIndex].supported_interfaces & doIPSec) != doIPSec)) {
4930 // if the child interface does not support IPSec
4931 goto fail;
4932 }
4933 parentPrivate->interface_type = kSCNetworkInterfaceTypeIPSec;
4934 parentPrivate->localized_key = CFSTR("ipsec");
4935 parentPrivate->entity_type = kSCValNetInterfaceTypeIPSec;
4936 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) {
4937 if (childIndex != kCFNotFound) {
4938 // if not a "vendor" child interface
4939 goto fail;
4940 }
4941
4942 parentPrivate->interface_type = kSCNetworkInterfaceTypeVPN;
4943 parentPrivate->localized_key = CFSTR("vpn");
4944 parentPrivate->localized_arg1 = CFRetain(childPrivate->entity_type);
4945 parentPrivate->entity_type = kSCValNetInterfaceTypeVPN;
4946 parentPrivate->entity_subtype = childPrivate->entity_type;
4947 if (childPrivate->entity_device != NULL) {
4948 parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device);
4949 }
4950 if (parentPrivate->entity_subtype != NULL) {
4951 CFArrayRef components;
4952 CFIndex n;
4953 CFStringRef vpnType;
4954
4955 //
4956 // the "default" interface name is derived from the VPN type
4957 //
4958 // e.g.
4959 // com.apple.Apple-VPN.vpnplugin --> "Apple VPN"
4960 // ^^^^^^^^^
4961 //
4962 vpnType = parentPrivate->entity_subtype;
4963 components = CFStringCreateArrayBySeparatingStrings(NULL, vpnType, CFSTR("."));
4964 n = CFArrayGetCount(components);
4965 if ((n >= 4) &&
4966 CFEqual(CFArrayGetValueAtIndex(components, n - 1), CFSTR("vpnplugin"))) {
4967 CFMutableStringRef str;
4968
4969 str = CFStringCreateMutableCopy(NULL,
4970 0,
4971 CFArrayGetValueAtIndex(components, n - 2));
4972 (void) CFStringFindAndReplace(str,
4973 CFSTR("-"),
4974 CFSTR(" "),
4975 CFRangeMake(0, CFStringGetLength(str)),
4976 0);
4977 parentPrivate->localized_name = str;
4978 }
4979 CFRelease(components);
4980 }
4981 } else if (CFStringFind(interfaceType, CFSTR("."), 0).location != kCFNotFound) {
4982 // if custom interface type
4983 pthread_mutex_lock(&lock);
4984 if (vendor_interface_types == NULL) {
4985 vendor_interface_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
4986 }
4987 CFSetAddValue(vendor_interface_types, interfaceType);
4988 parentPrivate->interface_type = CFSetGetValue(vendor_interface_types, interfaceType);
4989 pthread_mutex_unlock(&lock);
4990
4991 parentPrivate->entity_type = parentPrivate->interface_type; // interface config goes into a
4992 // a dictionary with the same
4993 // name as the interfaceType
4994 } else {
4995 // unknown interface type
4996 goto fail;
4997 }
4998
4999 parentPrivate->hidden = childPrivate->hidden;
5000
5001 if (childPrivate->overrides != NULL) {
5002 parentPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, childPrivate->overrides);
5003 }
5004
5005 // The following change handles the case where a user has both an Ethernet and
5006 // PPPoE network service. Because a PPPoE service is typically associated with
5007 // an ISP we want it to be sorted higher in the service order.
5008 if ((parentPrivate->entity_subtype != NULL) &&
5009 (CFEqual(parentPrivate->entity_subtype, kSCValNetInterfaceSubTypePPPoE))) {
5010 if ((childPrivate->interface_type != NULL) &&
5011 (CFEqual(childPrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211))) {
5012 parentPrivate->sort_order = kSortAirportPPP;
5013 } else {
5014 parentPrivate->sort_order = kSortEthernetPPP;
5015 }
5016 } else {
5017 // set sort order of the parent to match the child interface
5018 parentPrivate->sort_order = childPrivate->sort_order;
5019 }
5020
5021 return (SCNetworkInterfaceRef)parentPrivate;
5022
5023 fail :
5024
5025 CFRelease(parentPrivate);
5026 _SCErrorSet(kSCStatusInvalidArgument);
5027 return NULL;
5028 }
5029
5030
5031 __private_extern__
5032 CFDictionaryRef
5033 __SCNetworkInterfaceGetDefaultConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface)
5034 {
5035 CFDictionaryRef config = NULL;
5036 CFStringRef defaultType;
5037 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5038
5039 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
5040 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
5041
5042 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
5043 if (defaultType != NULL) {
5044 if (set != NULL) {
5045 CFStringRef path;
5046
5047 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
5048 SCNetworkSetGetSetID(set), // set
5049 interfacePrivate->entity_device, // interface
5050 defaultType); // entity
5051 if (path != NULL) {
5052 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
5053 CFRelease(path);
5054
5055 if (config == NULL) {
5056 // if the "set" does not have a saved configuration, use
5057 // the [template] "interface" configuration
5058 if (interfacePrivate->unsaved != NULL) {
5059 config = CFDictionaryGetValue(interfacePrivate->unsaved, defaultType);
5060 if (config == (CFDictionaryRef)kCFNull) {
5061 config = NULL;
5062 }
5063 }
5064 }
5065 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
5066 config = NULL;
5067 }
5068 }
5069 }
5070 }
5071
5072 return config;
5073 }
5074
5075
5076 static CFDictionaryRef
5077 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface,
5078 CFStringRef extendedType)
5079 {
5080 CFDictionaryRef config = NULL;
5081 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5082 CFArrayRef paths;
5083
5084 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
5085 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
5086
5087 paths = copyConfigurationPaths(interfacePrivate, extendedType);
5088 if (paths != NULL) {
5089 CFStringRef path;
5090
5091 path = CFArrayGetValueAtIndex(paths, 0);
5092 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
5093
5094 CFRelease(paths);
5095 } else {
5096 if (interfacePrivate->unsaved != NULL) {
5097 config = CFDictionaryGetValue(interfacePrivate->unsaved, extendedType);
5098 if (config == (CFDictionaryRef)kCFNull) {
5099 config = NULL;
5100 }
5101 }
5102 }
5103
5104 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
5105 config = NULL;
5106 }
5107
5108 return config;
5109 }
5110
5111
5112 CFDictionaryRef
5113 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface)
5114 {
5115 CFDictionaryRef config;
5116 CFStringRef defaultType;
5117
5118 if (!isA_SCNetworkInterface(interface)) {
5119 _SCErrorSet(kSCStatusInvalidArgument);
5120 return NULL;
5121 }
5122
5123 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
5124 if (defaultType == NULL) {
5125 return NULL;
5126 }
5127
5128 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType);
5129 if (config == NULL) {
5130 if (CFEqual(defaultType, kSCEntNetAirPort)) {
5131 SCNetworkInterfacePrivateRef interfacePrivate;
5132 CFStringRef path;
5133
5134 // if AirPort interface, check for a per-service config
5135 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5136 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
5137 interfacePrivate->serviceID, // service
5138 kSCEntNetAirPort); // entity
5139 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
5140 CFRelease(path);
5141 }
5142 }
5143 if (config == NULL) {
5144 _SCErrorSet(kSCStatusOK);
5145 }
5146
5147 return config;
5148 }
5149
5150
5151 CFDictionaryRef
5152 SCNetworkInterfaceGetExtendedConfiguration(SCNetworkInterfaceRef interface,
5153 CFStringRef extendedType)
5154 {
5155 CFDictionaryRef config;
5156
5157 if (!isA_SCNetworkInterface(interface)) {
5158 _SCErrorSet(kSCStatusInvalidArgument);
5159 return NULL;
5160 }
5161
5162 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) {
5163 _SCErrorSet(kSCStatusInvalidArgument);
5164 return NULL;
5165 }
5166
5167 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType);
5168 if (config == NULL) {
5169 _SCErrorSet(kSCStatusOK);
5170 }
5171
5172 return config;
5173 }
5174
5175
5176 __private_extern__
5177 CFStringRef
5178 __SCNetworkInterfaceGetEntityType(SCNetworkInterfaceRef interface)
5179 {
5180 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5181
5182 return interfacePrivate->entity_type;
5183 }
5184
5185
5186 __private_extern__
5187 CFStringRef
5188 __SCNetworkInterfaceGetEntitySubType(SCNetworkInterfaceRef interface)
5189 {
5190 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef) interface;
5191
5192 return interfacePrivate->entity_subtype;
5193 }
5194
5195
5196 CFStringRef
5197 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface)
5198 {
5199 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5200
5201 if (!isA_SCNetworkInterface(interface)) {
5202 _SCErrorSet(kSCStatusInvalidArgument);
5203 return NULL;
5204 }
5205
5206 if ((interfacePrivate->interface != NULL) &&
5207 (interfacePrivate->interface != kSCNetworkInterfaceIPv4)) {
5208 _SCErrorSet(kSCStatusOK);
5209 return NULL;
5210 }
5211
5212 return interfacePrivate->entity_device;
5213 }
5214
5215
5216 CFStringRef
5217 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface)
5218 {
5219 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5220
5221 if (!isA_SCNetworkInterface(interface)) {
5222 _SCErrorSet(kSCStatusInvalidArgument);
5223 return NULL;
5224 }
5225
5226 if ((interfacePrivate->address != NULL) &&
5227 (interfacePrivate->addressString == NULL)) {
5228 uint8_t *bp;
5229 char *cp;
5230 size_t n;
5231 char mac[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
5232 char *mac_p = mac;
5233
5234 bp = (uint8_t *)CFDataGetBytePtr(interfacePrivate->address);
5235 n = CFDataGetLength(interfacePrivate->address) * 3;
5236
5237 if (n > sizeof(mac)) {
5238 mac_p = CFAllocatorAllocate(NULL, n, 0);
5239 }
5240
5241 for (cp = mac_p; n > 0; n -= 3) {
5242 cp += snprintf(cp, n, "%2.2x:", *bp++);
5243 }
5244
5245 interfacePrivate->addressString = CFStringCreateWithCString(NULL, mac_p, kCFStringEncodingUTF8);
5246 if (mac_p != mac) CFAllocatorDeallocate(NULL, mac_p);
5247 }
5248
5249 return interfacePrivate->addressString;
5250 }
5251
5252
5253 SCNetworkInterfaceRef
5254 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface)
5255 {
5256 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5257
5258 if (!isA_SCNetworkInterface(interface)) {
5259 _SCErrorSet(kSCStatusInvalidArgument);
5260 return NULL;
5261 }
5262
5263 return interfacePrivate->interface;
5264 }
5265
5266
5267 CFStringRef
5268 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface)
5269 {
5270 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5271
5272 if (!isA_SCNetworkInterface(interface)) {
5273 _SCErrorSet(kSCStatusInvalidArgument);
5274 return NULL;
5275 }
5276
5277 return interfacePrivate->interface_type;
5278 }
5279
5280
5281 static CFStringRef
5282 copy_string_from_bundle(CFBundleRef bundle, CFStringRef key, Boolean localized)
5283 {
5284 CFStringRef str = NULL;
5285
5286 if (localized) {
5287 str = CFBundleCopyLocalizedString(bundle,
5288 key,
5289 key,
5290 NETWORKINTERFACE_LOCALIZATIONS);
5291 } else {
5292 str = _SC_CFBundleCopyNonLocalizedString(bundle,
5293 key,
5294 key,
5295 NETWORKINTERFACE_LOCALIZATIONS);
5296 }
5297
5298 return str;
5299 }
5300
5301
5302 static CFStringRef
5303 copy_interface_string(CFBundleRef bundle, CFStringRef key, Boolean localized)
5304 {
5305 static Boolean reported = FALSE;
5306 CFStringRef str = NULL;
5307
5308 str = copy_string_from_bundle(bundle, key, localized);
5309
5310 if (str == NULL) {
5311 SC_log(LOG_ERR, "Received NULL string for the interface key: {Bundle: %@, key: %@, localized: %d}", bundle,
5312 key,
5313 localized);
5314 goto done;
5315 }
5316
5317 if (CFEqual(str, key) && !reported) {
5318 const CFStringRef knownStrKey = CFSTR("airport");
5319 CFStringRef knownStrValue = NULL;
5320
5321 knownStrValue = copy_string_from_bundle(bundle, knownStrKey, localized);
5322 if (knownStrValue == NULL || CFEqual(knownStrValue, knownStrKey)) {
5323 /* We are here because we requested for a localized/non-localized string
5324 based on the localization key, but we were given the same key/NULL back,
5325 implying a bad...bad thing!
5326 */
5327 SC_log(LOG_ERR, "Failed to retrieve the interface string: {Bundle: %@, key: %@, localized: %d}", bundle,
5328 knownStrKey,
5329 localized);
5330
5331 #if TARGET_OS_IPHONE
5332 /* ...and we want to know about it! */
5333 _SC_crash("Failed to retrieve interface string", NULL, NULL);
5334 #endif //TARGET_OS_IPHONE
5335 reported = TRUE;
5336 }
5337
5338 if (knownStrValue != NULL) {
5339 CFRelease(knownStrValue);
5340 }
5341 }
5342
5343 done:
5344 return str;
5345 }
5346
5347
5348 static CFStringRef
5349 copy_display_name(SCNetworkInterfaceRef interface, Boolean localized, Boolean oldLocalization)
5350 {
5351 CFMutableStringRef local;
5352 CFStringRef name;
5353
5354 local = CFStringCreateMutable(NULL, 0);
5355
5356 while (interface != NULL) {
5357 Boolean added = FALSE;
5358 SCNetworkInterfaceRef child = NULL;
5359 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5360
5361 if ((interfacePrivate->interface != NULL) &&
5362 (interfacePrivate->interface != kSCNetworkInterfaceIPv4) &&
5363 !CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeVPN)) {
5364 child = interfacePrivate->interface;
5365 }
5366
5367 if ((bundle != NULL) && (interfacePrivate->localized_key != NULL)) {
5368 CFStringRef fmt;
5369 CFStringRef key = interfacePrivate->localized_key;
5370
5371 if (oldLocalization) {
5372 key = CFStringCreateWithFormat(NULL, NULL, CFSTR("X-%@"),
5373 interfacePrivate->localized_key);
5374 }
5375 fmt = copy_interface_string(bundle, key, localized);
5376 if (fmt != NULL) {
5377 CFStringAppendFormat(local,
5378 NULL,
5379 fmt,
5380 interfacePrivate->localized_arg1,
5381 interfacePrivate->localized_arg2);
5382 CFRelease(fmt);
5383 added = TRUE;
5384 }
5385 if (oldLocalization) {
5386 CFRelease(key);
5387 }
5388 }
5389
5390 if (!added &&
5391 (interfacePrivate->prefs != NULL) &&
5392 (interfacePrivate->serviceID != NULL) &&
5393 (child == NULL)) {
5394 CFDictionaryRef entity;
5395 CFStringRef path;
5396
5397 // check for (and use) the name of the interface when it
5398 // was last available
5399 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,
5400 interfacePrivate->serviceID,
5401 kSCEntNetInterface);
5402 entity = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
5403 CFRelease(path);
5404 if (isA_CFDictionary(entity)) {
5405 CFStringRef name;
5406
5407 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
5408 if (isA_CFString(name)) {
5409 CFStringAppend(local, name);
5410 added = TRUE;
5411 }
5412 }
5413 }
5414
5415 if (!added) {
5416 // create (non-)localized name based on the interface type
5417 CFStringAppend(local, interfacePrivate->interface_type);
5418
5419 // ... and, if this is a leaf node, the interface device
5420 if ((interfacePrivate->entity_device != NULL) && (child == NULL)) {
5421 CFStringAppendFormat(local, NULL, CFSTR(" (%@)"), interfacePrivate->entity_device);
5422 }
5423 }
5424
5425 if (child != NULL) {
5426 // if this interface is layered over another
5427 CFStringAppend(local, CFSTR(" --> "));
5428 }
5429
5430 interface = child;
5431 }
5432
5433 name = CFStringCreateCopy(NULL, local);
5434 CFRelease(local);
5435
5436 return name;
5437 }
5438
5439
5440 #if !TARGET_OS_IPHONE
5441 __private_extern__
5442 CFStringRef
5443 __SCNetworkInterfaceCopyXLocalizedDisplayName(SCNetworkInterfaceRef interface)
5444 {
5445 CFStringRef name;
5446
5447 if (!isA_SCNetworkInterface(interface)) {
5448 _SCErrorSet(kSCStatusInvalidArgument);
5449 return NULL;
5450 }
5451
5452 name = copy_display_name(interface, TRUE, TRUE);
5453 return name;
5454 }
5455
5456
5457 __private_extern__
5458 CFStringRef
5459 __SCNetworkInterfaceCopyXNonLocalizedDisplayName(SCNetworkInterfaceRef interface)
5460 {
5461 CFStringRef localized_name;
5462
5463 if (!isA_SCNetworkInterface(interface)) {
5464 _SCErrorSet(kSCStatusInvalidArgument);
5465 return NULL;
5466 }
5467
5468 localized_name = copy_display_name(interface, FALSE, TRUE);
5469 return localized_name;
5470 }
5471 #endif // !TARGET_OS_IPHONE
5472
5473 __private_extern__
5474 void
5475 __SCNetworkInterfaceSetUserDefinedName(SCNetworkInterfaceRef interface, CFStringRef name)
5476 {
5477 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5478
5479 if (!isA_SCNetworkInterface(interface)) {
5480 return;
5481 }
5482 if (name != NULL) {
5483 CFRetain(name);
5484 }
5485 if (interfacePrivate->name != NULL) {
5486 CFRelease(interfacePrivate->name);
5487 }
5488 interfacePrivate->name = name;
5489
5490 if (name != NULL) {
5491 CFRetain(name);
5492 }
5493 if (interfacePrivate->localized_name != NULL) {
5494 CFRelease(interfacePrivate->localized_name);
5495 }
5496 interfacePrivate->localized_name = name;
5497 }
5498
5499 __private_extern__
5500 CFStringRef
5501 __SCNetworkInterfaceGetUserDefinedName(SCNetworkInterfaceRef interface)
5502 {
5503 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5504
5505 if (!isA_SCNetworkInterface(interface)) {
5506 return NULL;
5507 }
5508
5509 return interfacePrivate->name;
5510 }
5511
5512
5513 __private_extern__
5514 CFStringRef
5515 __SCNetworkInterfaceGetNonLocalizedDisplayName(SCNetworkInterfaceRef interface)
5516 {
5517 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5518
5519 if (!isA_SCNetworkInterface(interface)) {
5520 _SCErrorSet(kSCStatusInvalidArgument);
5521 return NULL;
5522 }
5523
5524 if (interfacePrivate->name == NULL) {
5525 interfacePrivate->name = copy_display_name(interface, FALSE, FALSE);
5526 }
5527
5528 return interfacePrivate->name;
5529 }
5530
5531
5532 CFStringRef
5533 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface)
5534 {
5535 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5536
5537 if (!isA_SCNetworkInterface(interface)) {
5538 _SCErrorSet(kSCStatusInvalidArgument);
5539 return NULL;
5540 }
5541
5542 if (interfacePrivate->localized_name == NULL) {
5543 interfacePrivate->localized_name = copy_display_name(interface, TRUE, FALSE);
5544 }
5545
5546 return interfacePrivate->localized_name;
5547 }
5548
5549
5550 __private_extern__
5551 CFDictionaryRef
5552 __SCNetworkInterfaceGetTemplateOverrides(SCNetworkInterfaceRef interface, CFStringRef overrideType)
5553 {
5554 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5555 CFDictionaryRef overrides = NULL;
5556
5557 if (interfacePrivate->overrides != NULL) {
5558 overrides = CFDictionaryGetValue(interfacePrivate->overrides, overrideType);
5559 }
5560
5561 return overrides;
5562 }
5563
5564
5565 CFTypeID
5566 SCNetworkInterfaceGetTypeID(void)
5567 {
5568 pthread_once(&initialized, __SCNetworkInterfaceInitialize); /* initialize runtime */
5569 return __kSCNetworkInterfaceTypeID;
5570 }
5571
5572
5573 __private_extern__
5574 Boolean
5575 __SCNetworkInterfaceSetDefaultConfiguration(SCNetworkSetRef set,
5576 SCNetworkInterfaceRef interface,
5577 CFStringRef defaultType,
5578 CFDictionaryRef config,
5579 Boolean okToHold)
5580 {
5581 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5582 Boolean ok = FALSE;
5583
5584 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
5585 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
5586
5587 if (defaultType == NULL) {
5588 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
5589 if (defaultType == NULL) {
5590 return FALSE;
5591 }
5592 }
5593
5594 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
5595 config = NULL;
5596 }
5597
5598 if (set != NULL) {
5599 CFStringRef path;
5600
5601 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
5602 SCNetworkSetGetSetID(set), // set
5603 interfacePrivate->entity_device, // interface
5604 defaultType); // entity
5605 if (path != NULL) {
5606 ok = __setPrefsConfiguration(interfacePrivate->prefs, path, config, FALSE);
5607 CFRelease(path);
5608 if (ok) {
5609 // if configuration has been saved
5610 if (interfacePrivate->unsaved != NULL) {
5611 CFDictionaryRemoveValue(interfacePrivate->unsaved, defaultType);
5612 if (CFDictionaryGetCount(interfacePrivate->unsaved) == 0) {
5613 CFRelease(interfacePrivate->unsaved);
5614 interfacePrivate->unsaved = NULL;
5615 }
5616 }
5617 }
5618 } else {
5619 if (okToHold) {
5620 if (config == NULL) {
5621 // remember that we are clearing the configuration
5622 config = (CFDictionaryRef)kCFNull;
5623 }
5624
5625 if (interfacePrivate->unsaved == NULL) {
5626 interfacePrivate->unsaved = CFDictionaryCreateMutable(NULL,
5627 0,
5628 &kCFTypeDictionaryKeyCallBacks,
5629 &kCFTypeDictionaryValueCallBacks);
5630 }
5631 CFDictionarySetValue(interfacePrivate->unsaved, defaultType, config);
5632 ok = TRUE;
5633 } else {
5634 _SCErrorSet(kSCStatusNoKey);
5635 }
5636 }
5637 }
5638
5639 return ok;
5640 }
5641
5642
5643 __private_extern__
5644 Boolean
5645 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface,
5646 CFStringRef extendedType,
5647 CFDictionaryRef config,
5648 Boolean okToHold)
5649 {
5650 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5651 Boolean ok = FALSE;
5652 CFArrayRef paths;
5653
5654 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
5655 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
5656
5657 if (extendedType == NULL) {
5658 extendedType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
5659 if (extendedType == NULL) {
5660 return FALSE;
5661 }
5662 }
5663
5664 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
5665 config = NULL;
5666 }
5667
5668 paths = copyConfigurationPaths(interfacePrivate, extendedType);
5669 if (paths != NULL) {
5670 CFIndex i;
5671 CFIndex n;
5672
5673 n = CFArrayGetCount(paths);
5674 for (i = 0; i < n; i++) {
5675 CFStringRef path;
5676
5677 path = CFArrayGetValueAtIndex(paths, i);
5678 ok = __setPrefsConfiguration(interfacePrivate->prefs, path, config, FALSE);
5679 if (!ok) {
5680 break;
5681 }
5682 }
5683
5684 if (ok) {
5685 // if configuration has been saved
5686 if (interfacePrivate->unsaved != NULL) {
5687 CFDictionaryRemoveValue(interfacePrivate->unsaved, extendedType);
5688 if (CFDictionaryGetCount(interfacePrivate->unsaved) == 0) {
5689 CFRelease(interfacePrivate->unsaved);
5690 interfacePrivate->unsaved = NULL;
5691 }
5692 }
5693 }
5694
5695 CFRelease(paths);
5696 } else {
5697 if (okToHold) {
5698 if (config == NULL) {
5699 // remember that we are clearing the configuration
5700 config = (CFDictionaryRef)kCFNull;
5701 }
5702
5703 if (interfacePrivate->unsaved == NULL) {
5704 interfacePrivate->unsaved = CFDictionaryCreateMutable(NULL,
5705 0,
5706 &kCFTypeDictionaryKeyCallBacks,
5707 &kCFTypeDictionaryValueCallBacks);
5708 }
5709 CFDictionarySetValue(interfacePrivate->unsaved, extendedType, config);
5710 ok = TRUE;
5711 } else {
5712 _SCErrorSet(kSCStatusNoKey);
5713 }
5714 }
5715
5716 return ok;
5717 }
5718
5719
5720 Boolean
5721 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config)
5722 {
5723 CFStringRef defaultType;
5724 Boolean ok;
5725
5726 if (!isA_SCNetworkInterface(interface)) {
5727 _SCErrorSet(kSCStatusInvalidArgument);
5728 return FALSE;
5729 }
5730
5731 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
5732 if (defaultType == NULL) {
5733 return FALSE;
5734 }
5735
5736 ok = __SCNetworkInterfaceSetConfiguration(interface, defaultType, config, FALSE);
5737 if (ok) {
5738 SC_log(LOG_DEBUG, "SCNetworkInterfaceSetConfiguration(): %@ -> %@",
5739 interface,
5740 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL"));
5741 }
5742
5743 return ok;
5744 }
5745
5746
5747 Boolean
5748 SCNetworkInterfaceSetExtendedConfiguration(SCNetworkInterfaceRef interface,
5749 CFStringRef extendedType,
5750 CFDictionaryRef config)
5751 {
5752 Boolean ok;
5753
5754 if (!isA_SCNetworkInterface(interface)) {
5755 _SCErrorSet(kSCStatusInvalidArgument);
5756 return FALSE;
5757 }
5758
5759 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) {
5760 return FALSE;
5761 }
5762
5763 ok = __SCNetworkInterfaceSetConfiguration(interface, extendedType, config, FALSE);
5764 if (ok) {
5765 SC_log(LOG_DEBUG, "SCNetworkInterfaceSetExtendedConfiguration(): %@ -> %@",
5766 interface,
5767 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL"));
5768 }
5769
5770 return ok;
5771 }
5772
5773
5774 #pragma mark -
5775 #pragma mark SCNetworkInterface [Refresh Configuration] API
5776
5777
5778 #ifndef kSCEntNetRefreshConfiguration
5779 #define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration")
5780 #endif // kSCEntNetRefreshConfiguration
5781
5782 Boolean
5783 _SCNetworkInterfaceForceConfigurationRefresh(CFStringRef ifName)
5784 {
5785 CFStringRef key;
5786 Boolean ok = FALSE;
5787
5788 if (!isA_CFString(ifName)) {
5789 _SCErrorSet(kSCStatusInvalidArgument);
5790 return FALSE;
5791 }
5792
5793 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
5794 kSCDynamicStoreDomainState,
5795 ifName,
5796 kSCEntNetRefreshConfiguration);
5797 ok = SCDynamicStoreNotifyValue(NULL, key);
5798 CFRelease(key);
5799 return ok;
5800 }
5801
5802
5803 static Boolean
5804 __SCNetworkInterfaceForceConfigurationRefresh_helper(SCPreferencesRef prefs, CFStringRef ifName)
5805 {
5806 CFDataRef data = NULL;
5807 Boolean ok;
5808 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
5809 uint32_t status = kSCStatusOK;
5810 CFDataRef reply = NULL;
5811
5812 if (prefsPrivate->helper_port == MACH_PORT_NULL) {
5813 ok = __SCPreferencesCreate_helper(prefs);
5814 if (!ok) {
5815 return FALSE;
5816 }
5817 }
5818
5819 // serialize the interface name
5820 ok = _SCSerializeString(ifName, &data, NULL, NULL);
5821 if (!ok) {
5822 goto fail;
5823 }
5824
5825 // have the helper "refresh" the configuration
5826 status = kSCStatusOK;
5827 reply = NULL;
5828 ok = _SCHelperExec(prefsPrivate->helper_port,
5829 SCHELPER_MSG_INTERFACE_REFRESH,
5830 data,
5831 &status,
5832 NULL);
5833 if (data != NULL) CFRelease(data);
5834 if (!ok) {
5835 goto fail;
5836 }
5837
5838 if (status != kSCStatusOK) {
5839 goto error;
5840 }
5841
5842 return TRUE;
5843
5844 fail :
5845
5846 // close helper
5847 if (prefsPrivate->helper_port != MACH_PORT_NULL) {
5848 _SCHelperClose(&prefsPrivate->helper_port);
5849 }
5850
5851 status = kSCStatusAccessError;
5852
5853 error :
5854
5855 // return error
5856 _SCErrorSet(status);
5857 return FALSE;
5858 }
5859
5860
5861 Boolean
5862 SCNetworkInterfaceForceConfigurationRefresh(SCNetworkInterfaceRef interface)
5863 {
5864 CFStringRef ifName;
5865 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5866
5867 if (!isA_SCNetworkInterface(interface)) {
5868 _SCErrorSet(kSCStatusInvalidArgument);
5869 return FALSE;
5870 }
5871
5872 ifName = SCNetworkInterfaceGetBSDName(interface);
5873 if (ifName == NULL) {
5874 _SCErrorSet(kSCStatusInvalidArgument);
5875 return FALSE;
5876 }
5877
5878 if (interfacePrivate->prefs != NULL) {
5879 SCPreferencesRef prefs = interfacePrivate->prefs;
5880 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
5881
5882 if (prefsPrivate->authorizationData != NULL) {
5883 return __SCNetworkInterfaceForceConfigurationRefresh_helper(prefs, ifName);
5884 }
5885 }
5886
5887 return _SCNetworkInterfaceForceConfigurationRefresh(ifName);
5888 }
5889
5890
5891 Boolean
5892 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName)
5893 {
5894 return _SCNetworkInterfaceForceConfigurationRefresh(ifName);
5895 }
5896
5897
5898 #pragma mark -
5899 #pragma mark SCNetworkInterface Password APIs
5900
5901
5902 static CFStringRef
5903 getPasswordID(CFDictionaryRef config, CFStringRef serviceID)
5904 {
5905 CFStringRef unique_id = NULL;
5906
5907 if (config != NULL) {
5908 CFStringRef encryption;
5909
5910 encryption = CFDictionaryGetValue(config, kSCPropNetPPPAuthPasswordEncryption);
5911 if (isA_CFString(encryption) &&
5912 CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
5913 unique_id = CFDictionaryGetValue(config, kSCPropNetPPPAuthPassword);
5914 }
5915 }
5916 if (unique_id == NULL) {
5917 unique_id = serviceID;
5918 }
5919
5920 return unique_id;
5921 }
5922
5923
5924 static CFStringRef
5925 copySharedSecretID(CFDictionaryRef config, CFStringRef serviceID)
5926 {
5927 CFMutableStringRef shared_id = NULL;
5928
5929 if (config != NULL) {
5930 CFStringRef encryption;
5931
5932 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecretEncryption);
5933 if (isA_CFString(encryption) &&
5934 CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
5935 shared_id = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecret);
5936 if (shared_id != NULL) {
5937 CFRetain(shared_id);
5938 }
5939 }
5940 }
5941
5942 if (shared_id == NULL) {
5943 CFStringRef unique_id;
5944
5945 unique_id = getPasswordID(config, serviceID);
5946 shared_id = CFStringCreateMutableCopy(NULL, 0, unique_id);
5947 CFStringAppend(shared_id, CFSTR(".SS"));
5948 }
5949
5950 return shared_id;
5951 }
5952
5953
5954 static CFStringRef
5955 copyXAuthID(CFDictionaryRef config, CFStringRef serviceID)
5956 {
5957 CFMutableStringRef xauth_id = NULL;
5958
5959 if (config != NULL) {
5960 CFStringRef encryption;
5961
5962 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPasswordEncryption);
5963 if (isA_CFString(encryption) &&
5964 CFEqual(encryption, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) {
5965 xauth_id = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPassword);
5966 if (xauth_id != NULL) {
5967 CFRetain(xauth_id);
5968 }
5969 }
5970 }
5971
5972 if (xauth_id == NULL) {
5973 CFStringRef unique_id;
5974
5975 unique_id = getPasswordID(config, serviceID);
5976 xauth_id = CFStringCreateMutableCopy(NULL, 0, unique_id);
5977 CFStringAppend(xauth_id, CFSTR(".XAUTH"));
5978 }
5979
5980 return xauth_id;
5981 }
5982
5983
5984 static Boolean
5985 checkInterfacePassword(SCNetworkInterfaceRef interface,
5986 SCNetworkInterfacePasswordType passwordType,
5987 SCPreferencesRef *prefs,
5988 CFStringRef *serviceID)
5989 {
5990 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
5991
5992 if (!isA_SCNetworkInterface(interface)) {
5993 goto error;
5994 }
5995
5996 *serviceID = interfacePrivate->serviceID;
5997 if (*serviceID == NULL) {
5998 goto error;
5999 }
6000
6001 *prefs = interfacePrivate->prefs;
6002 if (*prefs == NULL) {
6003 goto error;
6004 }
6005
6006 switch (passwordType) {
6007 case kSCNetworkInterfacePasswordTypePPP : {
6008 CFStringRef interfaceType;
6009
6010 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
6011 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
6012 // if PPP
6013 break;
6014 }
6015
6016 goto error;
6017 }
6018
6019 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
6020 CFStringRef interfaceType;
6021
6022 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
6023 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
6024 interface = SCNetworkInterfaceGetInterface(interface);
6025 if (interface != NULL) {
6026 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
6027 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
6028 // if PPP->L2TP interface
6029 break;
6030 }
6031 }
6032 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) {
6033 // if IPSec interface
6034 break;
6035 }
6036
6037 goto error;
6038 }
6039
6040 case kSCNetworkInterfacePasswordTypeEAPOL : {
6041 break;
6042 }
6043
6044 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
6045 CFStringRef interfaceType;
6046
6047 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
6048 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) {
6049 // if IPSec interface
6050 break;
6051 }
6052
6053 goto error;
6054 }
6055
6056 case kSCNetworkInterfacePasswordTypeVPN : {
6057 CFStringRef interfaceType;
6058
6059 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
6060 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) {
6061 // if VPN interface
6062 break;
6063 }
6064
6065 goto error;
6066 }
6067
6068 default :
6069 break;
6070 }
6071
6072 return TRUE;
6073
6074 error :
6075
6076 _SCErrorSet(kSCStatusInvalidArgument);
6077 return FALSE;
6078 }
6079
6080
6081 Boolean
6082 SCNetworkInterfaceCheckPassword(SCNetworkInterfaceRef interface,
6083 SCNetworkInterfacePasswordType passwordType)
6084 {
6085 Boolean exists = FALSE;
6086 SCPreferencesRef prefs = NULL;
6087 CFStringRef serviceID = NULL;
6088
6089 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
6090 return FALSE;
6091 }
6092
6093 switch (passwordType) {
6094 case kSCNetworkInterfacePasswordTypePPP : {
6095 CFDictionaryRef config;
6096 CFStringRef unique_id;
6097
6098 // get configuration
6099 config = SCNetworkInterfaceGetConfiguration(interface);
6100
6101 // get serviceID
6102 unique_id = getPasswordID(config, serviceID);
6103
6104 // check
6105 exists = __extract_password(prefs,
6106 config,
6107 kSCPropNetPPPAuthPassword,
6108 kSCPropNetPPPAuthPasswordEncryption,
6109 kSCValNetPPPAuthPasswordEncryptionKeychain,
6110 unique_id,
6111 NULL);
6112 break;
6113 }
6114
6115 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
6116 CFDictionaryRef config;
6117 Boolean extended;
6118 CFStringRef shared_id;
6119
6120 // get configuration
6121 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP);
6122 if (extended) {
6123 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
6124 } else {
6125 config = SCNetworkInterfaceGetConfiguration(interface);
6126 }
6127
6128 // get sharedSecret ID
6129 shared_id = copySharedSecretID(config, serviceID);
6130
6131 // check
6132 exists = __extract_password(prefs,
6133 config,
6134 kSCPropNetIPSecSharedSecret,
6135 kSCPropNetIPSecSharedSecretEncryption,
6136 kSCValNetIPSecSharedSecretEncryptionKeychain,
6137 shared_id,
6138 NULL);
6139 CFRelease(shared_id);
6140 break;
6141 }
6142
6143 case kSCNetworkInterfacePasswordTypeEAPOL : {
6144 CFDictionaryRef config;
6145 CFStringRef unique_id = NULL;
6146
6147 // get configuration
6148 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
6149
6150 // get 802.1X identifier
6151 if (config != NULL) {
6152 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
6153 }
6154 if (!isA_CFString(unique_id)) {
6155 return FALSE;
6156 }
6157
6158 // check password
6159 exists = _SCPreferencesSystemKeychainPasswordItemExists(prefs, unique_id);
6160 break;
6161 }
6162
6163 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
6164 CFDictionaryRef config;
6165 CFStringRef xauth_id;
6166
6167 // get configuration
6168 config = SCNetworkInterfaceGetConfiguration(interface);
6169
6170 // get XAuth ID
6171 xauth_id = copyXAuthID(config, serviceID);
6172
6173 // check
6174 exists = __extract_password(prefs,
6175 config,
6176 kSCPropNetIPSecXAuthPassword,
6177 kSCPropNetIPSecXAuthPasswordEncryption,
6178 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
6179 xauth_id,
6180 NULL);
6181 CFRelease(xauth_id);
6182 break;
6183 }
6184
6185 case kSCNetworkInterfacePasswordTypeVPN : {
6186 CFDictionaryRef config;
6187 CFStringRef vpn_id;
6188
6189 // get configuration
6190 config = SCNetworkInterfaceGetConfiguration(interface);
6191
6192 // get serviceID
6193 vpn_id = getPasswordID(config, serviceID);
6194
6195 // check
6196 exists = __extract_password(prefs,
6197 config,
6198 kSCPropNetVPNAuthPassword,
6199 kSCPropNetVPNAuthPasswordEncryption,
6200 kSCValNetVPNAuthPasswordEncryptionKeychain,
6201 vpn_id,
6202 NULL);
6203 break;
6204 }
6205
6206 default :
6207 _SCErrorSet(kSCStatusInvalidArgument);
6208 return FALSE;
6209 }
6210
6211 return exists;
6212 }
6213
6214
6215 CFDataRef
6216 SCNetworkInterfaceCopyPassword(SCNetworkInterfaceRef interface,
6217 SCNetworkInterfacePasswordType passwordType)
6218 {
6219 CFDataRef password = NULL;
6220 SCPreferencesRef prefs = NULL;
6221 CFStringRef serviceID = NULL;
6222
6223 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
6224 return NULL;
6225 }
6226
6227 switch (passwordType) {
6228 case kSCNetworkInterfacePasswordTypePPP : {
6229 CFDictionaryRef config;
6230 CFStringRef unique_id;
6231
6232 // get configuration
6233 config = SCNetworkInterfaceGetConfiguration(interface);
6234
6235 // get serviceID
6236 unique_id = getPasswordID(config, serviceID);
6237
6238 // extract
6239 (void) __extract_password(prefs,
6240 config,
6241 kSCPropNetPPPAuthPassword,
6242 kSCPropNetPPPAuthPasswordEncryption,
6243 kSCValNetPPPAuthPasswordEncryptionKeychain,
6244 unique_id,
6245 &password);
6246 break;
6247 }
6248
6249 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
6250 CFDictionaryRef config;
6251 Boolean extended;
6252 CFStringRef shared_id;
6253
6254 // get configuration
6255 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP);
6256 if (extended) {
6257 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
6258 } else {
6259 config = SCNetworkInterfaceGetConfiguration(interface);
6260 }
6261
6262 // get sharedSecret ID
6263 shared_id = copySharedSecretID(config, serviceID);
6264
6265 // extract
6266 (void) __extract_password(prefs,
6267 config,
6268 kSCPropNetIPSecSharedSecret,
6269 kSCPropNetIPSecSharedSecretEncryption,
6270 kSCValNetIPSecSharedSecretEncryptionKeychain,
6271 shared_id,
6272 &password);
6273
6274 CFRelease(shared_id);
6275 break;
6276 }
6277
6278 case kSCNetworkInterfacePasswordTypeEAPOL : {
6279 CFDictionaryRef config;
6280 CFStringRef unique_id = NULL;
6281
6282 // get configuration
6283 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
6284
6285 // get 802.1X identifier
6286 if (config != NULL) {
6287 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
6288 }
6289 if (!isA_CFString(unique_id)) {
6290 _SCErrorSet(kSCStatusFailed);
6291 return NULL;
6292 }
6293
6294 // copy password
6295 password = _SCPreferencesSystemKeychainPasswordItemCopy(prefs, unique_id);
6296 break;
6297 }
6298
6299 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
6300 CFDictionaryRef config;
6301 CFStringRef xauth_id;
6302
6303 // get configuration
6304 config = SCNetworkInterfaceGetConfiguration(interface);
6305
6306 // get XAuth ID
6307 xauth_id = copyXAuthID(config, serviceID);
6308
6309 // extract
6310 (void) __extract_password(prefs,
6311 config,
6312 kSCPropNetIPSecXAuthPassword,
6313 kSCPropNetIPSecXAuthPasswordEncryption,
6314 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
6315 xauth_id,
6316 &password);
6317 CFRelease(xauth_id);
6318 break;
6319 }
6320
6321 case kSCNetworkInterfacePasswordTypeVPN : {
6322 CFDictionaryRef config;
6323 CFStringRef vpn_id;
6324
6325 // get configuration
6326 config = SCNetworkInterfaceGetConfiguration(interface);
6327
6328 // get serviceID
6329 vpn_id = getPasswordID(config, serviceID);
6330
6331 // extract
6332 (void) __extract_password(prefs,
6333 config,
6334 kSCPropNetVPNAuthPassword,
6335 kSCPropNetVPNAuthPasswordEncryption,
6336 kSCValNetVPNAuthPasswordEncryptionKeychain,
6337 vpn_id,
6338 &password);
6339 break;
6340 }
6341
6342 default :
6343 _SCErrorSet(kSCStatusInvalidArgument);
6344 return NULL;
6345 }
6346
6347 return password;
6348 }
6349
6350
6351 Boolean
6352 SCNetworkInterfaceRemovePassword(SCNetworkInterfaceRef interface,
6353 SCNetworkInterfacePasswordType passwordType)
6354 {
6355 Boolean ok = FALSE;
6356 SCPreferencesRef prefs = NULL;
6357 CFStringRef serviceID = NULL;
6358
6359 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
6360 return FALSE;
6361 }
6362
6363 switch (passwordType) {
6364 case kSCNetworkInterfacePasswordTypePPP : {
6365 CFDictionaryRef config;
6366 CFDictionaryRef newConfig = NULL;
6367 CFStringRef unique_id;
6368
6369 // get configuration
6370 config = SCNetworkInterfaceGetConfiguration(interface);
6371
6372 // get serviceID
6373 unique_id = getPasswordID(config, serviceID);
6374
6375 // remove password
6376 ok = __remove_password(prefs,
6377 config,
6378 kSCPropNetPPPAuthPassword,
6379 kSCPropNetPPPAuthPasswordEncryption,
6380 kSCValNetPPPAuthPasswordEncryptionKeychain,
6381 unique_id,
6382 &newConfig);
6383 if (ok) {
6384 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
6385 if (newConfig != NULL) CFRelease(newConfig);
6386 }
6387
6388 break;
6389 }
6390
6391 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
6392 CFDictionaryRef config;
6393 Boolean extended;
6394 CFDictionaryRef newConfig = NULL;
6395 CFStringRef shared_id;
6396
6397 // get configuration
6398 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP);
6399 if (extended) {
6400 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
6401 } else {
6402 config = SCNetworkInterfaceGetConfiguration(interface);
6403 }
6404
6405 // get sharedSecret ID
6406 shared_id = copySharedSecretID(config, serviceID);
6407
6408 // remove password
6409 ok = __remove_password(prefs,
6410 config,
6411 kSCPropNetIPSecSharedSecret,
6412 kSCPropNetIPSecSharedSecretEncryption,
6413 kSCValNetIPSecSharedSecretEncryptionKeychain,
6414 shared_id,
6415 &newConfig);
6416 if (ok) {
6417 if (extended) {
6418 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
6419 kSCEntNetIPSec,
6420 newConfig);
6421 } else {
6422 ok = SCNetworkInterfaceSetConfiguration(interface,
6423 newConfig);
6424 }
6425 if (newConfig != NULL) CFRelease(newConfig);
6426 }
6427
6428 CFRelease(shared_id);
6429 break;
6430 }
6431
6432 case kSCNetworkInterfacePasswordTypeEAPOL : {
6433 CFDictionaryRef config;
6434 CFStringRef unique_id = NULL;
6435
6436 // get configuration
6437 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
6438
6439 // get 802.1X identifier
6440 if (config != NULL) {
6441 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
6442 }
6443 if (!isA_CFString(unique_id)) {
6444 _SCErrorSet(kSCStatusFailed);
6445 return FALSE;
6446 }
6447
6448 // remove password
6449 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, unique_id);
6450 break;
6451 }
6452
6453 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
6454 CFDictionaryRef config;
6455 CFDictionaryRef newConfig = NULL;
6456 CFStringRef xauth_id;
6457
6458 // get configuration
6459 config = SCNetworkInterfaceGetConfiguration(interface);
6460
6461 // get XAuth ID
6462 xauth_id = copyXAuthID(config, serviceID);
6463
6464 // remove password
6465 ok = __remove_password(prefs,
6466 config,
6467 kSCPropNetIPSecXAuthPassword,
6468 kSCPropNetIPSecXAuthPasswordEncryption,
6469 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
6470 xauth_id,
6471 &newConfig);
6472 if (ok) {
6473 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
6474 if (newConfig != NULL) CFRelease(newConfig);
6475 }
6476
6477 CFRelease(xauth_id);
6478 break;
6479 }
6480
6481 case kSCNetworkInterfacePasswordTypeVPN : {
6482 CFDictionaryRef config;
6483 CFDictionaryRef newConfig = NULL;
6484 CFStringRef vpn_id;
6485
6486 // get configuration
6487 config = SCNetworkInterfaceGetConfiguration(interface);
6488
6489 // get serviceID
6490 vpn_id = getPasswordID(config, serviceID);
6491
6492 // remove password
6493 ok = __remove_password(prefs,
6494 config,
6495 kSCPropNetVPNAuthPassword,
6496 kSCPropNetVPNAuthPasswordEncryption,
6497 kSCValNetVPNAuthPasswordEncryptionKeychain,
6498 vpn_id,
6499 &newConfig);
6500 if (ok) {
6501 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
6502 if (newConfig != NULL) CFRelease(newConfig);
6503 }
6504 break;
6505 }
6506
6507 default :
6508 _SCErrorSet(kSCStatusInvalidArgument);
6509 return FALSE;
6510 }
6511
6512 return ok;
6513 }
6514
6515
6516 Boolean
6517 SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface,
6518 SCNetworkInterfacePasswordType passwordType,
6519 CFDataRef password,
6520 CFDictionaryRef options)
6521 {
6522 CFStringRef account = NULL;
6523 CFDictionaryRef config;
6524 CFStringRef description = NULL;
6525 CFStringRef label = NULL;
6526 Boolean ok = FALSE;
6527 SCPreferencesRef prefs = NULL;
6528 CFStringRef serviceID = NULL;
6529
6530 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
6531 return FALSE;
6532 }
6533
6534 switch (passwordType) {
6535 case kSCNetworkInterfacePasswordTypePPP : {
6536 SCNetworkServiceRef service = NULL;
6537 CFStringRef unique_id;
6538
6539 // get configuration
6540 config = SCNetworkInterfaceGetConfiguration(interface);
6541
6542 // get serviceID
6543 unique_id = getPasswordID(config, serviceID);
6544
6545 // get "Account", "Name", "Kind"
6546 if (config != NULL) {
6547 // auth name --> keychain "Account"
6548 account = CFDictionaryGetValue(config, kSCPropNetPPPAuthName);
6549
6550 // PPP [user defined] "name" --> keychain "Name"
6551 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
6552 }
6553
6554 if (label == NULL) {
6555 // service name --> keychain "Name"
6556 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
6557 prefs,
6558 serviceID,
6559 interface);
6560
6561 label = SCNetworkServiceGetName(service);
6562 if (label == NULL) {
6563 // interface name --> keychain "Name"
6564 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
6565 }
6566 }
6567
6568 if (bundle != NULL) {
6569 // "PPP Password" --> keychain "Kind"
6570 description = CFBundleCopyLocalizedString(bundle,
6571 CFSTR("KEYCHAIN_KIND_PPP_PASSWORD"),
6572 CFSTR("PPP Password"),
6573 NULL);
6574 }
6575
6576 // store password
6577 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
6578 unique_id,
6579 (label != NULL) ? label : CFSTR("Network Connection"),
6580 (description != NULL) ? description : CFSTR("PPP Password"),
6581 account,
6582 password,
6583 options);
6584 if (ok) {
6585 CFMutableDictionaryRef newConfig;
6586
6587 if (config != NULL) {
6588 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
6589 } else {
6590 newConfig = CFDictionaryCreateMutable(NULL,
6591 0,
6592 &kCFTypeDictionaryKeyCallBacks,
6593 &kCFTypeDictionaryValueCallBacks);
6594 }
6595 CFDictionarySetValue(newConfig,
6596 kSCPropNetPPPAuthPassword,
6597 unique_id);
6598 CFDictionarySetValue(newConfig,
6599 kSCPropNetPPPAuthPasswordEncryption,
6600 kSCValNetPPPAuthPasswordEncryptionKeychain);
6601 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
6602 CFRelease(newConfig);
6603 }
6604
6605 if (description != NULL) CFRelease(description);
6606 if (service != NULL) CFRelease(service);
6607 break;
6608 }
6609
6610 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
6611 CFDictionaryRef baseConfig = NULL;
6612 Boolean extended;
6613 SCNetworkServiceRef service = NULL;
6614 CFStringRef shared_id;
6615
6616 // get configuration
6617 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP);
6618 config = SCNetworkInterfaceGetConfiguration(interface);
6619 if (extended) {
6620 baseConfig = config;
6621 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
6622 }
6623
6624 // get sharedSecret ID
6625 shared_id = copySharedSecretID(config, serviceID);
6626
6627 // get "Account", "Name", "Kind"
6628 if (config != NULL) {
6629 CFStringRef localIdentifier;
6630 CFStringRef localIdentifierType;
6631
6632 if (CFDictionaryGetValueIfPresent(config,
6633 kSCPropNetIPSecLocalIdentifierType,
6634 (const void **)&localIdentifierType)
6635 && CFEqual(localIdentifierType, kSCValNetIPSecLocalIdentifierTypeKeyID)
6636 && CFDictionaryGetValueIfPresent(config,
6637 kSCPropNetIPSecLocalIdentifier,
6638 (const void **)&localIdentifier)
6639 && isA_CFString(localIdentifier)) {
6640 // local identifier --> keychain "Account"
6641 account = localIdentifier;
6642 }
6643
6644 // PPP [user defined] "name" --> keychain "Name"
6645 if (!extended) {
6646 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
6647 } else {
6648 if (baseConfig != NULL) {
6649 label = CFDictionaryGetValue(baseConfig, kSCPropUserDefinedName);
6650 }
6651 }
6652 }
6653
6654 if (label == NULL) {
6655 // service name --> keychain "Name"
6656 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
6657 prefs,
6658 serviceID,
6659 interface);
6660
6661 label = SCNetworkServiceGetName(service);
6662 if (label == NULL) {
6663 // interface name --> keychain "Name"
6664 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
6665 }
6666 }
6667
6668 if (bundle != NULL) {
6669 // "IPSec Shared Secret" --> keychain "Kind"
6670 description = CFBundleCopyLocalizedString(bundle,
6671 CFSTR("KEYCHAIN_KIND_IPSEC_SHARED_SECRET"),
6672 CFSTR("IPSec Shared Secret"),
6673 NULL);
6674 }
6675
6676 // set password
6677 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
6678 shared_id,
6679 (label != NULL) ? label : CFSTR("Network Connection"),
6680 (description != NULL) ? description : CFSTR("IPSec Shared Secret"),
6681 account,
6682 password,
6683 options);
6684 if (ok) {
6685 CFMutableDictionaryRef newConfig = NULL;
6686
6687 if (config != NULL) {
6688 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
6689 } else {
6690 newConfig = CFDictionaryCreateMutable(NULL,
6691 0,
6692 &kCFTypeDictionaryKeyCallBacks,
6693 &kCFTypeDictionaryValueCallBacks);
6694 }
6695 CFDictionarySetValue(newConfig,
6696 kSCPropNetIPSecSharedSecret,
6697 shared_id);
6698 CFDictionarySetValue(newConfig,
6699 kSCPropNetIPSecSharedSecretEncryption,
6700 kSCValNetIPSecSharedSecretEncryptionKeychain);
6701 if (extended) {
6702 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
6703 kSCEntNetIPSec,
6704 newConfig);
6705 } else {
6706 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
6707 }
6708 CFRelease(newConfig);
6709 }
6710
6711 if (description != NULL) CFRelease(description);
6712 if (service != NULL) CFRelease(service);
6713 CFRelease(shared_id);
6714 break;
6715 }
6716
6717 case kSCNetworkInterfacePasswordTypeEAPOL : {
6718 CFStringRef account = NULL;
6719 CFStringRef unique_id = NULL;
6720
6721 // get configuration
6722 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
6723
6724 // get 802.1X identifier
6725 if (config != NULL) {
6726 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
6727 unique_id = isA_CFString(unique_id);
6728 }
6729 if (unique_id != NULL) {
6730 CFRetain(unique_id);
6731 } else {
6732 CFUUIDRef uuid;
6733
6734 uuid = CFUUIDCreate(NULL);
6735 unique_id = CFUUIDCreateString(NULL, uuid);
6736 CFRelease(uuid);
6737 }
6738
6739 // 802.1x UserName --> keychain "Account"
6740 if (config != NULL) {
6741 account = CFDictionaryGetValue(config, kEAPClientPropUserName);
6742 }
6743
6744 // get "Name", "Kind"
6745 if (bundle != NULL) {
6746 CFStringRef interface_name;
6747
6748 // "Network Connection (%@)" --> keychain "Name"
6749 interface_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
6750 if (interface_name != NULL) {
6751 CFStringRef label_fmt;
6752
6753 label_fmt = CFBundleCopyLocalizedString(bundle,
6754 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL_INTERFACE"),
6755 CFSTR("Network Connection (%@)"),
6756 NULL);
6757 label = CFStringCreateWithFormat(NULL, NULL, label_fmt, interface_name);
6758 CFRelease(label_fmt);
6759 } else {
6760 label = CFBundleCopyLocalizedString(bundle,
6761 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL"),
6762 CFSTR("Network Connection"),
6763 NULL);
6764 }
6765
6766 // "802.1X Password" --> keychain "Kind"
6767 description = CFBundleCopyLocalizedString(bundle,
6768 CFSTR("KEYCHAIN_KIND_EAPOL"),
6769 CFSTR("802.1X Password"),
6770 NULL);
6771 }
6772
6773 // set password
6774 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
6775 unique_id,
6776 (label != NULL) ? label : CFSTR("Network Connection"),
6777 (description != NULL) ? description : CFSTR("802.1X Password"),
6778 account,
6779 password,
6780 options);
6781 if (ok) {
6782 CFMutableDictionaryRef newConfig = NULL;
6783
6784 if (config != NULL) {
6785 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
6786 } else {
6787 newConfig = CFDictionaryCreateMutable(NULL,
6788 0,
6789 &kCFTypeDictionaryKeyCallBacks,
6790 &kCFTypeDictionaryValueCallBacks);
6791 }
6792 CFDictionarySetValue(newConfig,
6793 kEAPClientPropUserPasswordKeychainItemID,
6794 unique_id);
6795 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
6796 kSCEntNetEAPOL,
6797 newConfig);
6798 CFRelease(newConfig);
6799 }
6800
6801 CFRelease(unique_id);
6802 if (label != NULL) CFRelease(label);
6803 if (description != NULL) CFRelease(description);
6804 break;
6805 }
6806
6807 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
6808 SCNetworkServiceRef service = NULL;
6809 CFStringRef xauth_id;
6810
6811 // get configuration
6812 config = SCNetworkInterfaceGetConfiguration(interface);
6813
6814 // get XAuth ID
6815 xauth_id = copyXAuthID(config, serviceID);
6816
6817 // get "Account", "Name", "Kind"
6818 if (config != NULL) {
6819 // auth name --> keychain "Account"
6820 account = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthName);
6821
6822 // IPSec [user defined] "name" --> keychain "Name"
6823 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
6824 }
6825
6826 if (label == NULL) {
6827 // service name --> keychain "Name"
6828 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
6829 prefs,
6830 serviceID,
6831 interface);
6832
6833 label = SCNetworkServiceGetName(service);
6834 if (label == NULL) {
6835 // interface name --> keychain "Name"
6836 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
6837 }
6838 }
6839
6840 if (bundle != NULL) {
6841 // "IPSec XAuth Password" --> keychain "Kind"
6842 description = CFBundleCopyLocalizedString(bundle,
6843 CFSTR("KEYCHAIN_KIND_IPSEC_XAUTH_PASSWORD"),
6844 CFSTR("IPSec XAuth Password"),
6845 NULL);
6846 }
6847
6848 // store password
6849 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
6850 xauth_id,
6851 (label != NULL) ? label : CFSTR("Network Connection"),
6852 (description != NULL) ? description : CFSTR("IPSec XAuth Password"),
6853 account,
6854 password,
6855 options);
6856 if (ok) {
6857 CFMutableDictionaryRef newConfig;
6858
6859 if (config != NULL) {
6860 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
6861 } else {
6862 newConfig = CFDictionaryCreateMutable(NULL,
6863 0,
6864 &kCFTypeDictionaryKeyCallBacks,
6865 &kCFTypeDictionaryValueCallBacks);
6866 }
6867 CFDictionarySetValue(newConfig,
6868 kSCPropNetIPSecXAuthPassword,
6869 xauth_id);
6870 CFDictionarySetValue(newConfig,
6871 kSCPropNetIPSecXAuthPasswordEncryption,
6872 kSCValNetIPSecXAuthPasswordEncryptionKeychain);
6873 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
6874 CFRelease(newConfig);
6875 }
6876
6877 CFRelease(xauth_id);
6878 if (description != NULL) CFRelease(description);
6879 if (service != NULL) CFRelease(service);
6880 break;
6881 }
6882
6883 case kSCNetworkInterfacePasswordTypeVPN : {
6884 SCNetworkServiceRef service = NULL;
6885 CFStringRef vpn_id;
6886
6887 // get configuration
6888 config = SCNetworkInterfaceGetConfiguration(interface);
6889
6890 // get serviceID
6891 vpn_id = getPasswordID(config, serviceID);
6892
6893 // get "Account", "Name", "Kind"
6894 if (config != NULL) {
6895 // auth name --> keychain "Account"
6896 account = CFDictionaryGetValue(config, kSCPropNetVPNAuthName);
6897
6898 // VPN [user defined] "name" --> keychain "Name"
6899 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
6900 }
6901
6902 if (label == NULL) {
6903 // service name --> keychain "Name"
6904 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
6905 prefs,
6906 serviceID,
6907 interface);
6908
6909 label = SCNetworkServiceGetName(service);
6910 if (label == NULL) {
6911 // interface name --> keychain "Name"
6912 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
6913 }
6914 }
6915
6916 if (bundle != NULL) {
6917 // "VPN Password" --> keychain "Kind"
6918 description = CFBundleCopyLocalizedString(bundle,
6919 CFSTR("KEYCHAIN_KIND_VPN_PASSWORD"),
6920 CFSTR("VPN Password"),
6921 NULL);
6922 }
6923
6924 // store password
6925 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
6926 vpn_id,
6927 (label != NULL) ? label : CFSTR("Network Connection"),
6928 (description != NULL) ? description : CFSTR("VPN Password"),
6929 account,
6930 password,
6931 options);
6932 if (ok) {
6933 CFMutableDictionaryRef newConfig;
6934
6935 if (config != NULL) {
6936 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
6937 } else {
6938 newConfig = CFDictionaryCreateMutable(NULL,
6939 0,
6940 &kCFTypeDictionaryKeyCallBacks,
6941 &kCFTypeDictionaryValueCallBacks);
6942 }
6943 CFDictionarySetValue(newConfig,
6944 kSCPropNetVPNAuthPassword,
6945 vpn_id);
6946 CFDictionarySetValue(newConfig,
6947 kSCPropNetVPNAuthPasswordEncryption,
6948 kSCValNetVPNAuthPasswordEncryptionKeychain);
6949 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
6950 CFRelease(newConfig);
6951 }
6952
6953 if (description != NULL) CFRelease(description);
6954 if (service != NULL) CFRelease(service);
6955 break;
6956 }
6957
6958 default :
6959 _SCErrorSet(kSCStatusInvalidArgument);
6960 break;
6961 }
6962
6963 return ok;
6964 }
6965
6966
6967 #pragma mark -
6968 #pragma mark SCNetworkInterface [InterfaceNamer] SPIs
6969
6970
6971 CFDictionaryRef
6972 _SCNetworkInterfaceCopyInterfaceInfo(SCNetworkInterfaceRef interface)
6973 {
6974 CFMutableDictionaryRef info;
6975 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
6976 CFStringRef name;
6977
6978 if (interface == NULL) {
6979 return NULL;
6980 }
6981
6982 info = CFDictionaryCreateMutable(NULL,
6983 0,
6984 &kCFTypeDictionaryKeyCallBacks,
6985 &kCFTypeDictionaryValueCallBacks);
6986
6987 // add non-localized interface name
6988 name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface);
6989 if (name != NULL) {
6990 CFDictionaryAddValue(info, kSCPropUserDefinedName, name);
6991 }
6992
6993 // add USB info
6994 if ((interfacePrivate->usb.vid != NULL) || (interfacePrivate->usb.pid != NULL)) {
6995 #if !TARGET_OS_SIMULATOR
6996 if (interfacePrivate->usb.name != NULL) {
6997 CFDictionaryAddValue(info, CFSTR(kUSBProductString), interfacePrivate->usb.name);
6998 }
6999 if (interfacePrivate->usb.vid != NULL) {
7000 CFDictionaryAddValue(info, CFSTR(kUSBVendorID), interfacePrivate->usb.vid);
7001 }
7002 if (interfacePrivate->usb.pid != NULL) {
7003 CFDictionaryAddValue(info, CFSTR(kUSBProductID), interfacePrivate->usb.pid);
7004 }
7005 #endif // !TARGET_OS_SIMULATOR
7006 }
7007
7008 if (CFDictionaryGetCount(info) == 0) {
7009 // do not return an empty dictionary
7010 CFRelease(info);
7011 info = NULL;
7012 }
7013
7014 return info;
7015 }
7016
7017
7018 SCNetworkInterfaceRef
7019 _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj)
7020 {
7021 SCNetworkInterfaceRef interface = NULL;
7022
7023 /* initialize runtime */
7024 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
7025
7026 if (IOObjectConformsTo(if_obj, kIONetworkInterfaceClass)) {
7027 interface = createInterface(if_obj, processNetworkInterface, NULL);
7028 } else if (IOObjectConformsTo(if_obj, kIOSerialBSDServiceValue)) {
7029 interface = createInterface(if_obj, processSerialInterface, kSCNetworkInterfaceHiddenPortKey);
7030 }
7031
7032 return interface;
7033 }
7034
7035
7036 CFStringRef
7037 _SCNetworkInterfaceGetConfigurationAction(SCNetworkInterfaceRef interface)
7038 {
7039 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7040
7041 return interfacePrivate->configurationAction;
7042 }
7043
7044
7045 CFDataRef
7046 _SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface)
7047 {
7048 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7049
7050 return interfacePrivate->address;
7051 }
7052
7053
7054 CFStringRef
7055 _SCNetworkInterfaceGetIOInterfaceNamePrefix(SCNetworkInterfaceRef interface)
7056 {
7057 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7058
7059 return interfacePrivate->prefix;
7060 }
7061
7062
7063 CFNumberRef
7064 _SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface)
7065 {
7066 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7067
7068 return interfacePrivate->type;
7069 }
7070
7071
7072 CFNumberRef
7073 _SCNetworkInterfaceGetIOInterfaceUnit(SCNetworkInterfaceRef interface)
7074 {
7075 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7076
7077 return interfacePrivate->unit;
7078 }
7079
7080
7081 static void
7082 update_ift_family(SCNetworkInterfaceRef interface)
7083 {
7084 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7085
7086 // note: family/subfamily are not in IORegistry, fetch with ioctl()
7087
7088 if ((interfacePrivate->family == NULL) && (interfacePrivate->subfamily == NULL)) {
7089 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
7090 struct ifreq ifr;
7091
7092 bzero(&ifr, sizeof(ifr));
7093 if ((bsdName != NULL) &&
7094 _SC_cfstring_to_cstring(bsdName, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII) != NULL) {
7095 int s;
7096
7097 s = socket(AF_INET, SOCK_DGRAM, 0);
7098 if (s != -1) {
7099 if (ioctl(s, SIOCGIFTYPE, (caddr_t)&ifr) == -1) {
7100 ifr.ifr_type.ift_family = 0;
7101 ifr.ifr_type.ift_subfamily = 0;
7102 }
7103 close(s);
7104 }
7105 }
7106
7107 interfacePrivate->family = CFNumberCreate(NULL,
7108 kCFNumberSInt32Type,
7109 &ifr.ifr_type.ift_family);
7110 interfacePrivate->subfamily = CFNumberCreate(NULL,
7111 kCFNumberSInt32Type,
7112 &ifr.ifr_type.ift_subfamily);
7113 }
7114 }
7115
7116
7117 CFNumberRef
7118 _SCNetworkInterfaceGetFamilyType(SCNetworkInterfaceRef interface)
7119 {
7120 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7121
7122 // note: family not in IORegistry, fetch with ioctl()
7123
7124 if (interfacePrivate->family == NULL) {
7125 update_ift_family(interface);
7126 }
7127
7128 return interfacePrivate->family;
7129 }
7130
7131
7132 CFNumberRef
7133 _SCNetworkInterfaceGetFamilySubType(SCNetworkInterfaceRef interface)
7134 {
7135 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7136
7137 // note: subfamily not in IORegistry, fetch with ioctl()
7138
7139 if (interfacePrivate->subfamily == NULL) {
7140 update_ift_family(interface);
7141 }
7142
7143 return interfacePrivate->subfamily;
7144 }
7145
7146
7147 CFStringRef
7148 _SCNetworkInterfaceGetIOPath(SCNetworkInterfaceRef interface)
7149 {
7150 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7151
7152 return interfacePrivate->path;
7153 }
7154
7155
7156 uint64_t
7157 _SCNetworkInterfaceGetIORegistryEntryID(SCNetworkInterfaceRef interface)
7158 {
7159 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7160
7161 return interfacePrivate->entryID;
7162 }
7163
7164
7165 __private_extern__
7166 Boolean
7167 __SCNetworkInterfaceIsActive (SCNetworkInterfaceRef interface)
7168 {
7169 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7170
7171 return interfacePrivate->active;
7172 }
7173
7174
7175 Boolean
7176 _SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface)
7177 {
7178 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7179
7180 return interfacePrivate->builtin;
7181 }
7182
7183
7184 #pragma mark -
7185 #pragma mark SCNetworkInterface SPIs
7186
7187
7188 #if !TARGET_OS_EMBEDDED
7189
7190 SCNetworkInterfaceRef
7191 _SCNetworkInterfaceCopyBTPANInterface(void)
7192 {
7193 CFDictionaryRef dict;
7194 SCNetworkInterfaceRef interface = NULL;
7195 CFStringRef key;
7196
7197 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin);
7198 dict = SCDynamicStoreCopyValue(NULL, key);
7199 CFRelease(key);
7200 if (dict != NULL) {
7201 CFDataRef addr;
7202 CFStringRef if_name;
7203 SCNetworkInterfacePrivateRef interfacePrivate;
7204
7205 if (isA_CFDictionary(dict) &&
7206 CFDictionaryGetValueIfPresent(dict,
7207 kInterfaceNamerKey_BT_PAN_Name,
7208 (const void **)&if_name) &&
7209 isA_CFString(if_name)) {
7210 CFMutableDictionaryRef entity;
7211
7212 entity = CFDictionaryCreateMutable(NULL,
7213 0,
7214 &kCFTypeDictionaryKeyCallBacks,
7215 &kCFTypeDictionaryValueCallBacks);
7216 CFDictionarySetValue(entity,
7217 kSCPropNetInterfaceType,
7218 kSCValNetInterfaceTypeEthernet);
7219 CFDictionarySetValue(entity,
7220 kSCPropNetInterfaceDeviceName,
7221 if_name);
7222 CFDictionarySetValue(entity,
7223 kSCPropUserDefinedName,
7224 CFSTR(BT_PAN_NAME));
7225 interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL);
7226 CFRelease(entity);
7227 }
7228
7229 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7230
7231 if ((interfacePrivate != NULL) &&
7232 (interfacePrivate->address == NULL) &&
7233 CFDictionaryGetValueIfPresent(dict,
7234 kInterfaceNamerKey_BT_PAN_Mac,
7235 (const void **)&addr) &&
7236 isA_CFData(addr)) {
7237 interfacePrivate->address = CFRetain(addr);
7238 }
7239
7240 CFRelease(dict);
7241 }
7242
7243 return interface;
7244 }
7245 #endif // !TARGET_OS_EMBEDDED
7246
7247
7248 CFStringRef
7249 _SCNetworkInterfaceCopySlashDevPath(SCNetworkInterfaceRef interface)
7250 {
7251 io_registry_entry_t device;
7252 io_iterator_t device_iterator = MACH_PORT_NULL;
7253 CFStringRef device_path = NULL;
7254 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7255 kern_return_t kr;
7256 CFStringRef match_keys[2];
7257 CFTypeRef match_vals[2];
7258 CFDictionaryRef match_dict;
7259 CFDictionaryRef matching;
7260
7261 if (interfacePrivate->entity_device == NULL) {
7262 return NULL;
7263 }
7264
7265 if (interfacePrivate->entity_device_unique == NULL) {
7266 goto done;
7267 }
7268
7269 match_keys[0] = CFSTR(kIOTTYBaseNameKey);
7270 match_vals[0] = interfacePrivate->entity_device;
7271 match_dict = CFDictionaryCreate(NULL,
7272 (const void **)match_keys,
7273 (const void **)match_vals,
7274 1,
7275 &kCFTypeDictionaryKeyCallBacks,
7276 &kCFTypeDictionaryValueCallBacks);
7277
7278 match_keys[0] = CFSTR(kIOProviderClassKey);
7279 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
7280 match_keys[1] = CFSTR(kIOPropertyMatchKey);
7281 match_vals[1] = match_dict;
7282 matching = CFDictionaryCreate(NULL,
7283 (const void **)match_keys,
7284 (const void **)match_vals,
7285 sizeof(match_keys)/sizeof(match_keys[0]),
7286 &kCFTypeDictionaryKeyCallBacks,
7287 &kCFTypeDictionaryValueCallBacks);
7288 CFRelease(match_dict);
7289
7290 // note: this "matching" dictionary will be consumed by the call to IOServiceGetMatchingServices
7291 kr = IOServiceGetMatchingServices(masterPort, matching, &device_iterator);
7292 if (kr != kIOReturnSuccess) {
7293 SC_log(LOG_INFO, "IOServiceGetMatchingServices() failed, kr = 0x%x", kr);
7294 goto done;
7295 }
7296
7297 while ((device_path == NULL) &&
7298 ((device = IOIteratorNext(device_iterator)) != MACH_PORT_NULL)) {
7299 CFDictionaryRef overrides;
7300
7301 overrides = IORegistryEntrySearchCFProperty(device,
7302 kIOServicePlane,
7303 kSCNetworkInterfaceNetworkConfigurationOverridesKey,
7304 NULL,
7305 kIORegistryIterateRecursively | kIORegistryIterateParents);
7306 if (overrides != NULL) {
7307 CFDictionaryRef modemOverrides;
7308
7309 modemOverrides = CFDictionaryGetValue(overrides, kSCEntNetModem);
7310 if (modemOverrides != NULL) {
7311 CFRetain(modemOverrides);
7312 }
7313 CFRelease(overrides);
7314 overrides = modemOverrides;
7315 }
7316 if (overrides == NULL) {
7317 overrides = IORegistryEntrySearchCFProperty(device,
7318 kIOServicePlane,
7319 CFSTR("DeviceModemOverrides"),
7320 NULL,
7321 kIORegistryIterateRecursively | kIORegistryIterateParents);
7322 }
7323 if (overrides != NULL) {
7324 if (isA_CFDictionary(overrides)) {
7325 CFStringRef matchIdentifier;
7326
7327 matchIdentifier = CFDictionaryGetValue(overrides, CFSTR("UniqueIdentifier"));
7328 if (isA_CFString(matchIdentifier) &&
7329 CFEqual(interfacePrivate->entity_device_unique, matchIdentifier)) {
7330 device_path = IORegistryEntryCreateCFProperty(device,
7331 CFSTR(kIOTTYDeviceKey),
7332 NULL,
7333 0);
7334 }
7335 }
7336 CFRelease(overrides);
7337 }
7338 IOObjectRelease(device);
7339 }
7340
7341 IOObjectRelease(device_iterator);
7342
7343 done :
7344
7345 if (device_path == NULL) {
7346 // if we haven't found an exact match to our UniqueIdentifier
7347 // so we simply return the base name.
7348 device_path = SCNetworkInterfaceGetBSDName(interface);
7349 if (device_path != NULL) {
7350 CFRetain(device_path);
7351 }
7352 }
7353
7354 return device_path;
7355 }
7356
7357
7358 #pragma mark -
7359
7360
7361 Boolean
7362 _SCNetworkInterfaceIsApplePreconfigured(SCNetworkInterfaceRef interface)
7363 {
7364 #if TARGET_OS_SIMULATOR
7365 #pragma unused(interface)
7366 #else // TARGET_OS_SIMULATOR
7367 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7368
7369 if (!interfacePrivate->hidden) {
7370 // if not HiddenConfiguration
7371 return FALSE;
7372 }
7373
7374 if ((interfacePrivate->overrides == NULL) ||
7375 (!CFDictionaryContainsKey(interfacePrivate->overrides, kSCNetworkProtocolTypeIPv4) &&
7376 !CFDictionaryContainsKey(interfacePrivate->overrides, kSCNetworkProtocolTypeIPv6))) {
7377 // if no [IPv4/IPv6] configuration overrides
7378 return FALSE;
7379 }
7380
7381 if (interfacePrivate->builtin) {
7382 // if built-in (and overrides are present)
7383 return TRUE;
7384 }
7385
7386 if (isA_CFNumber(interfacePrivate->usb.vid)) {
7387 int vid;
7388
7389 if (CFNumberGetValue(interfacePrivate->usb.vid, kCFNumberIntType, &vid) &&
7390 (vid == kIOUSBVendorIDAppleComputer)) {
7391 // if Apple interface (and overrides are present)
7392 return TRUE;
7393 }
7394 }
7395 #endif // TARGET_OS_SIMULATOR
7396
7397 return FALSE;
7398 }
7399
7400
7401 Boolean
7402 _SCNetworkInterfaceIsBluetoothPAN(SCNetworkInterfaceRef interface)
7403 {
7404 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7405
7406 return (interfacePrivate->sort_order == kSortBluetoothPAN_GN);
7407 }
7408
7409
7410 Boolean
7411 _SCNetworkInterfaceIsBluetoothPAN_NAP(SCNetworkInterfaceRef interface)
7412 {
7413 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7414
7415 return (interfacePrivate->sort_order == kSortBluetoothPAN_NAP);
7416 }
7417
7418
7419 Boolean
7420 _SCNetworkInterfaceIsBluetoothP2P(SCNetworkInterfaceRef interface)
7421 {
7422 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7423
7424 return (interfacePrivate->sort_order == kSortBluetoothPAN_U);
7425 }
7426
7427
7428 Boolean
7429 _SCNetworkInterfaceIsHiddenConfiguration(SCNetworkInterfaceRef interface)
7430 {
7431 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7432
7433 return interfacePrivate->hidden;
7434 }
7435
7436
7437 Boolean
7438 _SCNetworkInterfaceIsTethered(SCNetworkInterfaceRef interface)
7439 {
7440 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7441
7442 return (interfacePrivate->sort_order == kSortTethered);
7443 }
7444
7445
7446 Boolean
7447 _SCNetworkInterfaceIsThunderbolt(SCNetworkInterfaceRef interface)
7448 {
7449 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
7450 CFStringRef interfaceType;
7451
7452 if (!isA_SCNetworkInterface(interface)) {
7453 return FALSE;
7454 }
7455
7456 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
7457 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) {
7458 CFIndex i;
7459 CFArrayRef members;
7460 CFIndex n;
7461
7462 members = SCBridgeInterfaceGetMemberInterfaces(interface);
7463 n = (members != NULL) ? CFArrayGetCount(members) : 0;
7464 if (n == 0) {
7465 // if an empty bridge
7466 return FALSE;
7467 }
7468
7469 for (i = 0; i < n; i++) {
7470 SCNetworkInterfaceRef member;
7471 SCNetworkInterfacePrivateRef memberPrivate;
7472
7473 member = CFArrayGetValueAtIndex(members, i);
7474 memberPrivate = (SCNetworkInterfacePrivateRef)member;
7475 if (memberPrivate->sort_order != kSortThunderbolt) {
7476 return FALSE;
7477 }
7478 }
7479
7480 // if Ethernet Bridge interface with only Thunderbolt [IP] members
7481 return TRUE;
7482 }
7483
7484 return (interfacePrivate->sort_order == kSortThunderbolt);
7485 }
7486
7487
7488 #pragma mark -
7489
7490
7491 CFDictionaryRef
7492 SCNetworkInterfaceGetQoSMarkingPolicy(SCNetworkInterfaceRef interface)
7493 {
7494 CFDictionaryRef policy;
7495
7496 if (!isA_SCNetworkInterface(interface)) {
7497 _SCErrorSet(kSCStatusInvalidArgument);
7498 return NULL;
7499 }
7500
7501 policy = __SCNetworkInterfaceGetConfiguration(interface, kSCEntNetQoSMarkingPolicy);
7502 if (policy == NULL) {
7503 _SCErrorSet(kSCStatusOK);
7504 }
7505
7506 return policy;
7507 }
7508
7509 Boolean
7510 SCNetworkInterfaceSetQoSMarkingPolicy(SCNetworkInterfaceRef interface, CFDictionaryRef policy)
7511 {
7512 Boolean ok;
7513
7514 if (!isA_SCNetworkInterface(interface)) {
7515 _SCErrorSet(kSCStatusInvalidArgument);
7516 return FALSE;
7517 }
7518
7519 ok = __SCNetworkInterfaceSetConfiguration(interface, kSCEntNetQoSMarkingPolicy, policy, FALSE);
7520 if (ok) {
7521 SC_log(LOG_DEBUG, "SCNetworkInterfaceSetQoSMarkingPolicy(): %@ -> %@",
7522 interface,
7523 policy != NULL ? policy : (CFDictionaryRef)CFSTR("NULL"));
7524 }
7525
7526 return ok;
7527 }
7528
7529
7530 #pragma mark -
7531 #pragma mark SCNetworkInterface [internal] SPIs
7532
7533
7534 __private_extern__
7535 SCNetworkInterfacePrivateRef
7536 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator,
7537 SCNetworkInterfaceRef interface,
7538 SCPreferencesRef prefs,
7539 CFStringRef serviceID)
7540 {
7541 #pragma unused(allocator)
7542 SCNetworkInterfacePrivateRef oldPrivate = (SCNetworkInterfacePrivateRef)interface;
7543 SCNetworkInterfacePrivateRef newPrivate;
7544
7545 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
7546 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
7547
7548 if (interface == kSCNetworkInterfaceIPv4) {
7549 return (SCNetworkInterfacePrivateRef)CFRetain(interface);
7550 }
7551
7552 newPrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, prefs, serviceID);
7553 newPrivate->interface_type = oldPrivate->interface_type;
7554 if (oldPrivate->interface != NULL) {
7555 newPrivate->interface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, // allocator
7556 oldPrivate->interface, // interface
7557 prefs, // [new] prefs
7558 serviceID); // [new] serviceID
7559 }
7560 if (oldPrivate->name != NULL) {
7561 newPrivate->name = CFRetain(oldPrivate->name);
7562 }
7563 if (oldPrivate->prefix != NULL) {
7564 newPrivate->prefix = CFRetain(oldPrivate->prefix);
7565 }
7566 if (oldPrivate->localized_name != NULL) {
7567 newPrivate->localized_name = CFRetain(oldPrivate->localized_name);
7568 }
7569 newPrivate->localized_key = oldPrivate->localized_key;
7570 if (oldPrivate->localized_arg1 != NULL) {
7571 newPrivate->localized_arg1 = CFRetain(oldPrivate->localized_arg1);
7572 }
7573 if (oldPrivate->localized_arg2 != NULL) {
7574 newPrivate->localized_arg2 = CFRetain(oldPrivate->localized_arg2);
7575 }
7576 if (oldPrivate->unsaved != NULL) {
7577 newPrivate->unsaved = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->unsaved);
7578 }
7579 if (oldPrivate->entity_device != NULL) {
7580 newPrivate->entity_device = CFRetain(oldPrivate->entity_device);
7581 }
7582 if (oldPrivate->entity_device_unique != NULL) {
7583 newPrivate->entity_device_unique = CFRetain(oldPrivate->entity_device_unique);
7584 }
7585 newPrivate->entity_type = oldPrivate->entity_type;
7586 newPrivate->entity_subtype = oldPrivate->entity_subtype;
7587 if (oldPrivate->supported_interface_types != NULL) {
7588 newPrivate->supported_interface_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_interface_types);
7589 }
7590 if (oldPrivate->supported_protocol_types != NULL) {
7591 newPrivate->supported_protocol_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_protocol_types);
7592 }
7593 if (oldPrivate->address != NULL) {
7594 newPrivate->address = CFRetain(oldPrivate->address);
7595 }
7596 newPrivate->builtin = oldPrivate->builtin;
7597 if (oldPrivate->configurationAction != NULL) {
7598 newPrivate->configurationAction = CFRetain(oldPrivate->configurationAction);
7599 }
7600 newPrivate->hidden = oldPrivate->hidden;
7601 if (oldPrivate->location != NULL) {
7602 newPrivate->location = CFRetain(oldPrivate->location);
7603 }
7604 if (oldPrivate->path != NULL) {
7605 newPrivate->path = CFRetain(oldPrivate->path);
7606 }
7607 newPrivate->entryID = oldPrivate->entryID;
7608 if (oldPrivate->overrides != NULL) {
7609 newPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->overrides);
7610 }
7611 if (oldPrivate->type != NULL) {
7612 newPrivate->type = CFRetain(oldPrivate->type);
7613 }
7614 if (oldPrivate->unit != NULL) {
7615 newPrivate->unit = CFRetain(oldPrivate->unit);
7616 }
7617 if (oldPrivate->family != NULL) {
7618 newPrivate->family = CFRetain(oldPrivate->family);
7619 }
7620 if (oldPrivate->subfamily != NULL) {
7621 newPrivate->subfamily = CFRetain(oldPrivate->subfamily);
7622 }
7623 if (oldPrivate->usb.name != NULL) {
7624 newPrivate->usb.name = CFRetain(oldPrivate->usb.name);
7625 }
7626 if (oldPrivate->usb.vid != NULL) {
7627 newPrivate->usb.vid = CFRetain(oldPrivate->usb.vid);
7628 }
7629 if (oldPrivate->usb.pid != NULL) {
7630 newPrivate->usb.pid = CFRetain(oldPrivate->usb.pid);
7631 }
7632 newPrivate->sort_order = oldPrivate->sort_order;
7633
7634 newPrivate->supportsBond = oldPrivate->supportsBond;
7635 if (oldPrivate->bond.interfaces != NULL) {
7636 newPrivate->bond.interfaces = CFRetain(oldPrivate->bond.interfaces);
7637 }
7638 if (oldPrivate->bond.mode != NULL) {
7639 newPrivate->bond.mode = CFRetain(oldPrivate->bond.mode);
7640 }
7641 if (oldPrivate->bond.options != NULL) {
7642 newPrivate->bond.options = CFRetain(oldPrivate->bond.options);
7643 }
7644
7645 newPrivate->supportsBridge = oldPrivate->supportsBridge;
7646 if (oldPrivate->bridge.interfaces != NULL) {
7647 newPrivate->bridge.interfaces = CFRetain(oldPrivate->bridge.interfaces);
7648 }
7649 if (oldPrivate->bridge.options != NULL) {
7650 newPrivate->bridge.options = CFRetain(oldPrivate->bridge.options);
7651 }
7652
7653 newPrivate->supportsVLAN = oldPrivate->supportsVLAN;
7654 if (oldPrivate->vlan.interface != NULL) {
7655 newPrivate->vlan.interface = CFRetain(oldPrivate->vlan.interface);
7656 }
7657 if (oldPrivate->vlan.tag != NULL) {
7658 newPrivate->vlan.tag = CFRetain(oldPrivate->vlan.tag);
7659 }
7660 if (oldPrivate->vlan.options != NULL) {
7661 newPrivate->vlan.options = CFRetain(oldPrivate->vlan.options);
7662 }
7663
7664 return newPrivate;
7665 }
7666
7667
7668 __private_extern__
7669 CFArrayRef
7670 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface)
7671 {
7672 CFMutableArrayRef configs;
7673
7674 configs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
7675
7676 while (interface != NULL) {
7677 CFStringRef defaultType;
7678 CFMutableDictionaryRef interfaceConfiguration;
7679
7680 interfaceConfiguration = CFDictionaryCreateMutable(NULL,
7681 0,
7682 &kCFTypeDictionaryKeyCallBacks,
7683 &kCFTypeDictionaryValueCallBacks);
7684
7685 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
7686 if (defaultType != NULL) {
7687 CFDictionaryRef config;
7688 CFArrayRef extendedTypes;
7689
7690 if (set == NULL) {
7691 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType);
7692 } else {
7693 config = __SCNetworkInterfaceGetDefaultConfiguration(set, interface);
7694 }
7695 if (config == NULL) {
7696 config = (CFDictionaryRef)kCFNull;
7697 }
7698 CFDictionarySetValue(interfaceConfiguration, defaultType, config);
7699
7700 extendedTypes = extendedConfigurationTypes(interface);
7701 if (extendedTypes != NULL) {
7702 CFIndex i;
7703 CFIndex n;
7704
7705 n = CFArrayGetCount(extendedTypes);
7706 for (i = 0; i < n; i++) {
7707 CFStringRef extendedType;
7708
7709 extendedType = CFArrayGetValueAtIndex(extendedTypes, i);
7710 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType);
7711 if (config == NULL) {
7712 config = (CFDictionaryRef)kCFNull;
7713 }
7714 CFDictionarySetValue(interfaceConfiguration, extendedType, config);
7715 }
7716
7717 CFRelease(extendedTypes);
7718 }
7719 }
7720
7721 CFArrayAppendValue(configs, interfaceConfiguration);
7722 CFRelease(interfaceConfiguration);
7723
7724 interface = SCNetworkInterfaceGetInterface(interface);
7725 }
7726
7727 return configs;
7728 }
7729
7730
7731 __private_extern__ Boolean
7732 __SCNetworkInterfaceIsMember(SCPreferencesRef prefs, SCNetworkInterfaceRef interface)
7733 {
7734 CFArrayRef interfaces;
7735 Boolean match = FALSE;
7736 CFMutableSetRef members;
7737
7738 members = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
7739
7740 #if !TARGET_OS_IPHONE
7741 // add Bond [member] interfaces
7742 interfaces = SCBondInterfaceCopyAll(prefs);
7743 if (interfaces != NULL) {
7744 __SCBondInterfaceListCollectMembers(interfaces, members);
7745 CFRelease(interfaces);
7746 }
7747 #endif // !TARGET_OS_IPHONE
7748
7749 // add Bridge [member] interfaces
7750 interfaces = SCBridgeInterfaceCopyAll(prefs);
7751 if (interfaces != NULL) {
7752 __SCBridgeInterfaceListCollectMembers(interfaces, members);
7753 CFRelease(interfaces);
7754 }
7755
7756 if (CFSetGetCount(members) == 0) {
7757 goto done;
7758 }
7759
7760 while (interface != NULL) {
7761 match = CFSetContainsValue(members, interface);
7762 if (match) {
7763 // if the interface is a member of an
7764 // Ethernet Bond or Bridge
7765 break;
7766 }
7767
7768 interface = SCNetworkInterfaceGetInterface(interface);
7769 }
7770
7771 done :
7772
7773 CFRelease(members);
7774 return match;
7775 }
7776
7777
7778 __private_extern__
7779 void
7780 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface, CFArrayRef configs)
7781 {
7782 CFIndex i;
7783
7784 for (i = 0; interface != NULL; i++) {
7785 CFStringRef defaultType;
7786 CFDictionaryRef interfaceConfiguration;
7787 Boolean ok;
7788
7789 interfaceConfiguration = (configs != NULL) ? CFArrayGetValueAtIndex(configs, i) : NULL;
7790
7791 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
7792 if (defaultType != NULL) {
7793 CFDictionaryRef config;
7794 CFArrayRef extendedTypes;
7795
7796 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, defaultType)
7797 : NULL;
7798 if (config == (CFDictionaryRef)kCFNull) {
7799 config = NULL;
7800 }
7801 if (set == NULL) {
7802 // if service is not associated with the set
7803 ok = __SCNetworkInterfaceSetConfiguration(interface, defaultType, config, TRUE);
7804 } else {
7805 // apply default configuration to this set
7806 ok = __SCNetworkInterfaceSetDefaultConfiguration(set, interface, defaultType, config, TRUE);
7807 }
7808 if (ok) {
7809 SC_log(LOG_DEBUG, "__SCNetworkInterfaceSetDeepConfiguration(): %@, %@ -> %@",
7810 interface,
7811 defaultType,
7812 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL"));
7813 } else {
7814 SC_log(LOG_INFO, "__SCNetworkInterfaceSetDeepConfiguration() failed, interface=%@, type=%@",
7815 interface,
7816 defaultType);
7817 }
7818
7819 extendedTypes = extendedConfigurationTypes(interface);
7820 if (extendedTypes != NULL) {
7821 CFIndex j;
7822 CFIndex n;
7823
7824 n = CFArrayGetCount(extendedTypes);
7825 for (j = 0; j < n; j++) {
7826 CFStringRef extendedType;
7827
7828 extendedType = CFArrayGetValueAtIndex(extendedTypes, j);
7829 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, extendedType)
7830 : NULL;
7831 if (config == (CFDictionaryRef)kCFNull) {
7832 config = NULL;
7833 }
7834 ok = __SCNetworkInterfaceSetConfiguration(interface, extendedType, config, TRUE);
7835 if (ok) {
7836 SC_log(LOG_DEBUG, "__SCNetworkInterfaceSetDeepConfiguration(): %@, %@ -> %@",
7837 interface,
7838 extendedType,
7839 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL"));
7840 } else {
7841 SC_log(LOG_INFO, "__SCNetworkInterfaceSetDeepConfiguration() failed, interface=%@, type=%@",
7842 interface,
7843 extendedType);
7844 }
7845 }
7846
7847 CFRelease(extendedTypes);
7848 }
7849 }
7850
7851 interface = SCNetworkInterfaceGetInterface(interface);
7852 }
7853
7854 return;
7855 }
7856
7857
7858 SCNetworkInterfaceRef
7859 _SCNetworkInterfaceCopyActive(SCDynamicStoreRef store, CFStringRef bsdName)
7860 {
7861 SCNetworkInterfaceRef interface;
7862
7863 interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeAllVirtualInterfaces);
7864 if (interface == NULL) {
7865 return NULL;
7866 }
7867
7868 if (store != NULL) {
7869 SCNetworkInterfacePrivateRef interfacePrivate =
7870 (SCNetworkInterfacePrivateRef)interface;
7871
7872 CFRetain(store);
7873 interfacePrivate->store = store;
7874 }
7875
7876 return interface;
7877 }
7878
7879
7880 #if !TARGET_OS_SIMULATOR
7881 SCNetworkServicePrimaryRank
7882 SCNetworkInterfaceGetPrimaryRank(SCNetworkInterfaceRef interface)
7883 {
7884 IPMonitorControlRef control;
7885 SCNetworkInterfacePrivateRef interfacePrivate =
7886 (SCNetworkInterfacePrivateRef)interface;
7887 SCNetworkServicePrimaryRank rank = kSCNetworkServicePrimaryRankDefault;
7888
7889 control = interfacePrivate->IPMonitorControl;
7890 if (control != NULL) {
7891 CFStringRef ifName;
7892
7893 ifName = SCNetworkInterfaceGetBSDName(interface);
7894 if (ifName != NULL) {
7895 rank = IPMonitorControlGetInterfacePrimaryRank(control,
7896 ifName);
7897 }
7898 else {
7899 _SCErrorSet(kSCStatusInvalidArgument);
7900 }
7901 }
7902 return rank;
7903 }
7904
7905 Boolean
7906 SCNetworkInterfaceSetPrimaryRank(SCNetworkInterfaceRef interface,
7907 SCNetworkServicePrimaryRank newRank)
7908 {
7909 IPMonitorControlRef control;
7910 SCNetworkInterfacePrivateRef interfacePrivate =
7911 (SCNetworkInterfacePrivateRef)interface;
7912 CFStringRef ifName;
7913
7914 ifName = SCNetworkInterfaceGetBSDName(interface);
7915 if (ifName == NULL) {
7916 _SCErrorSet(kSCStatusInvalidArgument);
7917 return (FALSE);
7918 }
7919 control = interfacePrivate->IPMonitorControl;
7920 if (control == NULL) {
7921 control = IPMonitorControlCreate();
7922 if (control == NULL) {
7923 _SCErrorSet(kSCStatusFailed);
7924 return (FALSE);
7925 }
7926 interfacePrivate->IPMonitorControl = control;
7927 }
7928 return IPMonitorControlSetInterfacePrimaryRank(control,
7929 ifName,
7930 newRank);
7931 }
7932
7933 Boolean
7934 SCNetworkInterfaceGetDisableUntilNeeded(SCNetworkInterfaceRef interface)
7935 {
7936 Boolean disable_until_needed = FALSE;
7937 CFNumberRef disable_prop = NULL;
7938 CFIndex interfaceIndex;
7939 SCNetworkInterfacePrivateRef interfacePrivate
7940 = (SCNetworkInterfacePrivateRef)interface;
7941 CFArrayRef path_list;
7942
7943 if (interfacePrivate->prefs == NULL) {
7944 _SCErrorSet(kSCStatusInvalidArgument);
7945 return (FALSE);
7946 }
7947 interfaceIndex = findPerInterfaceConfiguration(interface);
7948 if (interfaceIndex == kCFNotFound) {
7949 _SCErrorSet(kSCStatusInvalidArgument);
7950 return (FALSE);
7951 }
7952 path_list = copyPerInterfaceConfigurationPaths(interfacePrivate, NULL);
7953 if (path_list != NULL) {
7954 CFDictionaryRef config;
7955 CFStringRef path = CFArrayGetValueAtIndex(path_list, 0);
7956
7957 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
7958 CFRelease(path_list);
7959 if (config != NULL) {
7960 int disable = 0;
7961
7962 disable_prop = CFDictionaryGetValue(config, kSCPropDisableUntilNeeded);
7963 disable_prop = isA_CFNumber(disable_prop);
7964 if (disable_prop != NULL) {
7965 if (CFNumberGetValue(disable_prop, kCFNumberIntType, &disable)) {
7966 disable_until_needed = (disable != 0) ? TRUE : FALSE;
7967 }
7968 else {
7969 /* invalid property, ignore it */
7970 disable_prop = NULL;
7971 }
7972 }
7973 }
7974 }
7975 if (disable_prop == NULL) {
7976 disable_until_needed
7977 = _SCNetworkInterfaceIsTethered(interface);
7978 }
7979 _SCErrorSet(kSCStatusOK);
7980 return (disable_until_needed);
7981 }
7982
7983 Boolean
7984 __SCNetworkInterfaceSetDisableUntilNeededValue(SCNetworkInterfaceRef interface, CFTypeRef disable)
7985 {
7986 CFIndex count;
7987 CFIndex i;
7988 CFIndex interfaceIndex;
7989 SCNetworkInterfacePrivateRef interfacePrivate
7990 = (SCNetworkInterfacePrivateRef)interface;
7991 Boolean ok = TRUE;
7992 CFArrayRef path_list;
7993
7994 if (interfacePrivate->prefs == NULL) {
7995 _SCErrorSet(kSCStatusInvalidArgument);
7996 return (FALSE);
7997 }
7998 if ((disable != NULL) && !isA_CFNumber(disable)) {
7999 _SCErrorSet(kSCStatusInvalidArgument);
8000 return (FALSE);
8001 }
8002 interfaceIndex = findPerInterfaceConfiguration(interface);
8003 if (interfaceIndex == kCFNotFound) {
8004 _SCErrorSet(kSCStatusInvalidArgument);
8005 return (FALSE);
8006 }
8007 path_list = copyPerInterfaceConfigurationPaths(interfacePrivate, NULL);
8008 if (path_list == NULL) {
8009 _SCErrorSet(kSCStatusInvalidArgument);
8010 return (FALSE);
8011 }
8012 count = CFArrayGetCount(path_list);
8013 for (i = 0; i < count; i++) {
8014 CFDictionaryRef config;
8015 CFMutableDictionaryRef new_config;
8016 CFStringRef path = CFArrayGetValueAtIndex(path_list, i);
8017
8018 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
8019 if (config != NULL) {
8020 new_config
8021 = CFDictionaryCreateMutableCopy(NULL, 0, config);
8022 } else {
8023 new_config
8024 = CFDictionaryCreateMutable(NULL, 0,
8025 &kCFTypeDictionaryKeyCallBacks,
8026 &kCFTypeDictionaryValueCallBacks);
8027 }
8028 if (disable != NULL) {
8029 CFDictionarySetValue(new_config, kSCPropDisableUntilNeeded, disable);
8030 } else {
8031 CFDictionaryRemoveValue(new_config, kSCPropDisableUntilNeeded);
8032 }
8033 ok = __setPrefsConfiguration(interfacePrivate->prefs,
8034 path,
8035 (CFDictionaryGetCount(new_config) > 0) ? new_config : NULL,
8036 FALSE);
8037 CFRelease(new_config);
8038 if (!ok) {
8039 break;
8040 }
8041 }
8042 CFRelease(path_list);
8043 return (ok);
8044 }
8045
8046 Boolean
8047 SCNetworkInterfaceSetDisableUntilNeeded(SCNetworkInterfaceRef interface, Boolean disable)
8048 {
8049 Boolean ok;
8050 const int one = 1;
8051 CFNumberRef num;
8052 const int zero = 0;
8053
8054 num = CFNumberCreate(NULL, kCFNumberIntType, disable ? &one : &zero);
8055 ok = __SCNetworkInterfaceSetDisableUntilNeededValue(interface, num);
8056 CFRelease(num);
8057
8058 return ok;
8059 }
8060
8061 #else // !TARGET_OS_SIMULATOR
8062
8063 SCNetworkServicePrimaryRank
8064 SCNetworkInterfaceGetPrimaryRank(SCNetworkInterfaceRef interface)
8065 {
8066 #pragma unused(interface)
8067 return (kSCNetworkServicePrimaryRankDefault);
8068 }
8069
8070 Boolean
8071 SCNetworkInterfaceSetPrimaryRank(SCNetworkInterfaceRef interface,
8072 SCNetworkServicePrimaryRank newRank)
8073 {
8074 #pragma unused(interface)
8075 #pragma unused(newRank)
8076 _SCErrorSet(kSCStatusInvalidArgument);
8077 return (FALSE);
8078 }
8079
8080 Boolean
8081 SCNetworkInterfaceGetDisableUntilNeeded(SCNetworkInterfaceRef interface)
8082 {
8083 #pragma unused(interface)
8084 return (FALSE);
8085 }
8086
8087 Boolean
8088 __SCNetworkInterfaceSetDisableUntilNeededValue(SCNetworkInterfaceRef interface, CFTypeRef disable)
8089 {
8090 #pragma unused(interface)
8091 #pragma unused(disable)
8092 return (FALSE);
8093 }
8094
8095 Boolean
8096 SCNetworkInterfaceSetDisableUntilNeeded(SCNetworkInterfaceRef interface, Boolean disable)
8097 {
8098 #pragma unused(interface)
8099 #pragma unused(disable)
8100 _SCErrorSet(kSCStatusInvalidArgument);
8101 return (FALSE);
8102 }
8103
8104 #endif // !TARGET_OS_SIMULATOR
8105
8106
8107 __private_extern__
8108 CFArrayRef // SCNetworkInterfaceRef
8109 __SCNetworkInterfaceCopyStoredWithPreferences(SCPreferencesRef ni_prefs)
8110 {
8111 CFStringRef defaultNetworkInterfacePath = NULL;
8112 CFArrayRef if_list;
8113 CFMutableArrayRef interfaceList = NULL;
8114 SCNetworkInterfaceRef interfaceNamer = NULL;
8115
8116 /* initialize runtime */
8117 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
8118
8119 if (ni_prefs == NULL) {
8120 defaultNetworkInterfacePath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), PREFS_DEFAULT_DIR, NETWORK_INTERFACES_PREFS);
8121 assert(defaultNetworkInterfacePath != NULL);
8122 ni_prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), defaultNetworkInterfacePath);
8123 }
8124
8125 if_list = SCPreferencesGetValue(ni_prefs, INTERFACES);
8126 if (isA_CFArray(if_list)) {
8127 CFIndex i;
8128 CFIndex n = CFArrayGetCount(if_list);
8129
8130 interfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
8131 for (i = 0; i < n; i++) {
8132 CFDictionaryRef dict;
8133
8134 dict = CFArrayGetValueAtIndex(if_list, i);
8135 if (isA_CFDictionary(dict) != NULL) {
8136 interfaceNamer = __SCNetworkInterfaceCreateWithStorageEntity(NULL, dict);
8137
8138 if (interfaceNamer != NULL) {
8139 CFArrayAppendValue(interfaceList, interfaceNamer);
8140 CFRelease(interfaceNamer);
8141 }
8142 }
8143 }
8144 }
8145
8146 if (defaultNetworkInterfacePath != NULL) {
8147 CFRelease(defaultNetworkInterfacePath);
8148 // prefs were created in the function, and hence need to be released
8149 CFRelease(ni_prefs);
8150 }
8151 return interfaceList;
8152 }
8153
8154
8155 __private_extern__
8156 Boolean
8157 __SCNetworkInterfaceSaveStoredWithPreferences(SCPreferencesRef prefs, CFArrayRef interfacesToSave)
8158 {
8159 CFStringRef defaultNetworkInterfacePath = NULL;
8160 Boolean success = FALSE;
8161
8162 if (prefs == NULL) { // TODO: Get the default preferences on the system
8163 defaultNetworkInterfacePath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), PREFS_DEFAULT_DIR, NETWORK_INTERFACES_PREFS);
8164 assert(defaultNetworkInterfacePath != NULL);
8165 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), defaultNetworkInterfacePath);
8166 }
8167
8168 if (isA_CFArray(interfacesToSave) == NULL) {
8169 SC_log(LOG_INFO, "No interfaces to save");
8170 goto done;
8171 }
8172 SCPreferencesSetValue(prefs, INTERFACES, interfacesToSave);
8173 success = TRUE;
8174 done:
8175 if (defaultNetworkInterfacePath != NULL) {
8176 CFRelease(defaultNetworkInterfacePath);
8177 // prefs were created in the function, and hence need to be released
8178 CFRelease(prefs);
8179 }
8180
8181 return success;
8182 }
8183
8184 __private_extern__
8185 SCNetworkInterfaceRef
8186 __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(CFAllocatorRef allocator, SCPreferencesRef ni_prefs, CFStringRef bsdName)
8187 {
8188 CFArrayRef if_list;
8189 SCNetworkInterfaceRef interface = NULL;
8190 CFStringRef defaultNetworkInterfacePath;
8191
8192 /* initialize runtime */
8193 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
8194
8195 if (ni_prefs == NULL) {
8196 defaultNetworkInterfacePath = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@"), PREFS_DEFAULT_DIR, NETWORK_INTERFACES_PREFS);
8197 ni_prefs = SCPreferencesCreate(allocator, CFSTR("SCNetworkInterface"), defaultNetworkInterfacePath);
8198 CFRelease(defaultNetworkInterfacePath);
8199 }
8200 else {
8201 CFRetain(ni_prefs);
8202 }
8203
8204 if_list = SCPreferencesGetValue(ni_prefs, INTERFACES);
8205
8206 if (isA_CFArray(if_list) != NULL) {
8207 CFIndex idx;
8208 CFIndex count = CFArrayGetCount(if_list);
8209
8210 for (idx = 0; idx < count; idx++) {
8211 CFDictionaryRef dict;
8212 CFStringRef tmp_bsdName;
8213
8214 dict = CFArrayGetValueAtIndex(if_list, idx);
8215 if (isA_CFDictionary(dict) == NULL) {
8216 continue;
8217 }
8218
8219 tmp_bsdName = CFDictionaryGetValue(dict, CFSTR(kSCNetworkInterfaceBSDName));
8220 if (tmp_bsdName == NULL) {
8221 continue;
8222 }
8223 if (CFEqual(bsdName, tmp_bsdName)) {
8224 interface = __SCNetworkInterfaceCreateWithStorageEntity(allocator, dict);
8225 break;
8226 }
8227 }
8228 }
8229
8230 CFRelease(ni_prefs);
8231 return interface;
8232 }
8233
8234 __private_extern__
8235 CFDictionaryRef
8236 __SCNetworkInterfaceCreateMappingUsingBSDName(CFArrayRef interfaces)
8237 {
8238 CFMutableDictionaryRef mappingBSDToInterface = NULL;
8239 CFStringRef bsdName = NULL;
8240 SCNetworkInterfaceRef interface = NULL;
8241 CFIndex count;
8242
8243 count = CFArrayGetCount(interfaces);
8244 if (count == 0) {
8245 SC_log(LOG_INFO, "No interfaces");
8246 return NULL;
8247 }
8248 mappingBSDToInterface = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
8249
8250 for (CFIndex idx = 0; idx < count; idx++) {
8251 interface = (SCNetworkInterfaceRef) CFArrayGetValueAtIndex(interfaces, idx);
8252
8253 bsdName = SCNetworkInterfaceGetBSDName(interface);
8254 if (isA_CFString(bsdName) == NULL) {
8255 SC_log(LOG_INFO, "No BSD name");
8256 continue;
8257 }
8258 CFDictionaryAddValue(mappingBSDToInterface, bsdName, interface);
8259 }
8260 if (CFDictionaryGetCount(mappingBSDToInterface) == 0) {
8261 CFRelease(mappingBSDToInterface);
8262 mappingBSDToInterface = NULL;
8263 SC_log(LOG_INFO, "No mappings");
8264 }
8265
8266 return mappingBSDToInterface;
8267 }
8268
8269 __private_extern__ Boolean
8270 __SCNetworkInterfaceEntityIsPPTP(CFDictionaryRef entity)
8271 {
8272 CFStringRef intfSubtype;
8273
8274 if (entity == NULL) {
8275 return FALSE;
8276 }
8277
8278 intfSubtype = CFDictionaryGetValue(entity, kSCPropNetInterfaceSubType);
8279 #pragma GCC diagnostic push
8280 #pragma GCC diagnostic ignored "-Wdeprecated"
8281 if (intfSubtype != NULL && CFEqual(intfSubtype, kSCValNetInterfaceSubTypePPTP)) {
8282 return TRUE;
8283 }
8284 #pragma GCC diagnostic pop
8285
8286 return FALSE;
8287 }