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