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