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