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