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