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