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