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