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