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