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