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