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