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