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