]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkInterface.c
configd-210.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkInterface.c
1 /*
2 * Copyright (c) 2004-2007 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 <CoreFoundation/CoreFoundation.h>
37 #include <CoreFoundation/CFRuntime.h>
38 #include <SystemConfiguration/SystemConfiguration.h>
39 #include "SCNetworkConfigurationInternal.h"
40 #include <SystemConfiguration/SCValidation.h>
41 #include <SystemConfiguration/SCPrivate.h>
42 #include <SystemConfiguration/BondConfiguration.h>
43 #include <SystemConfiguration/VLANConfiguration.h>
44 #include "SCPreferencesInternal.h"
45 #include "SCHelper_client.h"
46
47 #include <EAP8021X/EAPClientProperties.h>
48
49 #include <IOKit/IOKitLib.h>
50 #include <IOKit/IOCFBundle.h>
51 #include <IOKit/IOBSD.h>
52 #include <IOKit/network/IONetworkController.h>
53 #include <IOKit/network/IONetworkInterface.h>
54 #include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass
55 #include <IOKit/serial/IOSerialKeys.h>
56 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
57 #include "dy_framework.h"
58
59 #ifndef kIODeviceSupportsHoldKey
60 #define kIODeviceSupportsHoldKey "V92Modem"
61 #endif
62
63 #include <string.h>
64 #include <mach/mach.h>
65 #include <net/if.h>
66 #include <net/if_types.h>
67 #include <net/route.h>
68 #include <sys/param.h>
69 #include <sys/types.h>
70 #include <sys/socket.h>
71 #include <sys/stat.h>
72 #include <sys/sysctl.h>
73 #include <pthread.h>
74 #include <NSSystemDirectories.h>
75
76
77 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040
78 #error MAC_OS_X_VERSION_MIN_REQUIRED < 1040, Check MACOSX_DEPLOYMENT_TARGET
79 #endif
80
81
82 static CFStringRef copy_interface_string (CFBundleRef bundle, CFStringRef key, Boolean localized);
83 static CFStringRef __SCNetworkInterfaceCopyDescription (CFTypeRef cf);
84 static void __SCNetworkInterfaceDeallocate (CFTypeRef cf);
85 static Boolean __SCNetworkInterfaceEqual (CFTypeRef cf1, CFTypeRef cf2);
86 static CFHashCode __SCNetworkInterfaceHash (CFTypeRef cf);
87
88
89 enum {
90 kSortInternalModem,
91 kSortUSBModem,
92 kSortModem,
93 kSortBluetooth,
94 kSortIrDA,
95 kSortSerialPort,
96 kSortWWAN,
97 kSortEthernet,
98 kSortFireWire,
99 kSortAirPort,
100 kSortOtherWireless,
101 kSortBluetoothPAN,
102 kSortBond,
103 kSortVLAN,
104 kSortUnknown
105 };
106
107
108 const CFStringRef kSCNetworkInterfaceType6to4 = CFSTR("6to4");
109 const CFStringRef kSCNetworkInterfaceTypeBluetooth = CFSTR("Bluetooth");
110 const CFStringRef kSCNetworkInterfaceTypeBond = CFSTR("Bond");
111 const CFStringRef kSCNetworkInterfaceTypeEthernet = CFSTR("Ethernet");
112 const CFStringRef kSCNetworkInterfaceTypeFireWire = CFSTR("FireWire");
113 const CFStringRef kSCNetworkInterfaceTypeIEEE80211 = CFSTR("IEEE80211"); // IEEE 802.11, AirPort
114 const CFStringRef kSCNetworkInterfaceTypeIrDA = CFSTR("IrDA");
115 const CFStringRef kSCNetworkInterfaceTypeL2TP = CFSTR("L2TP");
116 const CFStringRef kSCNetworkInterfaceTypeModem = CFSTR("Modem");
117 const CFStringRef kSCNetworkInterfaceTypePPP = CFSTR("PPP");
118 const CFStringRef kSCNetworkInterfaceTypePPTP = CFSTR("PPTP");
119 const CFStringRef kSCNetworkInterfaceTypeSerial = CFSTR("Serial");
120 const CFStringRef kSCNetworkInterfaceTypeVLAN = CFSTR("VLAN");
121 const CFStringRef kSCNetworkInterfaceTypeWWAN = CFSTR("WWAN");
122
123 const CFStringRef kSCNetworkInterfaceTypeIPv4 = CFSTR("IPv4");
124
125 static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4 = {
126 INIT_CFRUNTIME_BASE(NULL, 0, 0x0080), // cfBase
127 NULL, // interface type
128 NULL, // name
129 NULL, // localized name
130 NULL, // localization key
131 NULL, // localization arg1
132 NULL, // localization arg2
133 NULL, // [layered] interface
134 NULL, // prefs
135 NULL, // serviceID
136 NULL, // unsaved
137 NULL, // entity_device
138 NULL, // entity_type
139 NULL, // entity_subtype
140 NULL, // supported_interface_types
141 NULL, // supported_protocol_types
142 NULL, // address
143 NULL, // addressString
144 FALSE, // builtin
145 NULL, // location
146 NULL, // path
147 NULL, // overrides
148 FALSE, // modemIsV92
149 FALSE, // supportsBond
150 FALSE, // supportsVLAN
151 NULL, // type
152 NULL, // unit
153 kSortUnknown, // sort_order
154 { NULL, NULL}, // bond { interfaces, options }
155 { NULL, NULL, NULL } // vlan { interface, tag, options }
156 };
157
158 const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4 = (SCNetworkInterfaceRef)&__kSCNetworkInterfaceIPv4;
159
160 #pragma mark -
161 #pragma mark SCNetworkInterface configuration details
162
163 #define doNone 0
164
165 #define do6to4 1<<0
166 #define doL2TP 1<<1
167 #define doPPP 1<<2
168 #define doPPTP 1<<3
169
170 #define doAppleTalk 1<<0
171 #define doDNS 1<<1
172 #define doIPv4 1<<2
173 #define doIPv6 1<<3
174 #define doProxies 1<<4
175 #define doSMB 1<<5
176
177 static const struct {
178 const CFStringRef *interface_type;
179 const CFStringRef *entity_hardware;
180 Boolean per_interface_config;
181 uint32_t supported_interfaces;
182 const CFStringRef *ppp_subtype;
183 uint32_t supported_protocols;
184 } configurations[] = {
185 // interface type entity_hardware if config? interface types PPP sub-type interface protocols
186 // ===================================== ================= ========== ======================= ======================================= =========================================
187 { &kSCNetworkInterfaceType6to4 , &kSCEntNet6to4 , FALSE, doNone, NULL, doIPv6 },
188 { &kSCNetworkInterfaceTypeBluetooth , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
189 { &kSCNetworkInterfaceTypeBond , &kSCEntNetEthernet, TRUE , doNone, NULL, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies|doSMB },
190 { &kSCNetworkInterfaceTypeEthernet , &kSCEntNetEthernet, TRUE , doPPP, &kSCValNetInterfaceSubTypePPPoE, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies|doSMB },
191 { &kSCNetworkInterfaceTypeFireWire , &kSCEntNetFireWire, TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
192 { &kSCNetworkInterfaceTypeIEEE80211 , &kSCEntNetAirPort , TRUE , doPPP, &kSCValNetInterfaceSubTypePPPoE, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies|doSMB },
193 { &kSCNetworkInterfaceTypeIrDA , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
194 { &kSCNetworkInterfaceTypeL2TP , NULL , FALSE, doPPP, &kSCValNetInterfaceSubTypeL2TP, doNone },
195 { &kSCNetworkInterfaceTypeModem , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
196 { &kSCNetworkInterfaceTypePPP , &kSCEntNetPPP , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB },
197 { &kSCNetworkInterfaceTypePPTP , NULL , FALSE, doPPP, &kSCValNetInterfaceSubTypePPTP, doNone },
198 { &kSCNetworkInterfaceTypeSerial , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
199 { &kSCNetworkInterfaceTypeVLAN , &kSCEntNetEthernet, TRUE , doNone, NULL, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies|doSMB },
200 { &kSCNetworkInterfaceTypeWWAN , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
201 // ===================================== ================= ========== ======================= ======================================= =========================================
202 { &kSCNetworkInterfaceTypeIPv4 , NULL , FALSE, do6to4|doL2TP|doPPTP, NULL, doNone }
203 };
204
205
206 #define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
207 static CFBundleRef bundle = NULL;
208
209
210 static CFTypeID __kSCNetworkInterfaceTypeID = _kCFRuntimeNotATypeID;
211
212
213 static const CFRuntimeClass __SCNetworkInterfaceClass = {
214 0, // version
215 "SCNetworkInterface", // className
216 NULL, // init
217 NULL, // copy
218 __SCNetworkInterfaceDeallocate, // dealloc
219 __SCNetworkInterfaceEqual, // equal
220 __SCNetworkInterfaceHash, // hash
221 NULL, // copyFormattingDesc
222 __SCNetworkInterfaceCopyDescription // copyDebugDesc
223 };
224
225
226 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
227 static pthread_once_t iokit_quiet = PTHREAD_ONCE_INIT;
228
229
230 static mach_port_t masterPort = MACH_PORT_NULL;
231
232
233 static CFStringRef
234 __SCNetworkInterfaceCopyDescription(CFTypeRef cf)
235 {
236 CFAllocatorRef allocator = CFGetAllocator(cf);
237 CFMutableStringRef result;
238 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
239
240 result = CFStringCreateMutable(allocator, 0);
241 CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkInterface %p [%p]> {"), cf, allocator);
242 CFStringAppendFormat(result, NULL, CFSTR("type = %@"), interfacePrivate->interface_type);
243 CFStringAppendFormat(result, NULL, CFSTR(", entity_device = %@"), interfacePrivate->entity_device);
244 CFStringAppendFormat(result, NULL, CFSTR(", entity_type = %@"), interfacePrivate->entity_type);
245 if (interfacePrivate->entity_subtype != NULL) {
246 CFStringAppendFormat(result, NULL, CFSTR(" / %@"), interfacePrivate->entity_subtype);
247 }
248 if (interfacePrivate->name != NULL) {
249 CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), interfacePrivate->name);
250 }
251 if (interfacePrivate->localized_name != NULL) {
252 CFStringAppendFormat(result, NULL, CFSTR(", name(l) = %@"), interfacePrivate->localized_name);
253 } else {
254 if (interfacePrivate->localized_key != NULL) {
255 CFStringAppendFormat(result, NULL, CFSTR(", name(k) = \"%@\""), interfacePrivate->localized_key);
256 if (interfacePrivate->localized_arg1 != NULL) {
257 CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg1);
258 }
259 if (interfacePrivate->localized_arg2 != NULL) {
260 CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg2);
261 }
262 }
263 }
264 if (interfacePrivate->address != NULL) {
265 const uint8_t *data;
266 CFIndex dataLen;
267 CFIndex i;
268
269 CFStringAppendFormat(result, NULL, CFSTR(", address = 0x"));
270
271 data = CFDataGetBytePtr(interfacePrivate->address);
272 dataLen = CFDataGetLength(interfacePrivate->address);
273 for (i = 0; i < dataLen; i++) {
274 CFStringAppendFormat(result, NULL, CFSTR("%02x"), data[i]);
275 }
276 }
277 CFStringAppendFormat(result, NULL, CFSTR(", builtin = %s"), interfacePrivate->builtin ? "TRUE" : "FALSE");
278 if (interfacePrivate->modemIsV92) {
279 CFStringAppendFormat(result, NULL, CFSTR(", v.92"));
280 }
281 if (interfacePrivate->location != NULL) {
282 CFStringAppendFormat(result, NULL, CFSTR(", location = %@"), interfacePrivate->location);
283 }
284 if (interfacePrivate->type != NULL) {
285 CFStringAppendFormat(result, NULL, CFSTR(", type = %@"), interfacePrivate->type);
286 }
287 if (interfacePrivate->unit != NULL) {
288 CFStringAppendFormat(result, NULL, CFSTR(", unit = %@"), interfacePrivate->unit);
289 }
290 if (interfacePrivate->path != NULL) {
291 CFStringAppendFormat(result, NULL, CFSTR(", path = %@"), interfacePrivate->path);
292 }
293 if (interfacePrivate->overrides != NULL) {
294 CFStringAppendFormat(result, NULL, CFSTR(", overrides = %p"), interfacePrivate->overrides);
295 }
296 CFStringAppendFormat(result, NULL, CFSTR(", order = %d"), interfacePrivate->sort_order);
297 if (interfacePrivate->prefs != NULL) {
298 CFStringAppendFormat(result, NULL, CFSTR(", prefs = %p"), interfacePrivate->prefs);
299 }
300 if (interfacePrivate->serviceID != NULL) {
301 CFStringAppendFormat(result, NULL, CFSTR(", service = %@"), interfacePrivate->serviceID);
302 }
303 if (interfacePrivate->interface != NULL) {
304 CFStringAppendFormat(result, NULL, CFSTR(", interface = %@"), interfacePrivate->interface);
305 }
306 if (interfacePrivate->unsaved != NULL) {
307 CFStringAppendFormat(result, NULL, CFSTR(", unsaved = %@"), interfacePrivate->unsaved);
308 }
309 if (interfacePrivate->bond.interfaces != NULL) {
310 CFIndex i;
311 CFIndex n;
312
313 n = CFArrayGetCount(interfacePrivate->bond.interfaces);
314 for (i = 0; i < n; i++) {
315 SCNetworkInterfaceRef member;
316
317 member = CFArrayGetValueAtIndex(interfacePrivate->bond.interfaces, i);
318 CFStringAppendFormat(result, NULL,
319 CFSTR("%s%@"),
320 (i == 0) ? ", interfaces = " : ", ",
321 SCNetworkInterfaceGetBSDName(member));
322 }
323 }
324 if (interfacePrivate->bond.mode != NULL) {
325 CFStringAppendFormat(result, NULL, CFSTR(", mode = %@"), interfacePrivate->bond.mode);
326 }
327 if (interfacePrivate->bond.options != NULL) {
328 CFStringAppendFormat(result, NULL, CFSTR(", options = %@"), interfacePrivate->bond.options);
329 }
330 if (interfacePrivate->bond.mode != NULL) {
331 CFStringAppendFormat(result, NULL, CFSTR(", mode = %@"), interfacePrivate->bond.mode);
332 }
333 if (interfacePrivate->vlan.interface != NULL) {
334 CFStringAppendFormat(result, NULL,
335 CFSTR(", interface = %@"),
336 SCNetworkInterfaceGetBSDName(interfacePrivate->vlan.interface));
337 }
338 if (interfacePrivate->vlan.tag != NULL) {
339 CFStringAppendFormat(result, NULL, CFSTR(", tag = %@"), interfacePrivate->vlan.tag);
340 }
341 if (interfacePrivate->vlan.options != NULL) {
342 CFStringAppendFormat(result, NULL, CFSTR(", options = %@"), interfacePrivate->vlan.options);
343 }
344 CFStringAppendFormat(result, NULL, CFSTR("}"));
345
346 return result;
347 }
348
349
350 static void
351 __SCNetworkInterfaceDeallocate(CFTypeRef cf)
352 {
353 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
354
355 /* release resources */
356
357 if (interfacePrivate->interface != NULL)
358 CFRelease(interfacePrivate->interface);
359
360 if (interfacePrivate->name != NULL)
361 CFRelease(interfacePrivate->name);
362
363 if (interfacePrivate->localized_name != NULL)
364 CFRelease(interfacePrivate->localized_name);
365
366 if (interfacePrivate->localized_arg1 != NULL)
367 CFRelease(interfacePrivate->localized_arg1);
368
369 if (interfacePrivate->localized_arg2 != NULL)
370 CFRelease(interfacePrivate->localized_arg2);
371
372 if (interfacePrivate->prefs != NULL)
373 CFRelease(interfacePrivate->prefs);
374
375 if (interfacePrivate->serviceID != NULL)
376 CFRelease(interfacePrivate->serviceID);
377
378 if (interfacePrivate->unsaved != NULL)
379 CFRelease(interfacePrivate->unsaved);
380
381 if (interfacePrivate->entity_device != NULL)
382 CFRelease(interfacePrivate->entity_device);
383
384 if (interfacePrivate->supported_interface_types != NULL)
385 CFRelease(interfacePrivate->supported_interface_types);
386
387 if (interfacePrivate->supported_protocol_types != NULL)
388 CFRelease(interfacePrivate->supported_protocol_types);
389
390 if (interfacePrivate->address != NULL)
391 CFRelease(interfacePrivate->address);
392
393 if (interfacePrivate->addressString != NULL)
394 CFRelease(interfacePrivate->addressString);
395
396 if (interfacePrivate->location != NULL)
397 CFRelease(interfacePrivate->location);
398
399 if (interfacePrivate->path != NULL)
400 CFRelease(interfacePrivate->path);
401
402 if (interfacePrivate->overrides != NULL)
403 CFRelease(interfacePrivate->overrides);
404
405 if (interfacePrivate->type != NULL)
406 CFRelease(interfacePrivate->type);
407
408 if (interfacePrivate->unit != NULL)
409 CFRelease(interfacePrivate->unit);
410
411 if (interfacePrivate->bond.interfaces != NULL)
412 CFRelease(interfacePrivate->bond.interfaces);
413
414 if (interfacePrivate->bond.mode != NULL)
415 CFRelease(interfacePrivate->bond.mode);
416
417 if (interfacePrivate->bond.options != NULL)
418 CFRelease(interfacePrivate->bond.options);
419
420 if (interfacePrivate->vlan.interface != NULL)
421 CFRelease(interfacePrivate->vlan.interface);
422
423 if (interfacePrivate->vlan.tag != NULL)
424 CFRelease(interfacePrivate->vlan.tag);
425
426 if (interfacePrivate->vlan.options != NULL)
427 CFRelease(interfacePrivate->vlan.options);
428
429 return;
430 }
431
432
433 static Boolean
434 __SCNetworkInterfaceEqual(CFTypeRef cf1, CFTypeRef cf2)
435 {
436 SCNetworkInterfacePrivateRef if1 = (SCNetworkInterfacePrivateRef)cf1;
437 SCNetworkInterfacePrivateRef if2 = (SCNetworkInterfacePrivateRef)cf2;
438
439 if (if1 == if2)
440 return TRUE;
441
442 if (!CFEqual(if1->interface_type, if2->interface_type)) {
443 return FALSE; // if not the same interface type
444 }
445
446 if (!_SC_CFEqual(if1->entity_device, if2->entity_device)) {
447 return FALSE; // if not the same device
448 }
449
450 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeBond)) {
451 if (!_SC_CFEqual(if1->bond.interfaces, if2->bond.interfaces)) {
452 return FALSE; // if not the same interfaces
453 }
454 if (!_SC_CFEqual(if1->bond.mode, if2->bond.mode)) {
455 return FALSE; // if not the same mode
456 }
457 }
458
459 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeVLAN)) {
460 if (!_SC_CFEqual(if1->vlan.interface, if2->vlan.interface)) {
461 return FALSE; // if not the same physical interface
462 }
463 if (!_SC_CFEqual(if1->vlan.tag, if2->vlan.tag)) {
464 return FALSE; // if not the same tag
465 }
466 }
467
468 if (!CFEqual(if1->interface, if2->interface)) {
469 return FALSE; // if not the same layering
470 }
471
472 return TRUE;
473 }
474
475
476 static CFHashCode
477 __SCNetworkInterfaceHash(CFTypeRef cf)
478 {
479 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
480
481 if (interfacePrivate->entity_device != NULL) {
482 return CFHash(interfacePrivate->entity_device);
483 }
484
485 return 0;
486 }
487
488
489 static void
490 __SCNetworkInterfaceInitialize(void)
491 {
492 kern_return_t kr;
493
494 // register w/CF
495 __kSCNetworkInterfaceTypeID = _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass);
496
497 // initialize __kSCNetworkInterfaceIPv4
498 _CFRuntimeSetInstanceTypeID(&__kSCNetworkInterfaceIPv4, __kSCNetworkInterfaceTypeID);
499 __kSCNetworkInterfaceIPv4.interface_type = kSCNetworkInterfaceTypeIPv4;
500 __kSCNetworkInterfaceIPv4.localized_key = CFSTR("ipv4");
501
502 // get CFBundleRef for SystemConfiguration.framework
503 bundle = _SC_CFBundleGet();
504
505 // get mach port used to communication with IOKit
506 kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
507 if (kr != KERN_SUCCESS) {
508 SCLog(TRUE, LOG_DEBUG,
509 CFSTR("__SCNetworkInterfaceInitialize(), could not get IOMasterPort, kr = 0x%x"),
510 kr);
511 }
512
513 return;
514 }
515
516
517 __private_extern__
518 SCNetworkInterfacePrivateRef
519 __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator,
520 SCNetworkInterfaceRef interface,
521 SCPreferencesRef prefs,
522 CFStringRef serviceID,
523 io_string_t path)
524 {
525 SCNetworkInterfacePrivateRef interfacePrivate;
526 uint32_t size;
527
528 /* initialize runtime */
529 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
530
531 /* allocate target */
532 size = sizeof(SCNetworkInterfacePrivate) - sizeof(CFRuntimeBase);
533 interfacePrivate = (SCNetworkInterfacePrivateRef)_CFRuntimeCreateInstance(allocator,
534 __kSCNetworkInterfaceTypeID,
535 size,
536 NULL);
537 if (interfacePrivate == NULL) {
538 return NULL;
539 }
540
541 interfacePrivate->interface_type = NULL;
542 interfacePrivate->name = NULL;
543 interfacePrivate->localized_name = NULL;
544 interfacePrivate->localized_key = NULL;
545 interfacePrivate->localized_arg1 = NULL;
546 interfacePrivate->localized_arg2 = NULL;
547 interfacePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL;
548 interfacePrivate->prefs = (prefs != NULL) ? CFRetain(prefs) : NULL;
549 interfacePrivate->serviceID = (serviceID != NULL) ? CFRetain(serviceID) : NULL;
550 interfacePrivate->unsaved = NULL;
551 interfacePrivate->entity_device = NULL;
552 interfacePrivate->entity_type = NULL;
553 interfacePrivate->entity_subtype = NULL;
554 interfacePrivate->supported_interface_types = NULL;
555 interfacePrivate->supported_protocol_types = NULL;
556 interfacePrivate->address = NULL;
557 interfacePrivate->addressString = NULL;
558 interfacePrivate->builtin = FALSE;
559 interfacePrivate->path = (path != NULL) ? CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8)
560 : NULL;
561 interfacePrivate->location = NULL;
562 interfacePrivate->overrides = NULL;
563 interfacePrivate->modemIsV92 = FALSE;
564 interfacePrivate->supportsBond = FALSE;
565 interfacePrivate->supportsVLAN = FALSE;
566 interfacePrivate->type = NULL;
567 interfacePrivate->unit = NULL;
568 interfacePrivate->sort_order = kSortUnknown;
569 interfacePrivate->bond.interfaces = NULL;
570 interfacePrivate->bond.mode = NULL;
571 interfacePrivate->bond.options = NULL;
572 interfacePrivate->vlan.interface = NULL;
573 interfacePrivate->vlan.tag = NULL;
574 interfacePrivate->vlan.options = NULL;
575
576 return interfacePrivate;
577 }
578
579
580 __private_extern__
581 Boolean
582 __SCNetworkInterfaceSupportsVLAN(CFStringRef bsd_if)
583 {
584 char * buf = NULL;
585 size_t buf_len = 0;
586 struct if_msghdr * ifm;
587 char * if_name = NULL;
588 unsigned int if_index;
589 int mib[6];
590 Boolean vlanOK = FALSE;
591
592 // get the interface index
593 if_name = _SC_cfstring_to_cstring(bsd_if, NULL, 0, kCFStringEncodingASCII);
594 if (if_name == NULL) {
595 return FALSE; // if conversion error
596 }
597 if_index = if_nametoindex(if_name);
598 if (if_index == 0) {
599 goto done; // if unknown interface
600 }
601
602 // get information for the specified interface
603 mib[0] = CTL_NET;
604 mib[1] = PF_ROUTE;
605 mib[2] = 0;
606 mib[3] = AF_LINK;
607 mib[4] = NET_RT_IFLIST;
608 mib[5] = if_index; /* ask for exactly one interface */
609
610 if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) == -1) {
611 SCLog(TRUE, LOG_ERR, CFSTR("sysctl() size failed: %s"), strerror(errno));
612 goto done;
613 }
614 buf = CFAllocatorAllocate(NULL, buf_len, 0);
615 if (sysctl(mib, 6, buf, &buf_len, NULL, 0) == -1) {
616 SCLog(TRUE, LOG_ERR, CFSTR("sysctl() failed: %s"), strerror(errno));
617 goto done;
618 }
619
620 // check the link type and hwassist flags
621 ifm = (struct if_msghdr *)buf;
622 switch (ifm->ifm_type) {
623 case RTM_IFINFO : {
624 #if defined(IF_HWASSIST_VLAN_TAGGING) && defined(IF_HWASSIST_VLAN_MTU)
625 struct if_data *if_data = &ifm->ifm_data;
626
627 if (if_data->ifi_hwassist & (IF_HWASSIST_VLAN_TAGGING | IF_HWASSIST_VLAN_MTU)) {
628 vlanOK = TRUE;
629 }
630 #endif
631 break;
632 }
633 }
634
635 done :
636
637 if (if_name != NULL) CFAllocatorDeallocate(NULL, if_name);
638 if (buf != NULL) CFAllocatorDeallocate(NULL, buf);
639
640 return vlanOK;
641 }
642
643
644 __private_extern__
645 SCNetworkInterfacePrivateRef
646 _SCBondInterfaceCreatePrivate(CFAllocatorRef allocator,
647 CFStringRef bond_if)
648 {
649 SCNetworkInterfacePrivateRef interfacePrivate;
650
651 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL, NULL);
652 if (interfacePrivate == NULL) {
653 return NULL;
654 }
655
656 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBond;
657 interfacePrivate->entity_type = kSCEntNetEthernet;
658 interfacePrivate->entity_device = CFStringCreateCopy(allocator, bond_if);
659 interfacePrivate->builtin = TRUE;
660 interfacePrivate->supportsVLAN = __SCNetworkInterfaceSupportsVLAN(bond_if);
661 interfacePrivate->sort_order = kSortBond;
662
663 interfacePrivate->localized_key = CFSTR("bond");
664 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
665
666 interfacePrivate->bond.interfaces = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
667 // interfacePrivate->bond.mode = NULL;
668 // interfacePrivate->bond.options = NULL;
669
670 return interfacePrivate;
671 }
672
673
674 __private_extern__
675 SCNetworkInterfacePrivateRef
676 _SCVLANInterfaceCreatePrivate(CFAllocatorRef allocator,
677 CFStringRef vlan_if)
678 {
679 SCNetworkInterfacePrivateRef interfacePrivate;
680
681 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL, NULL);
682 if (interfacePrivate == NULL) {
683 return NULL;
684 }
685
686 interfacePrivate->interface_type = kSCNetworkInterfaceTypeVLAN;
687 interfacePrivate->entity_type = kSCEntNetEthernet;
688 interfacePrivate->entity_device = CFStringCreateCopy(allocator, vlan_if);
689 interfacePrivate->builtin = TRUE;
690 interfacePrivate->sort_order = kSortVLAN;
691
692 interfacePrivate->localized_key = CFSTR("vlan");
693 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
694
695 // interfacePrivate->vlan.interface = NULL;
696 // interfacePrivate->vlan.tag = NULL;
697 // interfacePrivate->vlan.options = NULL;
698
699 return interfacePrivate;
700 }
701
702
703 #pragma mark -
704 #pragma mark Interface ordering
705
706
707 static CFArrayRef
708 split_path(CFStringRef path)
709 {
710 CFArrayRef components;
711 CFMutableStringRef nPath;
712
713 // turn '@'s into '/'s
714 nPath = CFStringCreateMutableCopy(NULL, 0, path);
715 (void) CFStringFindAndReplace(nPath,
716 CFSTR("@"),
717 CFSTR("/"),
718 CFRangeMake(0, CFStringGetLength(nPath)),
719 0);
720
721 // split path into components to be compared
722 components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
723 CFRelease(nPath);
724
725 return components;
726 }
727
728
729 CFComparisonResult
730 _SCNetworkInterfaceCompare(const void *val1, const void *val2, void *context)
731 {
732 SCNetworkInterfacePrivateRef dev1 = (SCNetworkInterfacePrivateRef)val1;
733 SCNetworkInterfacePrivateRef dev2 = (SCNetworkInterfacePrivateRef)val2;
734 CFComparisonResult res = kCFCompareEqualTo;
735
736 /* sort by interface type */
737 if (dev1->sort_order != dev2->sort_order) {
738 if (dev1->sort_order < dev2->sort_order) {
739 res = kCFCompareLessThan;
740 } else {
741 res = kCFCompareGreaterThan;
742 }
743 return (res);
744 }
745
746 /* built-in interfaces sort first */
747 if (dev1->builtin != dev2->builtin) {
748 if (dev1->builtin) {
749 res = kCFCompareLessThan;
750 } else {
751 res = kCFCompareGreaterThan;
752 }
753 return (res);
754 }
755
756 /* ... and then, sort built-in interfaces by "location" */
757 if (dev1->builtin) {
758 if (dev1->location != dev2->location) {
759 if (isA_CFString(dev1->location)) {
760 if (isA_CFString(dev2->location)) {
761 res = CFStringCompare(dev1->location, dev2->location, 0);
762 } else {
763 res = kCFCompareLessThan;
764 }
765 } else {
766 res = kCFCompareGreaterThan;
767 }
768
769 if (res != kCFCompareEqualTo) {
770 return (res);
771 }
772 }
773 }
774
775 /* ... and, then sort by IOPathMatch */
776 if ((dev1->path != NULL) && (dev2->path != NULL)) {
777 CFArrayRef elements1;
778 CFArrayRef elements2;
779 CFIndex i;
780 CFIndex n;
781 CFIndex n1;
782 CFIndex n2;
783
784 elements1 = split_path(dev1->path);
785 n1 = CFArrayGetCount(elements1);
786
787 elements2 = split_path(dev2->path);
788 n2 = CFArrayGetCount(elements2);
789
790 n = (n1 <= n2) ? n1 : n2;
791 for (i = 0; i < n; i++) {
792 CFStringRef e1;
793 CFStringRef e2;
794 char *end;
795 quad_t q1;
796 quad_t q2;
797 char *str;
798 Boolean isNum;
799
800 e1 = CFArrayGetValueAtIndex(elements1, i);
801 e2 = CFArrayGetValueAtIndex(elements2, i);
802
803 str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingUTF8);
804 errno = 0;
805 q1 = strtoq(str, &end, 16);
806 isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
807 CFAllocatorDeallocate(NULL, str);
808
809 if (isNum) {
810 // if e1 is a valid numeric string
811 str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingUTF8);
812 errno = 0;
813 q2 = strtoq(str, &end, 16);
814 isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
815 CFAllocatorDeallocate(NULL, str);
816
817 if (isNum) {
818 // if e2 is also a valid numeric string
819
820 if (q1 == q2) {
821 res = kCFCompareEqualTo;
822 continue;
823 } else if (q1 < q2) {
824 res = kCFCompareLessThan;
825 } else {
826 res = kCFCompareGreaterThan;
827 }
828 break;
829 }
830 }
831
832 res = CFStringCompare(e1, e2, 0);
833 if (res != kCFCompareEqualTo) {
834 break;
835 }
836 }
837
838 if (res == kCFCompareEqualTo) {
839 if (n1 < n2) {
840 res = kCFCompareLessThan;
841 } else if (n1 < n2) {
842 res = kCFCompareGreaterThan;
843 }
844 }
845
846 CFRelease(elements1);
847 CFRelease(elements2);
848
849 if (res != kCFCompareEqualTo) {
850 return (res);
851 }
852 }
853
854 /* ... and lastly, sort by BSD interface name */
855 if ((dev1->entity_device != NULL) && (dev2->entity_device != NULL)) {
856 res = CFStringCompare(dev1->entity_device, dev2->entity_device, 0);
857 }
858
859 return res;
860 }
861
862
863 static void
864 sort_interfaces(CFMutableArrayRef all_interfaces)
865 {
866 int n = CFArrayGetCount(all_interfaces);
867
868 if (n < 2) {
869 return;
870 }
871
872 CFArraySortValues(all_interfaces, CFRangeMake(0, n), _SCNetworkInterfaceCompare, NULL);
873 return;
874 }
875
876
877 __private_extern__
878 int
879 __SCNetworkInterfaceOrder(SCNetworkInterfaceRef interface)
880 {
881 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
882
883 return interfacePrivate->sort_order;
884 }
885
886
887 #pragma mark -
888 #pragma mark Interface details
889
890
891 static CFStringRef
892 IOCopyCFStringValue(CFTypeRef ioVal)
893 {
894 if (isA_CFString(ioVal)) {
895 return CFStringCreateCopy(NULL, ioVal);
896 }
897
898 if (isA_CFData(ioVal)) {
899 return CFStringCreateWithCString(NULL,
900 (const char *)CFDataGetBytePtr(ioVal),
901 kCFStringEncodingUTF8);
902 }
903
904 return NULL;
905 }
906
907
908 static CFStringRef
909 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict, CFStringRef io_key)
910 {
911 CFTypeRef ioVal;
912
913 ioVal = CFDictionaryGetValue(io_dict, io_key);
914 return IOCopyCFStringValue(ioVal);
915 }
916
917
918 static Boolean
919 IOStringValueHasPrefix(CFTypeRef ioVal, CFStringRef prefix)
920 {
921 Boolean match = FALSE;
922 CFIndex prefixLen = CFStringGetLength(prefix);
923 CFStringRef str = ioVal;
924
925 if (!isA_CFString(ioVal)) {
926 if (isA_CFData(ioVal)) {
927 str = CFStringCreateWithCStringNoCopy(NULL,
928 (const char *)CFDataGetBytePtr(ioVal),
929 kCFStringEncodingUTF8,
930 kCFAllocatorNull);
931 } else {
932 return FALSE;
933 }
934 }
935
936 if ((str != NULL) &&
937 (CFStringGetLength(str) >= prefixLen) &&
938 (CFStringCompareWithOptions(str,
939 prefix,
940 CFRangeMake(0, prefixLen),
941 kCFCompareCaseInsensitive) == kCFCompareEqualTo)) {
942 match = TRUE;
943 }
944
945 if (str != ioVal) CFRelease(str);
946 return match;
947 }
948
949
950 static const struct {
951 const CFStringRef name;
952 const CFStringRef slot;
953 } slot_mappings[] = {
954 // Beige G3
955 { CFSTR("A1") , CFSTR("1") },
956 { CFSTR("B1") , CFSTR("2") },
957 { CFSTR("C1") , CFSTR("3") },
958
959 // Blue&White G3, Yikes G4
960 { CFSTR("J12"), CFSTR("1") },
961 { CFSTR("J11"), CFSTR("2") },
962 { CFSTR("J10"), CFSTR("3") },
963 { CFSTR("J9"), CFSTR("4") },
964
965 // AGP G4
966 { CFSTR("A") , CFSTR("1") },
967 { CFSTR("B") , CFSTR("2") },
968 { CFSTR("C") , CFSTR("3") },
969 { CFSTR("D") , CFSTR("4") },
970
971 // Digital Audio G4 (and later models)
972 { CFSTR("1") , CFSTR("1") },
973 { CFSTR("2") , CFSTR("2") },
974 { CFSTR("3") , CFSTR("3") },
975 { CFSTR("4") , CFSTR("4") },
976 { CFSTR("5") , CFSTR("5") }
977 };
978
979
980 static CFStringRef
981 pci_slot(io_registry_entry_t interface, CFTypeRef *pci_slot_name)
982 {
983 kern_return_t kr;
984 io_registry_entry_t parent;
985 CFMutableStringRef slot;
986 CFTypeRef slot_name;
987
988 slot = NULL;
989 if (pci_slot_name != NULL) *pci_slot_name = NULL;
990
991 slot_name = IORegistryEntryCreateCFProperty(interface, CFSTR("AAPL,slot-name"), NULL, 0);
992 if (slot_name != NULL) {
993 CFIndex i;
994
995 slot = CFStringCreateMutable(NULL, 0);
996 if (isA_CFString(slot_name)) {
997 if (pci_slot_name != NULL) *pci_slot_name = CFStringCreateCopy(NULL, slot_name);
998 CFStringAppend(slot, slot_name);
999 } else if (isA_CFData(slot_name)) {
1000 if (pci_slot_name != NULL) *pci_slot_name = CFDataCreateCopy(NULL, slot_name);
1001 CFStringAppendCString(slot,
1002 (const char *)CFDataGetBytePtr(slot_name),
1003 kCFStringEncodingUTF8);
1004 }
1005
1006 if (CFStringGetLength(slot) > 5) {
1007 (void) CFStringFindAndReplace(slot,
1008 CFSTR("slot-"),
1009 CFSTR(""),
1010 CFRangeMake(0, 5),
1011 kCFCompareCaseInsensitive|kCFCompareAnchored);
1012 }
1013
1014 for (i = 0; i < sizeof(slot_mappings)/sizeof(slot_mappings[0]); i++) {
1015 if (CFStringCompare(slot,
1016 slot_mappings[i].name,
1017 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
1018 CFRelease(slot);
1019 slot = (CFMutableStringRef)CFRetain(slot_mappings[i].slot);
1020 break;
1021 }
1022 }
1023
1024 CFRelease(slot_name);
1025 }
1026
1027 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &parent);
1028 switch (kr) {
1029 case kIOReturnSuccess : {
1030 CFTypeRef parent_pci_slot_name = NULL;
1031 CFStringRef parent_slot;
1032
1033 parent_slot = pci_slot(parent, &parent_pci_slot_name);
1034 if (parent_slot != NULL) {
1035 if (slot != NULL) CFRelease(slot);
1036 slot = (CFMutableStringRef)parent_slot;
1037
1038 if (pci_slot_name != NULL) {
1039 if (*pci_slot_name != NULL) CFRelease(*pci_slot_name);
1040 *pci_slot_name = parent_pci_slot_name;
1041 } else {
1042 CFRelease(parent_pci_slot_name);
1043 }
1044 }
1045
1046 IOObjectRelease(parent);
1047 break;
1048 }
1049 case kIOReturnNoDevice :
1050 // if we have hit the root node
1051 break;
1052 default :
1053 SCLog(TRUE, LOG_DEBUG, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
1054 break;
1055 }
1056
1057 return slot;
1058 }
1059
1060
1061 static CFComparisonResult
1062 compare_bsdNames(const void *val1, const void *val2, void *context)
1063 {
1064 CFStringRef bsd1 = (CFStringRef)val1;
1065 CFStringRef bsd2 = (CFStringRef)val2;
1066
1067 return CFStringCompare(bsd1, bsd2, 0);
1068 }
1069
1070
1071 static CFStringRef
1072 pci_port(CFTypeRef slot_name, CFStringRef bsdName)
1073 {
1074 CFIndex n;
1075 CFStringRef port_name = NULL;
1076 CFMutableArrayRef port_names;
1077
1078 kern_return_t kr;
1079 CFStringRef match_keys[2];
1080 CFTypeRef match_vals[2];
1081 CFDictionaryRef match_dict;
1082 CFDictionaryRef matching;
1083 io_registry_entry_t slot;
1084 io_iterator_t slot_iterator = MACH_PORT_NULL;
1085
1086 match_keys[0] = CFSTR("AAPL,slot-name");
1087 match_vals[0] = slot_name;
1088
1089 match_dict = CFDictionaryCreate(NULL,
1090 (const void **)match_keys,
1091 (const void **)match_vals,
1092 1,
1093 &kCFTypeDictionaryKeyCallBacks,
1094 &kCFTypeDictionaryValueCallBacks);
1095
1096 match_keys[0] = CFSTR(kIOProviderClassKey);
1097 match_vals[0] = CFSTR("IOPCIDevice");
1098
1099 match_keys[1] = CFSTR(kIOPropertyMatchKey);
1100 match_vals[1] = match_dict;
1101
1102 // note: the "matching" dictionary will be consumed by the following
1103 matching = CFDictionaryCreate(NULL,
1104 (const void **)match_keys,
1105 (const void **)match_vals,
1106 sizeof(match_keys)/sizeof(match_keys[0]),
1107 &kCFTypeDictionaryKeyCallBacks,
1108 &kCFTypeDictionaryValueCallBacks);
1109 CFRelease(match_dict);
1110
1111 kr = IOServiceGetMatchingServices(masterPort, matching, &slot_iterator);
1112 if (kr != kIOReturnSuccess) {
1113 SCLog(TRUE, LOG_DEBUG, CFSTR("pci_port IOServiceGetMatchingServices() failed, kr = 0x%x"), kr);
1114 return MACH_PORT_NULL;
1115 }
1116
1117 port_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1118
1119 while ((slot = IOIteratorNext(slot_iterator)) != MACH_PORT_NULL) {
1120 io_registry_entry_t child;
1121 io_iterator_t child_iterator = MACH_PORT_NULL;
1122
1123 kr = IORegistryEntryCreateIterator(slot,
1124 kIOServicePlane,
1125 kIORegistryIterateRecursively,
1126 &child_iterator);
1127 if (kr != kIOReturnSuccess) {
1128 SCLog(TRUE, LOG_DEBUG, CFSTR("pci_port IORegistryEntryCreateIterator() failed, kr = 0x%x"), kr);
1129 return MACH_PORT_NULL;
1130 }
1131
1132 while ((child = IOIteratorNext(child_iterator)) != MACH_PORT_NULL) {
1133 if (IOObjectConformsTo(child, kIONetworkInterfaceClass)) {
1134 CFStringRef if_bsdName;
1135
1136 if_bsdName = IORegistryEntryCreateCFProperty(child,
1137 CFSTR(kIOBSDNameKey),
1138 NULL,
1139 0);
1140 if (if_bsdName != NULL) {
1141 CFArrayAppendValue(port_names, if_bsdName);
1142 CFRelease(if_bsdName);
1143 }
1144 }
1145 IOObjectRelease(child);
1146 }
1147 IOObjectRelease(child_iterator);
1148 IOObjectRelease(slot);
1149 }
1150 IOObjectRelease(slot_iterator);
1151
1152 n = CFArrayGetCount(port_names);
1153 if (n > 1) {
1154 CFArraySortValues(port_names, CFRangeMake(0, n), compare_bsdNames, NULL);
1155 n = CFArrayGetFirstIndexOfValue(port_names, CFRangeMake(0, n), bsdName);
1156 if (n != kCFNotFound) {
1157 port_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), n + 1);
1158 }
1159 }
1160
1161 CFRelease(port_names);
1162 return port_name;
1163 }
1164
1165
1166 static Boolean
1167 pci_slot_info(io_registry_entry_t interface, CFStringRef *slot_name, CFStringRef *port_name)
1168 {
1169 CFStringRef bsd_name;
1170 Boolean ok = FALSE;
1171 CFTypeRef pci_slot_name;
1172
1173 *slot_name = NULL;
1174 *port_name = NULL;
1175
1176 bsd_name = IORegistryEntryCreateCFProperty(interface, CFSTR(kIOBSDNameKey), NULL, 0);
1177 if (bsd_name == NULL) {
1178 return FALSE;
1179 }
1180
1181 *slot_name = pci_slot(interface, &pci_slot_name);
1182 if (*slot_name != NULL) {
1183 if (pci_slot_name != NULL) {
1184 *port_name = pci_port(pci_slot_name, bsd_name);
1185 CFRelease(pci_slot_name);
1186 }
1187 ok = TRUE;
1188 }
1189
1190 CFRelease(bsd_name);
1191 return ok;
1192 }
1193
1194
1195 static Boolean
1196 isBuiltin(io_registry_entry_t interface)
1197 {
1198 CFStringRef slot;
1199
1200 slot = pci_slot(interface, NULL);
1201 if (slot != NULL) {
1202 // interfaces which have a "slot" are not built-in
1203 CFRelease(slot);
1204 return FALSE;
1205 }
1206
1207 return TRUE;
1208 }
1209
1210
1211 #pragma mark -
1212 #pragma mark Interface enumeration
1213
1214
1215 typedef Boolean (*processInterface)(SCNetworkInterfacePrivateRef interfacePrivate,
1216 io_registry_entry_t interface,
1217 CFDictionaryRef interface_dict,
1218 io_registry_entry_t controller,
1219 CFDictionaryRef controller_dict,
1220 io_registry_entry_t bus,
1221 CFDictionaryRef bus_dict);
1222
1223
1224 static Boolean
1225 processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate,
1226 io_registry_entry_t interface,
1227 CFDictionaryRef interface_dict,
1228 io_registry_entry_t controller,
1229 CFDictionaryRef controller_dict,
1230 io_registry_entry_t bus,
1231 CFDictionaryRef bus_dict)
1232 {
1233 CFBooleanRef bVal;
1234 CFDataRef data;
1235 int ift = -1;
1236 int iVal;
1237 CFNumberRef num;
1238 CFStringRef str;
1239
1240 // interface type
1241 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType));
1242 if (isA_CFNumber(num) &&
1243 CFNumberGetValue(num, kCFNumberIntType, &ift)) {
1244 interfacePrivate->type = CFRetain(num);
1245 } else {
1246 SCLog(TRUE, LOG_DEBUG, CFSTR("processNetworkInterface() failed, no interface type"));
1247 return FALSE;
1248 }
1249
1250 switch (ift) {
1251 case IFT_ETHER :
1252 // Type, Hardware
1253
1254 if ((IOObjectConformsTo(controller, "IO80211Controller")) ||
1255 (IOObjectConformsTo(controller, "AirPortPCI" )) ||
1256 (IOObjectConformsTo(controller, "AirPortDriver" ))) {
1257 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
1258 interfacePrivate->entity_type = kSCEntNetEthernet;
1259 interfacePrivate->sort_order = kSortAirPort;
1260 } else if (IOObjectConformsTo(controller, "IOBluetoothBNEPDriver")) {
1261 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1262 interfacePrivate->entity_type = kSCEntNetEthernet;
1263 interfacePrivate->sort_order = kSortBluetoothPAN;
1264 } else {
1265 str = IODictionaryCopyCFStringValue(bus_dict, CFSTR("name"));
1266 if ((str != NULL) && CFEqual(str, CFSTR("radio"))) {
1267 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; // ??
1268 interfacePrivate->entity_type = kSCEntNetEthernet;
1269 interfacePrivate->sort_order = kSortOtherWireless;
1270 } else {
1271 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
1272 interfacePrivate->entity_type = kSCEntNetEthernet;
1273 interfacePrivate->sort_order = kSortEthernet;
1274
1275 // BOND support only enabled for ethernet devices
1276 interfacePrivate->supportsBond = TRUE;
1277 }
1278
1279 if (str != NULL) CFRelease(str);
1280 }
1281
1282 // built-in
1283 bVal = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOBuiltin)));
1284 if (bVal == NULL) {
1285 bVal = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOPrimaryInterface)));
1286 }
1287 if (bVal != NULL) {
1288 interfacePrivate->builtin = CFBooleanGetValue(bVal);
1289 } else {
1290 interfacePrivate->builtin = isBuiltin(interface);
1291 }
1292
1293 // location
1294 interfacePrivate->location = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOLocation));
1295
1296 // VLAN support
1297 num = CFDictionaryGetValue(controller_dict, CFSTR(kIOFeatures));
1298 if (isA_CFNumber(num) &&
1299 CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
1300 if (iVal & (kIONetworkFeatureHardwareVlan | kIONetworkFeatureSoftwareVlan)) {
1301 interfacePrivate->supportsVLAN = TRUE;
1302 }
1303 }
1304
1305 // localized name
1306 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) {
1307 interfacePrivate->localized_key = CFSTR("airport");
1308 } else if (interfacePrivate->sort_order == kSortBluetoothPAN) {
1309 interfacePrivate->localized_key = CFSTR("bluetooth-pan");
1310 } else if (interfacePrivate->sort_order == kSortOtherWireless) {
1311 interfacePrivate->localized_key = CFSTR("wireless");
1312 interfacePrivate->localized_arg1 = CFRetain(CFSTR("")); // ??
1313 } else if (interfacePrivate->builtin) {
1314 if ((interfacePrivate->location == NULL) ||
1315 (CFStringGetLength(interfacePrivate->location) == 0)) {
1316 interfacePrivate->localized_key = CFSTR("ether");
1317 } else {
1318 interfacePrivate->localized_key = CFSTR("multiether");
1319 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location);
1320 }
1321 } else {
1322 CFStringRef provider;
1323
1324 // check provider class
1325 provider = IORegistryEntrySearchCFProperty(interface,
1326 kIOServicePlane,
1327 CFSTR(kIOProviderClassKey),
1328 NULL,
1329 kIORegistryIterateRecursively | kIORegistryIterateParents);
1330 if (provider != NULL) {
1331 if (CFEqual(provider, CFSTR("IOPCIDevice"))) {
1332 CFStringRef port_name;
1333 CFStringRef slot_name;
1334
1335 if (pci_slot_info(interface, &slot_name, &port_name)) {
1336 if (port_name == NULL) {
1337 interfacePrivate->localized_key = CFSTR("pci-ether");
1338 interfacePrivate->localized_arg1 = slot_name;
1339 } else {
1340 interfacePrivate->localized_key = CFSTR("pci-multiether");
1341 interfacePrivate->localized_arg1 = slot_name;
1342 interfacePrivate->localized_arg2 = port_name;
1343 }
1344 }
1345 } else if (CFEqual(provider, CFSTR("IOUSBDevice"))) {
1346 CFTypeRef val;
1347
1348 // check if a "Product Name" has been provided
1349 val = IORegistryEntrySearchCFProperty(interface,
1350 kIOServicePlane,
1351 CFSTR(kIOPropertyProductNameKey),
1352 NULL,
1353 kIORegistryIterateRecursively | kIORegistryIterateParents);
1354 if (val != NULL) {
1355 CFStringRef productName;
1356
1357 productName = IOCopyCFStringValue(val);
1358 CFRelease(val);
1359
1360 if (productName != NULL) {
1361 if (CFStringGetLength(productName) > 0) {
1362 // if we have a [somewhat reasonable?] product name
1363 if (interfacePrivate->name != NULL) {
1364 CFRelease(interfacePrivate->name);
1365 }
1366 interfacePrivate->name = CFRetain(productName);
1367 if (interfacePrivate->localized_name != NULL) {
1368 CFRelease(interfacePrivate->localized_name);
1369 }
1370 interfacePrivate->localized_name = copy_interface_string(bundle, productName, TRUE);
1371 }
1372
1373 CFRelease(productName);
1374 }
1375 } else {
1376 interfacePrivate->localized_key = CFSTR("usb-ether");
1377 interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
1378 }
1379 }
1380 CFRelease(provider);
1381 }
1382
1383 if (interfacePrivate->localized_key == NULL) {
1384 // if no provider, not a PCI device, or no slot information
1385 interfacePrivate->localized_key = CFSTR("generic-ether");
1386 interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
1387 }
1388 }
1389
1390 break;
1391 case IFT_IEEE1394 :
1392 // Type
1393 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
1394
1395 // Entity
1396 interfacePrivate->entity_type = kSCEntNetFireWire;
1397
1398 // built-in
1399 interfacePrivate->builtin = isBuiltin(interface);
1400
1401 // sort order
1402 interfacePrivate->sort_order = kSortFireWire;
1403
1404 // localized name
1405 if (interfacePrivate->builtin) {
1406 interfacePrivate->localized_key = CFSTR("firewire");
1407 } else {
1408 CFStringRef slot_name;
1409
1410 slot_name = pci_slot(interface, NULL);
1411 if (slot_name != NULL) {
1412 interfacePrivate->localized_key = CFSTR("pci-firewire");
1413 interfacePrivate->localized_arg1 = slot_name;
1414 }
1415 }
1416
1417 break;
1418 default :
1419 SCLog(TRUE, LOG_DEBUG, CFSTR("processNetworkInterface() failed, unknown interface type = %d"), ift);
1420 return FALSE;
1421 }
1422
1423 // Device
1424 interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
1425
1426 // Hardware (MAC) address
1427 data = CFDictionaryGetValue(controller_dict, CFSTR(kIOMACAddress));
1428 if (isA_CFData(data)) {
1429 interfacePrivate->address = CFRetain(data);
1430 }
1431
1432 // interface unit
1433 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceUnit));
1434 if (isA_CFNumber(num) &&
1435 CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
1436 interfacePrivate->unit = CFRetain(num);
1437 }
1438
1439 return TRUE;
1440 }
1441
1442
1443 static void
1444 set_connection_script(SCNetworkInterfacePrivateRef interfacePrivate, CFStringRef script)
1445 {
1446 CFDictionaryRef dict;
1447 CFMutableDictionaryRef newDict;
1448
1449 if (interfacePrivate->overrides == NULL) {
1450 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1451 0,
1452 &kCFTypeDictionaryKeyCallBacks,
1453 &kCFTypeDictionaryValueCallBacks);
1454 }
1455
1456 dict = CFDictionaryGetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
1457 if (dict != NULL) {
1458 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
1459 } else {
1460 newDict = CFDictionaryCreateMutable(NULL,
1461 0,
1462 &kCFTypeDictionaryKeyCallBacks,
1463 &kCFTypeDictionaryValueCallBacks);
1464 }
1465 if (script != NULL) {
1466 CFDictionarySetValue(newDict, kSCPropNetModemConnectionScript, script);
1467 } else {
1468 CFDictionaryRemoveValue(newDict, kSCPropNetModemConnectionScript);
1469 }
1470 if (CFDictionaryGetCount(newDict) > 0) {
1471 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem, newDict);
1472 } else {
1473 CFDictionaryRemoveValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
1474 }
1475 CFRelease(newDict);
1476
1477 if (CFDictionaryGetCount(interfacePrivate->overrides) == 0) {
1478 CFRelease(interfacePrivate->overrides);
1479 interfacePrivate->overrides = NULL;
1480 }
1481 return;
1482 }
1483
1484
1485 static Boolean
1486 is_valid_connection_script(CFStringRef script)
1487 {
1488 char ccl[MAXPATHLEN];
1489 char path[MAXPATHLEN];
1490 NSSearchPathEnumerationState state;
1491
1492 (void) _SC_cfstring_to_cstring(script,
1493 ccl,
1494 sizeof(ccl),
1495 kCFStringEncodingUTF8);
1496
1497 state = NSStartSearchPathEnumeration(NSLibraryDirectory,
1498 NSLocalDomainMask|NSSystemDomainMask);
1499 while ((state = NSGetNextSearchPathEnumeration(state, path))) {
1500 size_t n;
1501 struct stat statBuf;
1502
1503 if (ccl[0] == '/') {
1504 path[0] = '\0'; // if modemCCL is a full path
1505 } else {
1506 strlcat(path, "/Modem Scripts/", sizeof(path));
1507 }
1508 strlcat(path, ccl, sizeof(path));
1509
1510 if (stat(path, &statBuf) != 0) {
1511 if (errno == ENOENT) {
1512 goto bundle;
1513 }
1514
1515 SCLog(TRUE, LOG_DEBUG,
1516 CFSTR("processSerialInterface stat() failed: %s"),
1517 strerror(errno));
1518 continue;
1519 }
1520 if (S_ISREG(statBuf.st_mode)) {
1521 // if we have a valid CCL script
1522 return TRUE;
1523 }
1524
1525 #define BUNDLE_EXT ".ccl"
1526 #define BUNDLE_EXT_LEN sizeof(BUNDLE_EXT) - 1
1527
1528 bundle :
1529
1530 n = strlen(path);
1531 if ((n <= BUNDLE_EXT_LEN) ||
1532 (strstr(&path[n - BUNDLE_EXT_LEN], BUNDLE_EXT) == NULL)) {
1533 strlcat(path, BUNDLE_EXT, sizeof(path));
1534 if (stat(path, &statBuf) != 0) {
1535 if (errno == ENOENT) {
1536 continue;
1537 }
1538
1539 SCLog(TRUE, LOG_DEBUG,
1540 CFSTR("processSerialInterface stat() failed: %s"),
1541 strerror(errno));
1542 continue;
1543 }
1544 }
1545 if (S_ISDIR(statBuf.st_mode)) {
1546 // if we have a valid CCL bundle
1547 return TRUE;
1548 }
1549 }
1550
1551 return FALSE;
1552 }
1553
1554
1555 static Boolean
1556 processSerialInterface(SCNetworkInterfacePrivateRef interfacePrivate,
1557 io_registry_entry_t interface,
1558 CFDictionaryRef interface_dict,
1559 io_registry_entry_t controller,
1560 CFDictionaryRef controller_dict,
1561 io_registry_entry_t bus,
1562 CFDictionaryRef bus_dict)
1563 {
1564 CFStringRef ift;
1565 Boolean isModem = FALSE;
1566 CFStringRef modemCCL = NULL;
1567 CFStringRef str;
1568 CFTypeRef val;
1569
1570 // check if hidden
1571 val = IORegistryEntrySearchCFProperty(interface,
1572 kIOServicePlane,
1573 CFSTR("HiddenPort"),
1574 NULL,
1575 kIORegistryIterateRecursively | kIORegistryIterateParents);
1576 if (val != NULL) {
1577 CFRelease(val);
1578 return FALSE; // if this interface should not be exposed
1579 }
1580
1581 // Type
1582 str = CFDictionaryGetValue(interface_dict, CFSTR(kIOTTYBaseNameKey));
1583 if (str == NULL) {
1584 return FALSE;
1585 }
1586
1587 /*
1588 * From MoreSCF:
1589 *
1590 * Exclude ports named "irda" because otherwise the IrDA ports on the
1591 * original iMac (rev's A through D) show up as serial ports. Given
1592 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
1593 * even support it, these ports definitely shouldn't be listed.
1594 */
1595 if (CFStringCompare(str,
1596 CFSTR("irda"),
1597 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
1598 return FALSE;
1599 }
1600
1601 if (IOStringValueHasPrefix(str, CFSTR("bluetooth"))) {
1602 // Bluetooth
1603 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
1604 interfacePrivate->sort_order = kSortBluetooth;
1605 } else if (IOStringValueHasPrefix(str, CFSTR("irda-ircomm"))) {
1606 // IrDA
1607 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
1608 interfacePrivate->sort_order = kSortIrDA;
1609 } else if (IOStringValueHasPrefix(str, CFSTR("wwan"))) {
1610 // WWAN
1611 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN;
1612 interfacePrivate->sort_order = kSortWWAN;
1613 } else {
1614 // Modem
1615 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
1616 interfacePrivate->sort_order = kSortModem;
1617
1618 // V.92 support
1619 val = IORegistryEntrySearchCFProperty(interface,
1620 kIOServicePlane,
1621 CFSTR(kIODeviceSupportsHoldKey),
1622 NULL,
1623 kIORegistryIterateRecursively | kIORegistryIterateParents);
1624 if (val != NULL) {
1625 uint32_t v92;
1626
1627 if (isA_CFNumber(val) &&
1628 CFNumberGetValue(val, kCFNumberSInt32Type, &v92)) {
1629 interfacePrivate->modemIsV92 = (v92 == 1);
1630 }
1631 CFRelease(val);
1632 }
1633 }
1634
1635 // Entity (Type)
1636 interfacePrivate->entity_type = kSCEntNetModem;
1637
1638 // Entity (Hardware)
1639 ift = CFDictionaryGetValue(interface_dict, CFSTR(kIOSerialBSDTypeKey));
1640 if (!isA_CFString(ift)) {
1641 return FALSE;
1642 }
1643
1644 if (CFEqual(ift, CFSTR(kIOSerialBSDModemType))) {
1645 // if modem
1646 isModem = TRUE;
1647
1648 if (CFEqual(str, CFSTR("modem"))) {
1649 interfacePrivate->builtin = TRUE;
1650 interfacePrivate->sort_order = kSortInternalModem;
1651 } else if (CFEqual(str, CFSTR("usbmodem"))) {
1652 interfacePrivate->sort_order = kSortUSBModem;
1653 }
1654 } else if (CFEqual(ift, CFSTR(kIOSerialBSDRS232Type))) {
1655 // if serial port
1656 interfacePrivate->sort_order = kSortSerialPort;
1657 } else {
1658 return FALSE;
1659 }
1660
1661 // Entity (Device)
1662 interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYDeviceKey));
1663
1664 // configuration template overrides
1665 val = IORegistryEntrySearchCFProperty(interface,
1666 kIOServicePlane,
1667 CFSTR("DevicePPPOverrides"),
1668 NULL,
1669 kIORegistryIterateRecursively | kIORegistryIterateParents);
1670 if (val != NULL) {
1671 if (isA_CFDictionary(val)) {
1672 if (interfacePrivate->overrides == NULL) {
1673 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1674 0,
1675 &kCFTypeDictionaryKeyCallBacks,
1676 &kCFTypeDictionaryValueCallBacks);
1677 }
1678 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypePPP, val);
1679 }
1680 CFRelease(val);
1681 }
1682
1683 val = IORegistryEntrySearchCFProperty(interface,
1684 kIOServicePlane,
1685 CFSTR("DeviceModemOverrides"),
1686 NULL,
1687 kIORegistryIterateRecursively | kIORegistryIterateParents);
1688 if (val != NULL) {
1689 if (isA_CFDictionary(val)) {
1690 if (interfacePrivate->overrides == NULL) {
1691 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1692 0,
1693 &kCFTypeDictionaryKeyCallBacks,
1694 &kCFTypeDictionaryValueCallBacks);
1695 }
1696 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem, val);
1697
1698 modemCCL = CFDictionaryGetValue(val, kSCPropNetModemConnectionScript);
1699 modemCCL = isA_CFString(modemCCL);
1700 }
1701 CFRelease(val);
1702 }
1703
1704 // modem CCL
1705 if (modemCCL == NULL) {
1706 val = IORegistryEntrySearchCFProperty(interface,
1707 kIOServicePlane,
1708 CFSTR("ModemCCL"),
1709 NULL,
1710 kIORegistryIterateRecursively | kIORegistryIterateParents);
1711 if (val != NULL) {
1712 modemCCL = IOCopyCFStringValue(val);
1713 if (modemCCL != NULL) {
1714 set_connection_script(interfacePrivate, modemCCL);
1715 CFRelease(modemCCL);
1716 }
1717
1718 CFRelease(val);
1719 }
1720 }
1721
1722 // localized name
1723 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIrDA)) {
1724 interfacePrivate->localized_key = CFSTR("irda");
1725 } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBluetooth)) {
1726 interfacePrivate->localized_key = CFSTR("bluetooth");
1727 } else {
1728 CFStringRef localized = NULL;
1729 CFStringRef name = NULL;
1730 CFMutableStringRef port;
1731
1732 port = CFStringCreateMutableCopy(NULL, 0, str);
1733 CFStringLowercase(port, NULL);
1734
1735 if (!isModem) {
1736 CFStringAppend(port, CFSTR("-port"));
1737 }
1738
1739 // set non-localized name
1740 if (bundle != NULL) {
1741 name = copy_interface_string(bundle, port, FALSE);
1742 }
1743 if (name != NULL) {
1744 if (!CFEqual(port, name)) {
1745 // if [English] localization available
1746 interfacePrivate->name = name;
1747 } else {
1748 // if no [English] localization available, use TTY base name
1749 CFRelease(name);
1750 interfacePrivate->name = CFStringCreateCopy(NULL, str);
1751 }
1752 } else {
1753 interfacePrivate->name = CFStringCreateCopy(NULL, str);
1754 }
1755
1756 // set localized name
1757 if (bundle != NULL) {
1758 localized = copy_interface_string(bundle, port, TRUE);
1759 }
1760 if (localized != NULL) {
1761 if (!CFEqual(port, localized)) {
1762 // if localization available
1763 interfacePrivate->localized_name = localized;
1764 } else {
1765 // if no localization available, use TTY base name
1766 CFRelease(localized);
1767 interfacePrivate->localized_name = CFStringCreateCopy(NULL, str);
1768 }
1769 } else {
1770 interfacePrivate->localized_name = CFStringCreateCopy(NULL, str);
1771 }
1772
1773 if (!isModem || !CFEqual(str, CFSTR("modem"))) {
1774 CFStringRef productName;
1775
1776 // check if a "Product Name" has been provided
1777 val = IORegistryEntrySearchCFProperty(interface,
1778 kIOServicePlane,
1779 CFSTR(kIOPropertyProductNameKey),
1780 NULL,
1781 kIORegistryIterateRecursively | kIORegistryIterateParents);
1782 if (val != NULL) {
1783 productName = IOCopyCFStringValue(val);
1784 CFRelease(val);
1785
1786 if (productName != NULL) {
1787 if (CFStringGetLength(productName) > 0) {
1788 // if we have a [somewhat reasonable?] product name
1789 if (interfacePrivate->name != NULL) {
1790 CFRelease(interfacePrivate->name);
1791 }
1792 interfacePrivate->name = CFRetain(productName);
1793 if (interfacePrivate->localized_name != NULL) {
1794 CFRelease(interfacePrivate->localized_name);
1795 }
1796 interfacePrivate->localized_name = copy_interface_string(bundle, productName, TRUE);
1797
1798 // if not provided, also check if the product name
1799 // matches a CCL script
1800 if ((modemCCL == NULL) &&
1801 is_valid_connection_script(productName)) {
1802 set_connection_script(interfacePrivate, productName);
1803 modemCCL = productName;
1804 }
1805 }
1806
1807 CFRelease(productName);
1808 }
1809 }
1810 }
1811
1812 CFRelease(port);
1813 }
1814
1815 return TRUE;
1816 }
1817
1818
1819 static SCNetworkInterfaceRef
1820 createInterface(io_registry_entry_t interface, processInterface func)
1821 {
1822 io_registry_entry_t bus = MACH_PORT_NULL;
1823 CFMutableDictionaryRef bus_dict = NULL;
1824 io_registry_entry_t controller = MACH_PORT_NULL;
1825 CFMutableDictionaryRef controller_dict = NULL;
1826 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
1827 CFMutableDictionaryRef interface_dict = NULL;
1828 kern_return_t kr;
1829 io_string_t path;
1830
1831 kr = IORegistryEntryGetPath(interface, kIOServicePlane, path);
1832 if (kr != kIOReturnSuccess) {
1833 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetPath() failed, kr = 0x%x"), kr);
1834 goto done;
1835 }
1836
1837 kr = IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions);
1838 if (kr != kIOReturnSuccess) {
1839 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
1840 goto done;
1841 }
1842
1843 /* get the controller node */
1844 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &controller);
1845 if (kr != KERN_SUCCESS) {
1846 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
1847 goto done;
1848 }
1849
1850 /* get the dictionary associated with the node */
1851 kr = IORegistryEntryCreateCFProperties(controller, &controller_dict, NULL, kNilOptions);
1852 if (kr != KERN_SUCCESS) {
1853 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
1854 goto done;
1855 }
1856
1857 /* get the bus node */
1858 kr = IORegistryEntryGetParentEntry(controller, kIOServicePlane, &bus);
1859 if (kr != KERN_SUCCESS) {
1860 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
1861 goto done;
1862 }
1863
1864 /* get the dictionary associated with the node */
1865 kr = IORegistryEntryCreateCFProperties(bus, &bus_dict, NULL, kNilOptions);
1866 if (kr != KERN_SUCCESS) {
1867 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
1868 goto done;
1869 }
1870
1871 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL, path);
1872
1873 if (!(*func)(interfacePrivate, interface, interface_dict, controller, controller_dict, bus, bus_dict)) {
1874 CFRelease(interfacePrivate);
1875 interfacePrivate = NULL;
1876 }
1877
1878 done :
1879
1880 if (interface_dict != NULL) CFRelease(interface_dict);
1881
1882 if (controller != MACH_PORT_NULL) IOObjectRelease(controller);
1883 if (controller_dict != NULL) CFRelease(controller_dict);
1884
1885 if (bus != MACH_PORT_NULL) IOObjectRelease(bus);
1886 if (bus_dict != NULL) CFRelease(bus_dict);
1887
1888 return (SCNetworkInterfaceRef)interfacePrivate;
1889 }
1890
1891
1892 static CFArrayRef
1893 findMatchingInterfaces(CFDictionaryRef matching, processInterface func)
1894 {
1895 CFMutableArrayRef interfaces;
1896 io_registry_entry_t interface;
1897 kern_return_t kr;
1898 io_iterator_t iterator = MACH_PORT_NULL;
1899
1900 kr = IOServiceGetMatchingServices(masterPort, matching, &iterator);
1901 if (kr != kIOReturnSuccess) {
1902 SCLog(TRUE, LOG_DEBUG, CFSTR("findMatchingInterfaces IOServiceGetMatchingServices() failed, kr = 0x%x"), kr);
1903 return NULL;
1904 }
1905
1906 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1907
1908 while ((interface = IOIteratorNext(iterator)) != MACH_PORT_NULL) {
1909 SCNetworkInterfaceRef match;
1910
1911 match = createInterface(interface, func);
1912 if (match != NULL) {
1913 CFArrayAppendValue(interfaces, match);
1914 CFRelease(match);
1915 }
1916
1917 IOObjectRelease(interface);
1918 }
1919
1920 IOObjectRelease(iterator);
1921
1922 return interfaces;
1923 }
1924
1925
1926 #pragma mark -
1927 #pragma mark helper functions
1928
1929
1930 static CFIndex
1931 findConfiguration(CFStringRef interface_type)
1932 {
1933 CFIndex i;
1934
1935 for (i = 0; i < sizeof(configurations)/sizeof(configurations[0]); i++) {
1936 if (CFEqual(interface_type, *configurations[i].interface_type)) {
1937 return i;
1938 }
1939 }
1940
1941 return kCFNotFound;
1942 }
1943
1944
1945 __private_extern__
1946 CFStringRef
1947 __SCNetworkInterfaceGetDefaultConfigurationType(SCNetworkInterfaceRef interface)
1948 {
1949 CFIndex interfaceIndex;
1950 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
1951
1952 if (interfacePrivate->serviceID == NULL) {
1953 // if not associated with a service (yet)
1954 _SCErrorSet(kSCStatusInvalidArgument);
1955 return NULL;
1956 }
1957
1958 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
1959 if (interfaceIndex == kCFNotFound) {
1960 // unknown interface type, use per-service configuration preferences
1961 return interfacePrivate->interface_type; // entity
1962 }
1963
1964 if (configurations[interfaceIndex].entity_hardware != NULL) {
1965 // if configuration information can be associated with this interface type
1966 return *configurations[interfaceIndex].entity_hardware;
1967 }
1968
1969 _SCErrorSet(kSCStatusInvalidArgument);
1970 return NULL;
1971 }
1972
1973
1974 __private_extern__
1975 Boolean
1976 __SCNetworkInterfaceIsValidExtendedConfigurationType(SCNetworkInterfaceRef interface,
1977 CFStringRef extendedType,
1978 Boolean requirePerInterface)
1979 {
1980 CFStringRef defaultType;
1981 CFIndex extendedIndex;
1982 CFIndex interfaceIndex;
1983 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
1984 Boolean ok = FALSE;
1985
1986 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
1987 if (defaultType == NULL) {
1988 goto done;
1989 }
1990
1991 if (CFEqual(extendedType, defaultType)) {
1992 // extended and default configuration types cannot conflict
1993 goto done;
1994 }
1995
1996 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
1997 if (interfaceIndex == kCFNotFound) {
1998 // configuration information for unknown interface type's
1999 // are stored along with the service and we don't allow
2000 // per-service extended configurations
2001 goto done;
2002 }
2003
2004 // It turns out that, for PPP interfaces, we want to be able to store
2005 // some extended interface configuration (e.g. IPSec [for L2TP]). For
2006 // now, I'm commenting out the following test.
2007 //
2008 // if (requirePerInterface && !configurations[interfaceIndex].per_interface_config) {
2009 // // we don't allow per-service extended configurations
2010 // goto done;
2011 // }
2012
2013 extendedIndex = findConfiguration(extendedType);
2014 if (extendedIndex != kCFNotFound) {
2015 // extended type cannot match a known interface type
2016 goto done;
2017 }
2018
2019 /*
2020 * ???
2021 * Do we match specific/known extended configuration types (e.g. EAPOL)
2022 * and ensure that any non-standard extended configuration types be of
2023 * the form com.myCompany.myType?
2024 * ???
2025 */
2026
2027 ok = TRUE;
2028
2029 done :
2030
2031 if (!ok) {
2032 _SCErrorSet(kSCStatusInvalidArgument);
2033 }
2034 return ok;
2035 }
2036
2037
2038 typedef struct {
2039 CFStringRef defaultType;
2040 CFMutableArrayRef types;
2041 } extendedConfiguration, *extendedConfigurationRef;
2042
2043
2044 static void
2045 __addExtendedConfigurationType(const void *key, const void *value, void *context)
2046 {
2047 CFStringRef extendedType = (CFStringRef)key;
2048 extendedConfigurationRef myContextRef = (extendedConfigurationRef)context;
2049
2050 if (CFEqual(extendedType, myContextRef->defaultType)) {
2051 // do not include the default configuration type
2052 return;
2053 }
2054
2055 if (CFArrayContainsValue(myContextRef->types,
2056 CFRangeMake(0, CFArrayGetCount(myContextRef->types)),
2057 extendedType)) {
2058 // if extendedType already has already been added
2059 return;
2060 }
2061
2062 CFArrayAppendValue(myContextRef->types, extendedType);
2063
2064 return;
2065 }
2066
2067
2068 static CFArrayRef
2069 extendedConfigurationTypes(SCNetworkInterfaceRef interface)
2070 {
2071 CFIndex i;
2072 CFIndex interfaceIndex;
2073 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2074 extendedConfiguration myContext;
2075 SCNetworkServiceRef service;
2076 CFArrayRef sets;
2077 CFIndex n;
2078
2079 myContext.defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
2080 if (myContext.defaultType == NULL) {
2081 myContext.types = NULL;
2082 goto done;
2083 }
2084
2085 myContext.types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2086
2087 if (interfacePrivate->serviceID == NULL) {
2088 // if not associated with a service (yet)
2089 goto done;
2090 }
2091
2092 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2093 if (interfaceIndex == kCFNotFound) {
2094 // we don't allow per-service extended configurations
2095 goto done;
2096 }
2097
2098 if (!configurations[interfaceIndex].per_interface_config) {
2099 // known interface type but we still don't allow
2100 // per-service extended configurations
2101 goto done;
2102 }
2103
2104 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
2105 interfacePrivate->prefs,
2106 interfacePrivate->serviceID,
2107 interface);
2108
2109 sets = SCNetworkSetCopyAll(interfacePrivate->prefs);
2110 n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
2111
2112 for (i = 0; i < n; i++) {
2113 CFDictionaryRef configs;
2114 Boolean found;
2115 CFStringRef path;
2116 CFArrayRef services;
2117 SCNetworkSetRef set;
2118
2119 set = CFArrayGetValueAtIndex(sets, i);
2120 services = SCNetworkSetCopyServices(set);
2121 found = CFArrayContainsValue(services,
2122 CFRangeMake(0, CFArrayGetCount(services)),
2123 service);
2124 CFRelease(services);
2125
2126 if (!found) {
2127 continue;
2128 }
2129
2130 // add stored extended configuration types
2131 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
2132 SCNetworkSetGetSetID(set), // set
2133 interfacePrivate->entity_device, // service
2134 NULL); // entity
2135 configs = __getPrefsConfiguration(interfacePrivate->prefs, path);
2136 CFRelease(path);
2137 if (isA_CFDictionary(configs)) {
2138 CFDictionaryApplyFunction(configs,
2139 __addExtendedConfigurationType,
2140 &myContext);
2141 }
2142
2143 // add not-yet-stored extended configuration types
2144 if (interfacePrivate->unsaved != NULL) {
2145 CFDictionaryApplyFunction(interfacePrivate->unsaved,
2146 __addExtendedConfigurationType,
2147 &myContext);
2148 }
2149
2150 break;
2151 }
2152
2153 CFRelease(service);
2154 if (sets != NULL) CFRelease(sets);
2155
2156 done :
2157
2158 return myContext.types;
2159 }
2160
2161
2162 static CFArrayRef
2163 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate,
2164 CFStringRef extendedType)
2165 {
2166 CFMutableArrayRef array;
2167 CFIndex i;
2168 CFIndex interfaceIndex;
2169 CFIndex n;
2170 CFStringRef path;
2171 SCNetworkServiceRef service;
2172 CFArrayRef sets;
2173
2174 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2175
2176 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2177 if (interfaceIndex == kCFNotFound) {
2178 // unknown interface type, use per-service configuration preferences
2179 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
2180 interfacePrivate->serviceID, // service
2181 extendedType); // entity
2182 CFArrayAppendValue(array, path);
2183 CFRelease(path);
2184 return array;
2185 }
2186
2187 if (!configurations[interfaceIndex].per_interface_config) {
2188 // known interface type, per-service configuration preferences
2189 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
2190 interfacePrivate->serviceID, // service
2191 extendedType); // entity
2192 CFArrayAppendValue(array, path);
2193 CFRelease(path);
2194 return array;
2195 }
2196
2197 // known interface type, per-interface configuration preferences
2198 //
2199 // 1. look for all sets which contain the associated service
2200 // 2. add a per-set path for the interface configuration for
2201 // each set.
2202
2203 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
2204 interfacePrivate->prefs,
2205 interfacePrivate->serviceID,
2206 (SCNetworkInterfaceRef)interfacePrivate);
2207
2208 sets = SCNetworkSetCopyAll(interfacePrivate->prefs);
2209 n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
2210
2211 for (i = 0; i < n; i++) {
2212 CFArrayRef services;
2213 SCNetworkSetRef set;
2214
2215 set = CFArrayGetValueAtIndex(sets, i);
2216 services = SCNetworkSetCopyServices(set);
2217 if (CFArrayContainsValue(services,
2218 CFRangeMake(0, CFArrayGetCount(services)),
2219 service)) {
2220 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
2221 SCNetworkSetGetSetID(set), // set
2222 interfacePrivate->entity_device, // service
2223 extendedType); // entity
2224 CFArrayAppendValue(array, path);
2225 CFRelease(path);
2226 }
2227 CFRelease(services);
2228 }
2229
2230 if (CFArrayGetCount(array) == 0) {
2231 CFRelease(array);
2232 array = NULL;
2233 }
2234
2235 CFRelease(service);
2236 if (sets != NULL) CFRelease(sets);
2237 return array;
2238 }
2239
2240
2241 #pragma mark -
2242 #pragma mark SCNetworkInterface <--> preferences entity
2243
2244
2245 __private_extern__
2246 CFDictionaryRef
2247 __SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface)
2248 {
2249 CFMutableDictionaryRef entity;
2250 CFIndex interfaceIndex;
2251 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2252
2253 entity = CFDictionaryCreateMutable(NULL,
2254 0,
2255 &kCFTypeDictionaryKeyCallBacks,
2256 &kCFTypeDictionaryValueCallBacks);
2257 if (interfacePrivate->entity_type != NULL) {
2258 CFDictionarySetValue(entity,
2259 kSCPropNetInterfaceType,
2260 interfacePrivate->entity_type);
2261 }
2262 if (interfacePrivate->entity_subtype != NULL) {
2263 CFDictionarySetValue(entity,
2264 kSCPropNetInterfaceSubType,
2265 interfacePrivate->entity_subtype);
2266 }
2267 if (interfacePrivate->entity_device != NULL) {
2268 CFDictionarySetValue(entity,
2269 kSCPropNetInterfaceDeviceName,
2270 interfacePrivate->entity_device);
2271 }
2272
2273 // match the "hardware" with the lowest layer
2274 while (TRUE) {
2275 SCNetworkInterfaceRef nextInterface;
2276
2277 nextInterface = SCNetworkInterfaceGetInterface(interface);
2278 if (nextInterface == NULL) {
2279 break;
2280 }
2281
2282 interface = nextInterface;
2283 }
2284 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2285
2286 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2287 if (interfaceIndex != kCFNotFound) {
2288 if (configurations[interfaceIndex].entity_hardware != NULL) {
2289 CFDictionarySetValue(entity,
2290 kSCPropNetInterfaceHardware,
2291 *configurations[interfaceIndex].entity_hardware);
2292 }
2293 } else {
2294 CFDictionarySetValue(entity,
2295 kSCPropNetInterfaceHardware,
2296 interfacePrivate->interface_type);
2297 }
2298
2299 // add the localized display name (which will only be used when/if the
2300 // interface is removed from the system)
2301 CFDictionarySetValue(entity,
2302 kSCPropUserDefinedName,
2303 SCNetworkInterfaceGetLocalizedDisplayName(interface));
2304
2305 // note that this is a V.92 capable modem
2306 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeModem) &&
2307 interfacePrivate->modemIsV92) {
2308 int one = 1;
2309 CFNumberRef num;
2310
2311 num = CFNumberCreate(NULL, kCFNumberIntType, &one);
2312 CFDictionarySetValue(entity,
2313 kSCPropNetInterfaceSupportsModemOnHold,
2314 num);
2315 CFRelease(num);
2316 }
2317
2318 return entity;
2319 }
2320
2321
2322 static SCNetworkInterfaceRef
2323 findInterface(CFArrayRef interfaces, CFStringRef match_if)
2324 {
2325 CFIndex i;
2326 CFIndex n;
2327
2328 n = CFArrayGetCount(interfaces);
2329 for (i = 0; i < n; i++) {
2330 SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(interfaces, i);
2331 CFStringRef interfaceName;
2332
2333 interfaceName = SCNetworkInterfaceGetBSDName(interface);
2334 if ((interfaceName != NULL) && CFEqual(interfaceName, match_if)) {
2335 CFRetain(interface);
2336 return interface;
2337 }
2338 }
2339
2340 return NULL;
2341 }
2342
2343
2344 static SCNetworkInterfaceRef
2345 findBondInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
2346 {
2347 CFArrayRef bonds;
2348 SCNetworkInterfaceRef interface = NULL;
2349
2350 if (prefs == NULL) {
2351 return (NULL);
2352 }
2353
2354 // check if the interface is an Ethernet Bond
2355 bonds = SCBondInterfaceCopyAll(prefs);
2356 if (bonds != NULL) {
2357 interface = findInterface(bonds, ifDevice);
2358 CFRelease(bonds);
2359 }
2360 return interface;
2361 }
2362
2363 static SCNetworkInterfaceRef
2364 findVLANInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
2365 {
2366 SCNetworkInterfaceRef interface = NULL;
2367 CFArrayRef vlans;
2368
2369 if (prefs == NULL) {
2370 return (NULL);
2371 }
2372
2373 // check if the interface is a VLAN
2374 vlans = SCVLANInterfaceCopyAll(prefs);
2375 if (vlans != NULL) {
2376 interface = findInterface(vlans, ifDevice);
2377 CFRelease(vlans);
2378 }
2379 return interface;
2380 }
2381
2382
2383 SCNetworkInterfaceRef
2384 _SCNetworkInterfaceCreateWithBSDName(CFAllocatorRef allocator,
2385 CFStringRef bsdName,
2386 UInt32 flags)
2387 {
2388 CFMutableDictionaryRef entity;
2389 SCNetworkInterfaceRef interface;
2390
2391 entity = CFDictionaryCreateMutable(NULL,
2392 0,
2393 &kCFTypeDictionaryKeyCallBacks,
2394 &kCFTypeDictionaryValueCallBacks);
2395 CFDictionarySetValue(entity, kSCPropNetInterfaceDeviceName, bsdName);
2396 if ((flags & kIncludeVLANInterfaces) == 0) {
2397 CFDictionarySetValue(entity, CFSTR("_NO_VLAN_INTERFACES_"), kCFBooleanTrue);
2398 }
2399 if ((flags & kIncludeBondInterfaces) == 0) {
2400 CFDictionarySetValue(entity, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue);
2401 }
2402 interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL);
2403 CFRelease(entity);
2404
2405 return interface;
2406 }
2407
2408
2409 SCNetworkInterfaceRef
2410 _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator,
2411 CFDictionaryRef interface_entity,
2412 SCNetworkServiceRef service)
2413 {
2414 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
2415 CFStringRef ifDevice;
2416 CFStringRef ifSubType;
2417 CFStringRef ifType;
2418 CFArrayRef matching_interfaces = NULL;
2419
2420 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2421 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
2422
2423 ifType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceType);
2424 if (ifType == NULL) {
2425 /*
2426 * The interface "Type" was not specified. We'll make an
2427 * assumption that this is an "Ethernet" interface. If a
2428 * real interface exists with the provided interface name
2429 * then the actual type will be set accordingly. If not, we'll
2430 * end up crafting an "Ethernet" SCNetworkInterface which
2431 * will keep the rest of the configuration APIs happy.
2432 */
2433 ifType = kSCValNetInterfaceTypeEthernet;
2434 }
2435
2436 if (!isA_CFString(ifType)) {
2437 return NULL;
2438 }
2439
2440 ifSubType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceSubType);
2441 if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2442 if (!isA_CFString(ifSubType)) {
2443 return NULL;
2444 }
2445 }
2446
2447 ifDevice = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceDeviceName);
2448
2449 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet) ||
2450 CFEqual(ifType, kSCValNetInterfaceTypeFireWire) ||
2451 (CFEqual(ifType, kSCValNetInterfaceTypePPP) && CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE))) {
2452 char bsdName[IFNAMSIZ + 1];
2453 CFMutableDictionaryRef matching;
2454
2455 if (!isA_CFString(ifDevice)) {
2456 return NULL;
2457 }
2458
2459 if (_SC_cfstring_to_cstring(ifDevice, bsdName, sizeof(bsdName), kCFStringEncodingASCII) == NULL) {
2460 goto done;
2461 }
2462
2463 matching = IOBSDNameMatching(masterPort, 0, bsdName);
2464 if (matching == NULL) {
2465 goto done;
2466 }
2467
2468 // note: the "matching" dictionary will be consumed by the following
2469 matching_interfaces = findMatchingInterfaces(matching, processNetworkInterface);
2470
2471 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2472 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
2473 CFDictionaryRef matching;
2474 CFStringRef match_keys[2];
2475 CFStringRef match_vals[2];
2476
2477 if (!isA_CFString(ifDevice)) {
2478 return NULL;
2479 }
2480
2481 match_keys[0] = CFSTR(kIOProviderClassKey);
2482 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
2483
2484 match_keys[1] = CFSTR(kIOTTYDeviceKey);
2485 match_vals[1] = ifDevice;
2486
2487 matching = CFDictionaryCreate(NULL,
2488 (const void **)match_keys,
2489 (const void **)match_vals,
2490 sizeof(match_keys)/sizeof(match_keys[0]),
2491 &kCFTypeDictionaryKeyCallBacks,
2492 &kCFTypeDictionaryValueCallBacks);
2493
2494 // note: the "matching" dictionary will be consumed by the following
2495 matching_interfaces = findMatchingInterfaces(matching, processSerialInterface);
2496
2497 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypeL2TP)) {
2498 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2499 kSCNetworkInterfaceTypeL2TP);
2500 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPTP)) {
2501 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2502 kSCNetworkInterfaceTypePPTP);
2503 } else {
2504 // XXX do we allow non-Apple variants of PPP??? XXX
2505 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2506 ifSubType);
2507 }
2508 } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) {
2509 if (!isA_CFString(ifDevice)) {
2510 return NULL;
2511 }
2512
2513 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2514 kSCNetworkInterfaceType6to4);
2515 } else if ((CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) && (ifDevice == NULL)) {
2516 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2517 ifType);
2518 }
2519
2520 if (matching_interfaces != NULL) {
2521 CFIndex n;
2522 SCPreferencesRef prefs;
2523
2524 n = CFArrayGetCount(matching_interfaces);
2525 switch (n) {
2526 case 0 :
2527 if (!CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
2528 break;
2529 }
2530 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), NULL);
2531 if (prefs == NULL) {
2532 break;
2533 }
2534 if (!CFDictionaryContainsKey(interface_entity, CFSTR("_NO_VLAN_INTERFACES_"))) {
2535 interfacePrivate = (SCNetworkInterfacePrivateRef)findVLANInterface(prefs, ifDevice);
2536 }
2537 if ((interfacePrivate == NULL)
2538 && !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BOND_INTERFACES_"))) {
2539 interfacePrivate = (SCNetworkInterfacePrivateRef)findBondInterface(prefs, ifDevice);
2540 }
2541 CFRelease(prefs);
2542 break;
2543 case 1 :
2544 interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0);
2545 CFRetain(interfacePrivate);
2546 break;
2547 default :
2548 SCLog(TRUE, LOG_DEBUG, CFSTR("_SCNetworkInterfaceCreateWithEntity() failed, more than one interface matches %@"), ifDevice);
2549 CFRelease(matching_interfaces);
2550 _SCErrorSet(kSCStatusFailed);
2551 return NULL;
2552 }
2553 CFRelease(matching_interfaces);
2554 }
2555
2556 done :
2557
2558 if (interfacePrivate == NULL) {
2559 /*
2560 * if device not present on this system
2561 */
2562 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL, NULL);
2563 interfacePrivate->entity_type = ifType;
2564 interfacePrivate->entity_subtype = ifSubType;
2565 interfacePrivate->entity_device = (ifDevice != NULL) ? CFStringCreateCopy(NULL, ifDevice) : NULL;
2566
2567 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
2568 CFStringRef entity_hardware;
2569
2570 entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware);
2571 if ((entity_hardware != NULL) &&
2572 CFEqual(entity_hardware, kSCEntNetAirPort)) {
2573 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
2574 } else {
2575 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
2576 }
2577 } else if (CFEqual(ifType, kSCValNetInterfaceTypeFireWire)) {
2578 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
2579 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2580 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE)) {
2581 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
2582 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
2583 if (CFStringHasPrefix(ifDevice, CFSTR("Bluetooth"))) {
2584 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
2585 } else if (CFStringHasPrefix(ifDevice, CFSTR("irda"))) {
2586 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
2587 } else if (CFStringHasPrefix(ifDevice, CFSTR("wwan"))) {
2588 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN;
2589 } else {
2590 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
2591 }
2592 } else {
2593 // PPTP, L2TP, ...
2594 CFRelease(interfacePrivate);
2595 interfacePrivate = (SCNetworkInterfacePrivateRef)kSCNetworkInterfaceIPv4;
2596 CFRetain(interfacePrivate);
2597 }
2598 } else if (CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) {
2599 // if vendor interface
2600 interfacePrivate->interface_type = ifType;
2601 } else {
2602 // if unknown interface
2603 CFRelease(interfacePrivate);
2604 interfacePrivate = NULL;
2605 }
2606 }
2607
2608 if ((interfacePrivate != NULL) && (service != NULL)) {
2609 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
2610
2611 if (interfacePrivate->prefs != NULL)
2612 CFRelease(interfacePrivate->prefs);
2613 if (interfacePrivate->serviceID != NULL)
2614 CFRelease(interfacePrivate->serviceID);
2615
2616 interfacePrivate->prefs = CFRetain(servicePrivate->prefs);
2617 interfacePrivate->serviceID = CFRetain(servicePrivate->serviceID);
2618 }
2619
2620 if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2621 SCNetworkInterfaceRef parent;
2622
2623 parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate,
2624 kSCNetworkInterfaceTypePPP);
2625 CFRelease(interfacePrivate);
2626 interfacePrivate = (SCNetworkInterfacePrivateRef)parent;
2627 }
2628
2629 return (SCNetworkInterfaceRef)interfacePrivate;
2630 }
2631
2632
2633 #pragma mark -
2634 #pragma mark SCNetworkInterface APIs
2635
2636
2637 __private_extern__
2638 CFArrayRef
2639 __SCNetworkInterfaceCopyAll_IONetworkInterface(void)
2640 {
2641 CFDictionaryRef matching;
2642 CFArrayRef new_interfaces;
2643
2644 // get Ethernet, Firewire, and AirPort interfaces
2645
2646 matching = IOServiceMatching(kIONetworkInterfaceClass);
2647 new_interfaces = findMatchingInterfaces(matching, processNetworkInterface);
2648
2649 return new_interfaces;
2650 }
2651
2652
2653 static
2654 CFArrayRef
2655 __SCNetworkInterfaceCopyAll_Modem()
2656 {
2657 CFDictionaryRef matching;
2658 CFStringRef match_keys[2];
2659 CFStringRef match_vals[2];
2660 CFArrayRef new_interfaces;
2661
2662 match_keys[0] = CFSTR(kIOProviderClassKey);
2663 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
2664
2665 match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
2666 match_vals[1] = CFSTR(kIOSerialBSDModemType);
2667
2668 matching = CFDictionaryCreate(NULL,
2669 (const void **)match_keys,
2670 (const void **)match_vals,
2671 sizeof(match_keys)/sizeof(match_keys[0]),
2672 &kCFTypeDictionaryKeyCallBacks,
2673 &kCFTypeDictionaryValueCallBacks);
2674 new_interfaces = findMatchingInterfaces(matching, processSerialInterface);
2675
2676 return new_interfaces;
2677 }
2678
2679
2680 static
2681 CFArrayRef
2682 __SCNetworkInterfaceCopyAll_RS232()
2683 {
2684 CFDictionaryRef matching;
2685 CFStringRef match_keys[2];
2686 CFStringRef match_vals[2];
2687 CFArrayRef new_interfaces;
2688
2689 match_keys[0] = CFSTR(kIOProviderClassKey);
2690 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
2691
2692 match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
2693 match_vals[1] = CFSTR(kIOSerialBSDRS232Type);
2694
2695 matching = CFDictionaryCreate(NULL,
2696 (const void **)match_keys,
2697 (const void **)match_vals,
2698 sizeof(match_keys)/sizeof(match_keys[0]),
2699 &kCFTypeDictionaryKeyCallBacks,
2700 &kCFTypeDictionaryValueCallBacks);
2701 new_interfaces = findMatchingInterfaces(matching, processSerialInterface);
2702
2703 return new_interfaces;
2704 }
2705
2706
2707 static void
2708 add_interfaces(CFMutableArrayRef all_interfaces, CFArrayRef new_interfaces)
2709 {
2710 CFIndex i;
2711 CFIndex n;
2712
2713 n = CFArrayGetCount(new_interfaces);
2714 for (i = 0; i < n; i++) {
2715 CFStringRef bsdName;
2716 SCNetworkInterfaceRef interface;
2717
2718 interface = CFArrayGetValueAtIndex(new_interfaces, i);
2719 bsdName = SCNetworkInterfaceGetBSDName(interface);
2720 if (bsdName != NULL) {
2721 CFArrayAppendValue(all_interfaces, interface);
2722 }
2723 }
2724
2725 return;
2726 }
2727
2728
2729 static void
2730 __waitForInterfaces()
2731 {
2732 CFStringRef key;
2733 CFArrayRef keys;
2734 Boolean ok;
2735 SCDynamicStoreRef store;
2736
2737 store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL, NULL);
2738 if (store == NULL) {
2739 return;
2740 }
2741
2742 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin);
2743 keys = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
2744 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
2745 CFRelease(keys);
2746 if (!ok) {
2747 SCLog(TRUE, LOG_ERR,
2748 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"), SCErrorString(SCError()));
2749 goto done;
2750 }
2751
2752 while (TRUE) {
2753 CFDictionaryRef dict;
2754 Boolean quiet = FALSE;
2755
2756 // check if quiet
2757 dict = SCDynamicStoreCopyValue(store, key);
2758 if (dict != NULL) {
2759 if (isA_CFDictionary(dict) &&
2760 (CFDictionaryContainsKey(dict, CFSTR("*QUIET*")) ||
2761 CFDictionaryContainsKey(dict, CFSTR("*TIMEOUT*")))) {
2762 quiet = TRUE;
2763 }
2764 CFRelease(dict);
2765 }
2766 if (quiet) {
2767 break;
2768 }
2769
2770 ok = SCDynamicStoreNotifyWait(store);
2771 if (!ok) {
2772 SCLog(TRUE, LOG_ERR,
2773 CFSTR("SCDynamicStoreNotifyWait() failed: %s"), SCErrorString(SCError()));
2774 goto done;
2775 }
2776 }
2777
2778 done :
2779
2780 CFRelease(key);
2781 CFRelease(store);
2782 return;
2783 }
2784
2785
2786 CFArrayRef /* of SCNetworkInterfaceRef's */
2787 SCNetworkInterfaceCopyAll()
2788 {
2789 CFMutableArrayRef all_interfaces;
2790 CFArrayRef new_interfaces;
2791 SCPreferencesRef prefs;
2792
2793 /* initialize runtime */
2794 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
2795
2796 /* wait for IOKit to quiesce */
2797 pthread_once(&iokit_quiet, __waitForInterfaces);
2798
2799 all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2800
2801 // get Ethernet, Firewire, and AirPort interfaces
2802 new_interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
2803 if (new_interfaces != NULL) {
2804 add_interfaces(all_interfaces, new_interfaces);
2805 CFRelease(new_interfaces);
2806 }
2807
2808 // get Modem interfaces
2809 new_interfaces = __SCNetworkInterfaceCopyAll_Modem();
2810 if (new_interfaces != NULL) {
2811 add_interfaces(all_interfaces, new_interfaces);
2812 CFRelease(new_interfaces);
2813 }
2814
2815 // get serial (RS232) interfaces
2816 new_interfaces = __SCNetworkInterfaceCopyAll_RS232();
2817 if (new_interfaces != NULL) {
2818 add_interfaces(all_interfaces, new_interfaces);
2819 CFRelease(new_interfaces);
2820 }
2821
2822 // get virtual network interfaces (Bond, VLAN)
2823 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL);
2824 if (prefs != NULL) {
2825 new_interfaces = SCBondInterfaceCopyAll(prefs);
2826 if (new_interfaces != NULL) {
2827 add_interfaces(all_interfaces, new_interfaces);
2828 CFRelease(new_interfaces);
2829 }
2830
2831 new_interfaces = SCVLANInterfaceCopyAll(prefs);
2832 if (new_interfaces != NULL) {
2833 add_interfaces(all_interfaces, new_interfaces);
2834 CFRelease(new_interfaces);
2835 }
2836
2837 CFRelease(prefs);
2838 }
2839
2840 // all interfaces have been identified, order and return
2841 sort_interfaces(all_interfaces);
2842
2843 return all_interfaces;
2844 }
2845
2846
2847 CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */
2848 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface)
2849 {
2850 CFIndex i;
2851 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2852
2853 if (!isA_SCNetworkInterface(interface)) {
2854 _SCErrorSet(kSCStatusInvalidArgument);
2855 return NULL;
2856 }
2857
2858 if (interfacePrivate->supported_interface_types != NULL) {
2859 goto done;
2860 }
2861
2862 i = findConfiguration(interfacePrivate->interface_type);
2863 if (i != kCFNotFound) {
2864 if (configurations[i].supported_interfaces != doNone) {
2865 interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2866 if (configurations[i].supported_interfaces & do6to4) {
2867 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceType6to4);
2868 }
2869 if (configurations[i].supported_interfaces & doL2TP) {
2870 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeL2TP);
2871 }
2872 if (configurations[i].supported_interfaces & doPPP) {
2873 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPP);
2874 }
2875 if (configurations[i].supported_interfaces & doPPTP) {
2876 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPTP);
2877 }
2878 }
2879 }
2880
2881 done :
2882
2883 return interfacePrivate->supported_interface_types;
2884 }
2885
2886
2887 CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */
2888 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface)
2889 {
2890 CFIndex i;
2891 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2892
2893 if (!isA_SCNetworkInterface(interface)) {
2894 _SCErrorSet(kSCStatusInvalidArgument);
2895 return NULL;
2896 }
2897
2898 if (interfacePrivate->supported_protocol_types != NULL) {
2899 goto done;
2900 }
2901
2902 i = findConfiguration(interfacePrivate->interface_type);
2903 if (i != kCFNotFound) {
2904 if (configurations[i].supported_protocols != doNone) {
2905 interfacePrivate->supported_protocol_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2906 if (configurations[i].supported_protocols & doAppleTalk) {
2907 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeAppleTalk);
2908 }
2909 if (configurations[i].supported_protocols & doDNS) {
2910 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeDNS);
2911 }
2912 if (configurations[i].supported_protocols & doIPv4) {
2913 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv4);
2914 }
2915 if (configurations[i].supported_protocols & doIPv6) {
2916 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv6);
2917 }
2918 if (configurations[i].supported_protocols & doProxies) {
2919 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeProxies);
2920 }
2921 if (configurations[i].supported_protocols & doSMB) {
2922 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeSMB);
2923 }
2924 }
2925 }
2926
2927 done :
2928
2929 return interfacePrivate->supported_protocol_types;
2930 }
2931
2932
2933 SCNetworkInterfaceRef
2934 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child, CFStringRef interfaceType)
2935 {
2936 SCNetworkInterfacePrivateRef childPrivate = (SCNetworkInterfacePrivateRef)child;
2937 CFIndex childIndex;
2938 SCNetworkInterfacePrivateRef parentPrivate;
2939
2940 if (!isA_SCNetworkInterface(child)) {
2941 _SCErrorSet(kSCStatusInvalidArgument);
2942 return NULL;
2943 }
2944
2945 if (!isA_CFString(interfaceType)) {
2946 _SCErrorSet(kSCStatusInvalidArgument);
2947 return NULL;
2948 }
2949
2950 childIndex = findConfiguration(childPrivate->interface_type);
2951
2952 parentPrivate = __SCNetworkInterfaceCreatePrivate(NULL,
2953 child,
2954 childPrivate->prefs,
2955 childPrivate->serviceID,
2956 NULL);
2957 if (parentPrivate == NULL) {
2958 _SCErrorSet(kSCStatusFailed);
2959 return NULL;
2960 }
2961
2962 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
2963 parentPrivate->interface_type = kSCNetworkInterfaceTypePPP;
2964 parentPrivate->entity_type = kSCEntNetPPP;
2965
2966 // entity subtype
2967 if (childIndex != kCFNotFound) {
2968 if (configurations[childIndex].ppp_subtype != NULL) {
2969 parentPrivate->entity_subtype = *configurations[childIndex].ppp_subtype;
2970 } else {
2971 // sorry, the child interface does not support PPP
2972 goto fail;
2973 }
2974 } else {
2975 // if the child's interface type not known, use the child entities "Type"
2976 parentPrivate->entity_subtype = childPrivate->entity_type;
2977 }
2978
2979 if (childPrivate->entity_device != NULL) {
2980 parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device);
2981 }
2982 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
2983 if ((childIndex == kCFNotFound) ||
2984 ((configurations[childIndex].supported_interfaces & doL2TP) != doL2TP)) {
2985 // if the child interface does not support L2TP
2986 goto fail;
2987 }
2988 parentPrivate->interface_type = kSCNetworkInterfaceTypeL2TP;
2989 parentPrivate->localized_key = CFSTR("l2tp");
2990 parentPrivate->entity_type = kSCValNetInterfaceSubTypeL2TP; // interface config goes into "L2TP"
2991 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) {
2992 if ((childIndex == kCFNotFound) ||
2993 ((configurations[childIndex].supported_interfaces & doPPTP) != doPPTP)) {
2994 // if the child interface does not support PPTP
2995 goto fail;
2996 }
2997 parentPrivate->interface_type = kSCNetworkInterfaceTypePPTP;
2998 parentPrivate->localized_key = CFSTR("pptp");
2999 parentPrivate->entity_type = kSCValNetInterfaceSubTypePPTP; // interface config goes into "PPTP"
3000 } else if (CFEqual(interfaceType, kSCNetworkInterfaceType6to4)) {
3001 if ((childIndex == kCFNotFound) ||
3002 ((configurations[childIndex].supported_interfaces & do6to4) != do6to4)) {
3003 // if the child interface does not support 6to4
3004 goto fail;
3005 }
3006
3007 parentPrivate->interface_type = kSCNetworkInterfaceType6to4;
3008 parentPrivate->localized_key = CFSTR("6to4");
3009 parentPrivate->entity_type = kSCEntNet6to4;
3010 parentPrivate->entity_device = CFRetain(CFSTR("stf0"));
3011 } else if (CFStringFind(interfaceType, CFSTR("."), 0).location != kCFNotFound) {
3012 // if custom interface type
3013 parentPrivate->interface_type = interfaceType;
3014 parentPrivate->entity_type = interfaceType; // interface config goes into a
3015 // a dictionary with the same
3016 // name as the interfaceType
3017 } else {
3018 // unknown interface type
3019 goto fail;
3020 }
3021
3022 if (childPrivate->overrides != NULL) {
3023 parentPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, childPrivate->overrides);
3024 };
3025 parentPrivate->sort_order = childPrivate->sort_order;
3026
3027 return (SCNetworkInterfaceRef)parentPrivate;
3028
3029 fail :
3030
3031 CFRelease(parentPrivate);
3032 _SCErrorSet(kSCStatusInvalidArgument);
3033 return NULL;
3034 }
3035
3036
3037 static CFDictionaryRef
3038 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface,
3039 CFStringRef extendedType)
3040 {
3041 CFDictionaryRef config = NULL;
3042 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3043 CFArrayRef paths;
3044
3045 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3046 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3047
3048 paths = copyConfigurationPaths(interfacePrivate, extendedType);
3049 if (paths != NULL) {
3050 CFStringRef path;
3051
3052 path = CFArrayGetValueAtIndex(paths, 0);
3053 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
3054
3055 CFRelease(paths);
3056 } else {
3057 if (interfacePrivate->unsaved != NULL) {
3058 config = CFDictionaryGetValue(interfacePrivate->unsaved, extendedType);
3059 if (config == (CFDictionaryRef)kCFNull) {
3060 config = NULL;
3061 }
3062 }
3063 }
3064
3065 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
3066 config = NULL;
3067 }
3068
3069 return config;
3070 }
3071
3072
3073 CFDictionaryRef
3074 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface)
3075 {
3076 CFDictionaryRef config;
3077 CFStringRef defaultType;
3078
3079 if (!isA_SCNetworkInterface(interface)) {
3080 _SCErrorSet(kSCStatusInvalidArgument);
3081 return NULL;
3082 }
3083
3084 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
3085 if (defaultType == NULL) {
3086 return NULL;
3087 }
3088
3089 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType);
3090 if (config == NULL) {
3091 if (CFEqual(defaultType, kSCEntNetAirPort)) {
3092 SCNetworkInterfacePrivateRef interfacePrivate;
3093 CFStringRef path;
3094
3095 // if AirPort interface, check for a per-service config
3096 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3097 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
3098 interfacePrivate->serviceID, // service
3099 kSCEntNetAirPort); // entity
3100 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
3101 CFRelease(path);
3102 }
3103 }
3104 if (config == NULL) {
3105 _SCErrorSet(kSCStatusOK);
3106 }
3107
3108 return config;
3109 }
3110
3111
3112 CFDictionaryRef
3113 SCNetworkInterfaceGetExtendedConfiguration(SCNetworkInterfaceRef interface,
3114 CFStringRef extendedType)
3115 {
3116 CFDictionaryRef config;
3117
3118 if (!isA_SCNetworkInterface(interface)) {
3119 _SCErrorSet(kSCStatusInvalidArgument);
3120 return NULL;
3121 }
3122
3123 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) {
3124 _SCErrorSet(kSCStatusInvalidArgument);
3125 return NULL;
3126 }
3127
3128 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType);
3129 if (config == NULL) {
3130 _SCErrorSet(kSCStatusOK);
3131 }
3132
3133 return config;
3134 }
3135
3136
3137 CFStringRef
3138 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface)
3139 {
3140 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3141
3142 if (!isA_SCNetworkInterface(interface)) {
3143 _SCErrorSet(kSCStatusInvalidArgument);
3144 return NULL;
3145 }
3146
3147 if ((interfacePrivate->interface != NULL) &&
3148 (interfacePrivate->interface != kSCNetworkInterfaceIPv4)) {
3149 _SCErrorSet(kSCStatusOK);
3150 return NULL;
3151 }
3152
3153 return interfacePrivate->entity_device;
3154 }
3155
3156
3157 CFStringRef
3158 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface)
3159 {
3160 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3161
3162 if (!isA_SCNetworkInterface(interface)) {
3163 _SCErrorSet(kSCStatusInvalidArgument);
3164 return NULL;
3165 }
3166
3167 if ((interfacePrivate->address != NULL) &&
3168 (interfacePrivate->addressString == NULL)) {
3169 uint8_t *bp;
3170 char *cp;
3171 CFIndex n;
3172 char mac[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
3173 char *mac_p = mac;
3174
3175 bp = (uint8_t *)CFDataGetBytePtr(interfacePrivate->address);
3176 n = CFDataGetLength(interfacePrivate->address) * 3;
3177
3178 if (n > sizeof(mac)) {
3179 mac_p = CFAllocatorAllocate(NULL, 0, n);
3180 }
3181
3182 for (cp = mac_p; n > 0; n -= 3) {
3183 cp += snprintf(cp, n, "%2.2x:", *bp++);
3184 }
3185
3186 interfacePrivate->addressString = CFStringCreateWithCString(NULL, mac_p, kCFStringEncodingUTF8);
3187 if (mac_p != mac) CFAllocatorDeallocate(NULL, mac_p);
3188 }
3189
3190 return interfacePrivate->addressString;
3191 }
3192
3193
3194 SCNetworkInterfaceRef
3195 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface)
3196 {
3197 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3198
3199 if (!isA_SCNetworkInterface(interface)) {
3200 _SCErrorSet(kSCStatusInvalidArgument);
3201 return NULL;
3202 }
3203
3204 return interfacePrivate->interface;
3205 }
3206
3207
3208 CFStringRef
3209 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface)
3210 {
3211 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3212
3213 if (!isA_SCNetworkInterface(interface)) {
3214 _SCErrorSet(kSCStatusInvalidArgument);
3215 return NULL;
3216 }
3217
3218 return interfacePrivate->interface_type;
3219 }
3220
3221
3222 static CFStringRef
3223 copy_interface_string(CFBundleRef bundle, CFStringRef key, Boolean localized)
3224 {
3225 CFStringRef str = NULL;
3226
3227 if (localized) {
3228 str = CFBundleCopyLocalizedString(bundle,
3229 key,
3230 key,
3231 NETWORKINTERFACE_LOCALIZATIONS);
3232 } else {
3233 str = _SC_CFBundleCopyNonLocalizedString(bundle,
3234 key,
3235 key,
3236 NETWORKINTERFACE_LOCALIZATIONS);
3237 }
3238
3239 return str;
3240 }
3241
3242
3243 static CFStringRef
3244 copy_display_name(SCNetworkInterfaceRef interface, Boolean localized)
3245 {
3246 CFMutableStringRef local;
3247 CFStringRef name;
3248
3249 local = CFStringCreateMutable(NULL, 0);
3250
3251 while (interface != NULL) {
3252 Boolean added = FALSE;
3253 SCNetworkInterfaceRef child = NULL;
3254 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3255
3256 if ((interfacePrivate->interface != NULL) &&
3257 (interfacePrivate->interface != kSCNetworkInterfaceIPv4)) {
3258 child = interfacePrivate->interface;
3259 }
3260
3261 if ((bundle != NULL) && (interfacePrivate->localized_key != NULL)) {
3262 CFStringRef fmt;
3263
3264 fmt = copy_interface_string(bundle, interfacePrivate->localized_key, localized);
3265 if (fmt != NULL) {
3266 CFStringAppendFormat(local,
3267 NULL,
3268 fmt,
3269 interfacePrivate->localized_arg1,
3270 interfacePrivate->localized_arg2);
3271 CFRelease(fmt);
3272 added = TRUE;
3273 }
3274 }
3275
3276 if (!added &&
3277 (interfacePrivate->prefs != NULL) &&
3278 (interfacePrivate->serviceID != NULL) &&
3279 (child == NULL)) {
3280 CFDictionaryRef entity;
3281 CFStringRef path;
3282
3283 // check for (and use) the name of the interface when it
3284 // was last available
3285 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,
3286 interfacePrivate->serviceID,
3287 kSCEntNetInterface);
3288 entity = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
3289 CFRelease(path);
3290 if (isA_CFDictionary(entity)) {
3291 CFStringRef name;
3292
3293 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
3294 if (isA_CFString(name)) {
3295 CFStringAppend(local, name);
3296 added = TRUE;
3297 }
3298 }
3299 }
3300
3301 if (!added) {
3302 // create (non-)localized name based on the interface type
3303 CFStringAppend(local, interfacePrivate->interface_type);
3304
3305 // ... and, if this is a leaf node, the interface device
3306 if ((interfacePrivate->entity_device != NULL) && (child == NULL)) {
3307 CFStringAppendFormat(local, NULL, CFSTR(" (%@)"), interfacePrivate->entity_device);
3308 }
3309 }
3310
3311 if (child != NULL) {
3312 // if this interface is layered over another
3313 CFStringAppend(local, CFSTR(" --> "));
3314 }
3315
3316 interface = child;
3317 }
3318
3319 name = CFStringCreateCopy(NULL, local);
3320 CFRelease(local);
3321
3322 return name;
3323 }
3324
3325
3326 __private_extern__
3327 CFStringRef
3328 __SCNetworkInterfaceGetNonLocalizedDisplayName(SCNetworkInterfaceRef interface)
3329 {
3330 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3331
3332 if (!isA_SCNetworkInterface(interface)) {
3333 _SCErrorSet(kSCStatusInvalidArgument);
3334 return NULL;
3335 }
3336
3337 if (interfacePrivate->name == NULL) {
3338 interfacePrivate->name = copy_display_name(interface, FALSE);
3339 }
3340
3341 return interfacePrivate->name;
3342 }
3343
3344
3345 CFStringRef
3346 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface)
3347 {
3348 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3349
3350 if (!isA_SCNetworkInterface(interface)) {
3351 _SCErrorSet(kSCStatusInvalidArgument);
3352 return NULL;
3353 }
3354
3355 if (interfacePrivate->localized_name == NULL) {
3356 interfacePrivate->localized_name = copy_display_name(interface, TRUE);
3357 }
3358
3359 return interfacePrivate->localized_name;
3360 }
3361
3362
3363 __private_extern__
3364 CFDictionaryRef
3365 __SCNetworkInterfaceGetTemplateOverrides(SCNetworkInterfaceRef interface, CFStringRef interfaceType)
3366 {
3367 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3368 CFDictionaryRef overrides = NULL;
3369
3370 if (interfacePrivate->overrides != NULL) {
3371 overrides = CFDictionaryGetValue(interfacePrivate->overrides, interfaceType);
3372 }
3373
3374 return overrides;
3375 }
3376
3377
3378 CFTypeID
3379 SCNetworkInterfaceGetTypeID(void)
3380 {
3381 pthread_once(&initialized, __SCNetworkInterfaceInitialize); /* initialize runtime */
3382 return __kSCNetworkInterfaceTypeID;
3383 }
3384
3385
3386 __private_extern__
3387 Boolean
3388 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface,
3389 CFStringRef extendedType,
3390 CFDictionaryRef config,
3391 Boolean okToHold)
3392 {
3393 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3394 Boolean ok = FALSE;
3395 CFArrayRef paths;
3396
3397 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3398 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3399
3400 if (extendedType == NULL) {
3401 extendedType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
3402 if (extendedType == NULL) {
3403 return FALSE;
3404 }
3405 }
3406
3407 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
3408 config = NULL;
3409 }
3410
3411 paths = copyConfigurationPaths(interfacePrivate, extendedType);
3412 if (paths != NULL) {
3413 CFIndex i;
3414 CFIndex n;
3415
3416 n = CFArrayGetCount(paths);
3417 for (i = 0; i < n; i++) {
3418 CFStringRef path;
3419
3420 path = CFArrayGetValueAtIndex(paths, i);
3421 ok = __setPrefsConfiguration(interfacePrivate->prefs, path, config, FALSE);
3422 if (!ok) {
3423 break;
3424 }
3425 }
3426
3427 if (ok) {
3428 // if configuration has been saved
3429 if (interfacePrivate->unsaved != NULL) {
3430 CFDictionaryRemoveValue(interfacePrivate->unsaved, extendedType);
3431 if (CFDictionaryGetCount(interfacePrivate->unsaved) == 0) {
3432 CFRelease(interfacePrivate->unsaved);
3433 interfacePrivate->unsaved = NULL;
3434 }
3435 }
3436 }
3437
3438 CFRelease(paths);
3439 } else {
3440 if (okToHold) {
3441 if (config == NULL) {
3442 // remember that we are clearing the configuration
3443 config = (CFDictionaryRef)kCFNull;
3444 }
3445
3446 if (interfacePrivate->unsaved == NULL) {
3447 interfacePrivate->unsaved = CFDictionaryCreateMutable(NULL,
3448 0,
3449 &kCFTypeDictionaryKeyCallBacks,
3450 &kCFTypeDictionaryValueCallBacks);
3451 }
3452 CFDictionarySetValue(interfacePrivate->unsaved, extendedType, config);
3453 ok = TRUE;
3454 } else {
3455 _SCErrorSet(kSCStatusNoKey);
3456 }
3457 }
3458
3459 return ok;
3460 }
3461
3462
3463 Boolean
3464 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config)
3465 {
3466 CFStringRef defaultType;
3467
3468 if (!isA_SCNetworkInterface(interface)) {
3469 _SCErrorSet(kSCStatusInvalidArgument);
3470 return FALSE;
3471 }
3472
3473 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
3474 if (defaultType == NULL) {
3475 return FALSE;
3476 }
3477
3478 return __SCNetworkInterfaceSetConfiguration(interface, defaultType, config, FALSE);
3479 }
3480
3481
3482 Boolean
3483 SCNetworkInterfaceSetExtendedConfiguration(SCNetworkInterfaceRef interface,
3484 CFStringRef extendedType,
3485 CFDictionaryRef config)
3486 {
3487 if (!isA_SCNetworkInterface(interface)) {
3488 _SCErrorSet(kSCStatusInvalidArgument);
3489 return FALSE;
3490 }
3491
3492 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) {
3493 return FALSE;
3494 }
3495
3496 return __SCNetworkInterfaceSetConfiguration(interface, extendedType, config, FALSE);
3497 }
3498
3499
3500 #pragma mark -
3501 #pragma mark SCNetworkInterface [Refresh Configuration] API
3502
3503
3504 #ifndef kSCEntNetRefreshConfiguration
3505 #define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration")
3506 #endif // kSCEntNetRefreshConfiguration
3507
3508 Boolean
3509 _SCNetworkInterfaceForceConfigurationRefresh(CFStringRef ifName)
3510 {
3511 CFStringRef key;
3512 Boolean ok = FALSE;
3513 SCDynamicStoreRef store;
3514
3515 if (!isA_CFString(ifName)) {
3516 _SCErrorSet(kSCStatusInvalidArgument);
3517 return FALSE;
3518 }
3519
3520 store = SCDynamicStoreCreate(NULL, CFSTR("_SCNetworkInterfaceForceConfigurationRefresh"), NULL, NULL);
3521 if (store == NULL) {
3522 return FALSE;
3523 }
3524
3525 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
3526 kSCDynamicStoreDomainState,
3527 ifName,
3528 kSCEntNetRefreshConfiguration);
3529 ok = SCDynamicStoreNotifyValue(store, key);
3530 CFRelease(key);
3531 CFRelease(store);
3532 return ok;
3533 }
3534
3535
3536 static Boolean
3537 __SCNetworkInterfaceForceConfigurationRefresh_helper(SCPreferencesRef prefs, CFStringRef ifName)
3538 {
3539 CFDataRef data = NULL;
3540 Boolean ok;
3541 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
3542 uint32_t status = kSCStatusOK;
3543 CFDataRef reply = NULL;
3544
3545 if (prefsPrivate->helper == -1) {
3546 ok = __SCPreferencesCreate_helper(prefs);
3547 if (!ok) {
3548 return FALSE;
3549 }
3550 }
3551
3552 // serialize the interface name
3553 ok = _SCSerializeString(ifName, &data, NULL, NULL);
3554 if (!ok) {
3555 goto fail;
3556 }
3557
3558 // have the helper "refresh" the configuration
3559 status = kSCStatusOK;
3560 reply = NULL;
3561 ok = _SCHelperExec(prefsPrivate->helper,
3562 SCHELPER_MSG_INTERFACE_REFRESH,
3563 data,
3564 &status,
3565 NULL);
3566 if (data != NULL) CFRelease(data);
3567 if (!ok) {
3568 goto fail;
3569 }
3570
3571 if (status != kSCStatusOK) {
3572 goto error;
3573 }
3574
3575 return TRUE;
3576
3577 fail :
3578
3579 // close helper
3580 if (prefsPrivate->helper != -1) {
3581 _SCHelperClose(prefsPrivate->helper);
3582 prefsPrivate->helper = -1;
3583 }
3584
3585 status = kSCStatusAccessError;
3586
3587 error :
3588
3589 // return error
3590 _SCErrorSet(status);
3591 return FALSE;
3592 }
3593
3594
3595 Boolean
3596 SCNetworkInterfaceForceConfigurationRefresh(SCNetworkInterfaceRef interface)
3597 {
3598 CFStringRef ifName;
3599 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3600
3601 if (!isA_SCNetworkInterface(interface)) {
3602 _SCErrorSet(kSCStatusInvalidArgument);
3603 return FALSE;
3604 }
3605
3606 ifName = SCNetworkInterfaceGetBSDName(interface);
3607 if (ifName == NULL) {
3608 _SCErrorSet(kSCStatusInvalidArgument);
3609 return FALSE;
3610 }
3611
3612 if (interfacePrivate->prefs != NULL) {
3613 SCPreferencesRef prefs = interfacePrivate->prefs;
3614 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
3615
3616 if (prefsPrivate->authorizationData != NULL) {
3617 return __SCNetworkInterfaceForceConfigurationRefresh_helper(prefs, ifName);
3618 }
3619 }
3620
3621 return _SCNetworkInterfaceForceConfigurationRefresh(ifName);
3622 }
3623
3624
3625 Boolean
3626 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName)
3627 {
3628 return _SCNetworkInterfaceForceConfigurationRefresh(ifName);
3629 }
3630
3631
3632 #pragma mark -
3633 #pragma mark SCNetworkInterface Password APIs
3634
3635
3636 static CFStringRef
3637 getPasswordID(CFDictionaryRef config, CFStringRef serviceID)
3638 {
3639 CFStringRef unique_id = NULL;
3640
3641 if (config != NULL) {
3642 CFStringRef encryption;
3643
3644 encryption = CFDictionaryGetValue(config, kSCPropNetPPPAuthPasswordEncryption);
3645 if (isA_CFString(encryption) &&
3646 CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
3647 unique_id = CFDictionaryGetValue(config, kSCPropNetPPPAuthPassword);
3648 }
3649 }
3650 if (unique_id == NULL) {
3651 unique_id = serviceID;
3652 }
3653
3654 return unique_id;
3655 }
3656
3657
3658 static CFStringRef
3659 copySharedSecretID(CFDictionaryRef config, CFStringRef serviceID)
3660 {
3661 CFMutableStringRef sharedSecret = NULL;
3662
3663 if (config != NULL) {
3664 CFStringRef encryption;
3665
3666 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecretEncryption);
3667 if (isA_CFString(encryption) &&
3668 CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
3669 sharedSecret = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecret);
3670 if (sharedSecret != NULL) {
3671 CFRetain(sharedSecret);
3672 }
3673 }
3674 }
3675
3676 if (sharedSecret == NULL) {
3677 CFStringRef unique_id;
3678
3679 unique_id = getPasswordID(config, serviceID);
3680 sharedSecret = CFStringCreateMutableCopy(NULL, 0, unique_id);
3681 CFStringAppend(sharedSecret, CFSTR(".SS"));
3682 }
3683
3684 return sharedSecret;
3685 }
3686
3687
3688 static Boolean
3689 checkInterfacePassword(SCNetworkInterfaceRef interface,
3690 SCNetworkInterfacePasswordType passwordType,
3691 SCPreferencesRef *prefs,
3692 CFStringRef *serviceID)
3693 {
3694 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3695
3696 if (!isA_SCNetworkInterface(interface)) {
3697 _SCErrorSet(kSCStatusInvalidArgument);
3698 return FALSE;
3699 }
3700
3701 *serviceID = interfacePrivate->serviceID;
3702 if (*serviceID == NULL) {
3703 _SCErrorSet(kSCStatusInvalidArgument);
3704 return FALSE;
3705 }
3706
3707 *prefs = interfacePrivate->prefs;
3708 if (*prefs == NULL) {
3709 _SCErrorSet(kSCStatusInvalidArgument);
3710 return FALSE;
3711 }
3712
3713 switch (passwordType) {
3714 case kSCNetworkInterfacePasswordTypePPP : {
3715 CFStringRef interfaceType;
3716
3717 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
3718 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
3719 _SCErrorSet(kSCStatusInvalidArgument);
3720 return FALSE;
3721 }
3722 break;
3723 }
3724
3725 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
3726 CFStringRef interfaceType;
3727
3728 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
3729 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
3730 _SCErrorSet(kSCStatusInvalidArgument);
3731 return FALSE;
3732 }
3733
3734 interface = SCNetworkInterfaceGetInterface(interface);
3735 if (interface == NULL) {
3736 _SCErrorSet(kSCStatusInvalidArgument);
3737 return FALSE;
3738 }
3739
3740 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
3741 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
3742 _SCErrorSet(kSCStatusInvalidArgument);
3743 return FALSE;
3744 }
3745 break;
3746 }
3747
3748 case kSCNetworkInterfacePasswordTypeEAPOL : {
3749 break;
3750 }
3751
3752 default :
3753 break;
3754 }
3755
3756 return TRUE;
3757 }
3758
3759
3760 Boolean
3761 SCNetworkInterfaceCheckPassword(SCNetworkInterfaceRef interface,
3762 SCNetworkInterfacePasswordType passwordType)
3763 {
3764 Boolean exists = FALSE;
3765 SCPreferencesRef prefs = NULL;
3766 CFStringRef serviceID = NULL;
3767
3768 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
3769 return FALSE;
3770 }
3771
3772 switch (passwordType) {
3773 case kSCNetworkInterfacePasswordTypePPP : {
3774 CFDictionaryRef config;
3775 CFStringRef unique_id;
3776
3777 // get configuration
3778 config = SCNetworkInterfaceGetConfiguration(interface);
3779
3780 // get serviceID
3781 unique_id = getPasswordID(config, serviceID);
3782
3783 // check
3784 exists = __extract_password(prefs,
3785 config,
3786 kSCPropNetPPPAuthPassword,
3787 kSCPropNetPPPAuthPasswordEncryption,
3788 kSCValNetPPPAuthPasswordEncryptionKeychain,
3789 unique_id,
3790 NULL);
3791 break;
3792 }
3793
3794 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
3795 CFDictionaryRef config;
3796 CFStringRef shared_id;
3797
3798 // get configuration
3799 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
3800
3801 // get sharedSecret ID
3802 shared_id = copySharedSecretID(config, serviceID);
3803
3804 // check
3805 exists = __extract_password(prefs,
3806 config,
3807 kSCPropNetIPSecSharedSecret,
3808 kSCPropNetIPSecSharedSecretEncryption,
3809 kSCValNetIPSecSharedSecretEncryptionKeychain,
3810 shared_id,
3811 NULL);
3812 CFRelease(shared_id);
3813 break;
3814 }
3815
3816 case kSCNetworkInterfacePasswordTypeEAPOL : {
3817 CFDictionaryRef config;
3818 CFStringRef unique_id = NULL;
3819
3820 // get configuration
3821 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
3822
3823 // get 802.1X identifier
3824 if (config != NULL) {
3825 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
3826 }
3827 if (!isA_CFString(unique_id)) {
3828 return FALSE;
3829 }
3830
3831 // check password
3832 exists = _SCPreferencesSystemKeychainPasswordItemExists(prefs, unique_id);
3833 break;
3834 }
3835
3836 default :
3837 _SCErrorSet(kSCStatusInvalidArgument);
3838 return FALSE;
3839 }
3840
3841 return exists;
3842 }
3843
3844
3845 CFDataRef
3846 SCNetworkInterfaceCopyPassword(SCNetworkInterfaceRef interface,
3847 SCNetworkInterfacePasswordType passwordType)
3848 {
3849 CFDataRef password = NULL;
3850 SCPreferencesRef prefs = NULL;
3851 CFStringRef serviceID = NULL;
3852
3853 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
3854 return NULL;
3855 }
3856
3857 switch (passwordType) {
3858 case kSCNetworkInterfacePasswordTypePPP : {
3859 CFDictionaryRef config;
3860 CFStringRef unique_id;
3861
3862 // get configuration
3863 config = SCNetworkInterfaceGetConfiguration(interface);
3864
3865 // get serviceID
3866 unique_id = getPasswordID(config, serviceID);
3867
3868 // extract
3869 (void) __extract_password(prefs,
3870 config,
3871 kSCPropNetPPPAuthPassword,
3872 kSCPropNetPPPAuthPasswordEncryption,
3873 kSCValNetPPPAuthPasswordEncryptionKeychain,
3874 unique_id,
3875 &password);
3876 break;
3877 }
3878
3879 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
3880 CFDictionaryRef config;
3881 CFStringRef shared_id;
3882
3883 // get configuration
3884 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
3885
3886 // get sharedSecret ID
3887 shared_id = copySharedSecretID(config, serviceID);
3888
3889 // extract
3890 (void) __extract_password(prefs,
3891 config,
3892 kSCPropNetIPSecSharedSecret,
3893 kSCPropNetIPSecSharedSecretEncryption,
3894 kSCValNetIPSecSharedSecretEncryptionKeychain,
3895 shared_id,
3896 &password);
3897
3898 CFRelease(shared_id);
3899 break;
3900 }
3901
3902 case kSCNetworkInterfacePasswordTypeEAPOL : {
3903 CFDictionaryRef config;
3904 CFStringRef unique_id = NULL;
3905
3906 // get configuration
3907 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
3908
3909 // get 802.1X identifier
3910 if (config != NULL) {
3911 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
3912 }
3913 if (!isA_CFString(unique_id)) {
3914 _SCErrorSet(kSCStatusFailed);
3915 return NULL;
3916 }
3917
3918 // copy password
3919 password = _SCPreferencesSystemKeychainPasswordItemCopy(prefs, unique_id);
3920 break;
3921 }
3922
3923 default :
3924 _SCErrorSet(kSCStatusInvalidArgument);
3925 return NULL;
3926 }
3927
3928 return password;
3929 }
3930
3931
3932 Boolean
3933 SCNetworkInterfaceRemovePassword(SCNetworkInterfaceRef interface,
3934 SCNetworkInterfacePasswordType passwordType)
3935 {
3936 Boolean ok = FALSE;
3937 SCPreferencesRef prefs = NULL;
3938 CFStringRef serviceID = NULL;
3939
3940 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
3941 return FALSE;
3942 }
3943
3944 switch (passwordType) {
3945 case kSCNetworkInterfacePasswordTypePPP : {
3946 CFDictionaryRef config;
3947 CFStringRef unique_id;
3948
3949 // get configuration
3950 config = SCNetworkInterfaceGetConfiguration(interface);
3951
3952 // get serviceID
3953 unique_id = getPasswordID(config, serviceID);
3954
3955 // remove password
3956 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, unique_id);
3957 if (ok) {
3958 CFMutableDictionaryRef newConfig;
3959
3960 if (config != NULL) {
3961 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
3962 CFDictionaryRemoveValue(newConfig, kSCPropNetPPPAuthPassword);
3963 CFDictionaryRemoveValue(newConfig, kSCPropNetPPPAuthPasswordEncryption);
3964 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
3965 CFRelease(newConfig);
3966 }
3967 }
3968 break;
3969 }
3970
3971 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
3972 CFDictionaryRef config;
3973 CFStringRef shared_id;
3974
3975 // get configuration
3976 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
3977
3978 // get sharedSecret ID
3979 shared_id = copySharedSecretID(config, serviceID);
3980
3981 // remove password
3982 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, shared_id);
3983 if (ok) {
3984 CFMutableDictionaryRef newConfig;
3985
3986 if (config != NULL) {
3987 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
3988 CFDictionaryRemoveValue(newConfig, kSCPropNetIPSecSharedSecret);
3989 CFDictionaryRemoveValue(newConfig, kSCPropNetIPSecSharedSecretEncryption);
3990 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
3991 kSCEntNetIPSec,
3992 newConfig);
3993 CFRelease(newConfig);
3994 }
3995 }
3996
3997 CFRelease(shared_id);
3998 break;
3999 }
4000
4001 case kSCNetworkInterfacePasswordTypeEAPOL : {
4002 CFDictionaryRef config;
4003 CFStringRef unique_id = NULL;
4004
4005 // get configuration
4006 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
4007
4008 // get 802.1X identifier
4009 if (config != NULL) {
4010 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
4011 }
4012 if (!isA_CFString(unique_id)) {
4013 _SCErrorSet(kSCStatusFailed);
4014 return FALSE;
4015 }
4016
4017 // remove password
4018 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, unique_id);
4019 break;
4020 }
4021
4022 default :
4023 _SCErrorSet(kSCStatusInvalidArgument);
4024 return FALSE;
4025 }
4026
4027 return ok;
4028 }
4029
4030
4031 Boolean
4032 SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface,
4033 SCNetworkInterfacePasswordType passwordType,
4034 CFDataRef password,
4035 CFDictionaryRef options)
4036 {
4037 CFStringRef account = NULL;
4038 CFDictionaryRef config;
4039 CFStringRef description = NULL;
4040 CFStringRef label = NULL;
4041 Boolean ok = FALSE;
4042 SCPreferencesRef prefs = NULL;
4043 CFStringRef serviceID = NULL;
4044
4045 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
4046 return FALSE;
4047 }
4048
4049 switch (passwordType) {
4050 case kSCNetworkInterfacePasswordTypePPP : {
4051 SCNetworkServiceRef service = NULL;
4052 CFStringRef unique_id;
4053
4054 // get configuration
4055 config = SCNetworkInterfaceGetConfiguration(interface);
4056
4057 // get serviceID
4058 unique_id = getPasswordID(config, serviceID);
4059
4060 // get "Account", "Name", "Kind"
4061 if (config != NULL) {
4062 // auth name --> keychain "Account"
4063 account = CFDictionaryGetValue(config, kSCPropNetPPPAuthName);
4064
4065 // PPP [user defined] "name" --> keychain "Name"
4066 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
4067 }
4068
4069 if (label == NULL) {
4070 // service name --> keychain "Name"
4071 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
4072 prefs,
4073 serviceID,
4074 interface);
4075
4076 label = SCNetworkServiceGetName(service);
4077 if (label == NULL) {
4078 // interface name --> keychain "Name"
4079 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
4080 }
4081 }
4082
4083 if (bundle != NULL) {
4084 // "PPP Password" --> keychain "Kind"
4085 description = CFBundleCopyLocalizedString(bundle,
4086 CFSTR("KEYCHAIN_PPP_PASSWORD"),
4087 CFSTR("PPP Password"),
4088 NULL);
4089 }
4090
4091 // store password
4092 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
4093 unique_id,
4094 (label != NULL) ? label : CFSTR("PPP"),
4095 (description != NULL) ? description : CFSTR("PPP Password"),
4096 account,
4097 password,
4098 options);
4099 if (ok) {
4100 CFMutableDictionaryRef newConfig;
4101
4102 if (config != NULL) {
4103 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
4104 } else {
4105 newConfig = CFDictionaryCreateMutable(NULL,
4106 0,
4107 &kCFTypeDictionaryKeyCallBacks,
4108 &kCFTypeDictionaryValueCallBacks);
4109 }
4110 CFDictionarySetValue(newConfig,
4111 kSCPropNetPPPAuthPassword,
4112 unique_id);
4113 CFDictionarySetValue(newConfig,
4114 kSCPropNetPPPAuthPasswordEncryption,
4115 kSCValNetPPPAuthPasswordEncryptionKeychain);
4116 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
4117 CFRelease(newConfig);
4118 }
4119
4120 if (description != NULL) CFRelease(description);
4121 if (service != NULL) CFRelease(service);
4122 break;
4123 }
4124
4125 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
4126 SCNetworkServiceRef service = NULL;
4127 CFStringRef shared_id;
4128
4129 // get configuration
4130 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
4131
4132 // get sharedSecret ID
4133 shared_id = copySharedSecretID(config, serviceID);
4134
4135 // get "Name", "Kind"
4136 if (config != NULL) {
4137 // PPP [user defined] "name" --> keychain "Name"
4138 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
4139 }
4140
4141 if (label == NULL) {
4142 // service name --> keychain "Name"
4143 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
4144 prefs,
4145 serviceID,
4146 interface);
4147
4148 label = SCNetworkServiceGetName(service);
4149 if (label == NULL) {
4150 // interface name --> keychain "Name"
4151 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
4152 }
4153 }
4154
4155 if (bundle != NULL) {
4156 // "IPSec Shared Secret" --> keychain "Kind"
4157 description = CFBundleCopyLocalizedString(bundle,
4158 CFSTR("KEYCHAIN_IPSEC_SHARED_SECRET"),
4159 CFSTR("IPSec Shared Secret"),
4160 NULL);
4161 }
4162
4163 // set password
4164 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
4165 shared_id,
4166 (label != NULL) ? label : CFSTR("PPP"),
4167 (description != NULL) ? description : CFSTR("IPSec Shared Secret"),
4168 NULL,
4169 password,
4170 options);
4171 if (ok) {
4172 CFMutableDictionaryRef newConfig = NULL;
4173
4174 if (config != NULL) {
4175 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
4176 } else {
4177 newConfig = CFDictionaryCreateMutable(NULL,
4178 0,
4179 &kCFTypeDictionaryKeyCallBacks,
4180 &kCFTypeDictionaryValueCallBacks);
4181 }
4182 CFDictionarySetValue(newConfig,
4183 kSCPropNetIPSecSharedSecret,
4184 shared_id);
4185 CFDictionarySetValue(newConfig,
4186 kSCPropNetIPSecSharedSecretEncryption,
4187 kSCValNetIPSecSharedSecretEncryptionKeychain);
4188 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
4189 kSCEntNetIPSec,
4190 newConfig);
4191 CFRelease(newConfig);
4192 }
4193
4194 if (description != NULL) CFRelease(description);
4195 if (service != NULL) CFRelease(service);
4196 CFRelease(shared_id);
4197 break;
4198 }
4199
4200 case kSCNetworkInterfacePasswordTypeEAPOL : {
4201 CFStringRef unique_id = NULL;
4202
4203 // get configuration
4204 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
4205
4206 // get 802.1X identifier
4207 if (config != NULL) {
4208 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
4209 }
4210 if (isA_CFString(unique_id)) {
4211 CFRetain(unique_id);
4212 } else {
4213 CFUUIDRef uuid;
4214
4215 uuid = CFUUIDCreate(NULL);
4216 unique_id = CFUUIDCreateString(NULL, uuid);
4217 CFRelease(uuid);
4218 }
4219
4220 // get "Name", "Kind"
4221 if (bundle != NULL) {
4222 // "802.1X Password" --> keychain "Name"
4223 label = CFBundleCopyLocalizedString(bundle,
4224 CFSTR("KEYCHAIN_EAPOL_PASSWORD"),
4225 CFSTR("802.1X Password"),
4226 NULL);
4227 // "Internet Connect" --> keychain "Kind"
4228 description = CFBundleCopyLocalizedString(bundle,
4229 CFSTR("KEYCHAIN_INTERNET_CONNECT"),
4230 CFSTR("Internet Connect"),
4231 NULL);
4232 }
4233
4234 // set password
4235 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
4236 unique_id,
4237 (label != NULL) ? label : CFSTR("802.1X Password"),
4238 (description != NULL) ? description : CFSTR("Internet Connect"),
4239 NULL,
4240 password,
4241 options);
4242 if (ok) {
4243 CFMutableDictionaryRef newConfig = NULL;
4244
4245 if (config != NULL) {
4246 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
4247 } else {
4248 newConfig = CFDictionaryCreateMutable(NULL,
4249 0,
4250 &kCFTypeDictionaryKeyCallBacks,
4251 &kCFTypeDictionaryValueCallBacks);
4252 }
4253 CFDictionarySetValue(newConfig,
4254 kEAPClientPropUserPasswordKeychainItemID,
4255 unique_id);
4256 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
4257 kSCEntNetEAPOL,
4258 newConfig);
4259 CFRelease(newConfig);
4260 }
4261
4262 CFRelease(unique_id);
4263 if (label != NULL) CFRelease(label);
4264 if (description != NULL) CFRelease(description);
4265 break;
4266 }
4267
4268 default :
4269 _SCErrorSet(kSCStatusInvalidArgument);
4270 break;
4271 }
4272
4273 return ok;
4274 }
4275
4276
4277 #pragma mark -
4278 #pragma mark SCNetworkInterface [InterfaceNamer] SPIs
4279
4280
4281 SCNetworkInterfaceRef
4282 _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj)
4283 {
4284 SCNetworkInterfaceRef interface;
4285
4286 /* initialize runtime */
4287 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
4288
4289 interface = createInterface(if_obj, processNetworkInterface);
4290 return interface;
4291 }
4292
4293
4294 CFDataRef
4295 _SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface)
4296 {
4297 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4298
4299 return interfacePrivate->address;
4300 }
4301
4302
4303 CFNumberRef
4304 _SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface)
4305 {
4306 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4307
4308 return interfacePrivate->type;
4309 }
4310
4311
4312 CFNumberRef
4313 _SCNetworkInterfaceGetIOInterfaceUnit(SCNetworkInterfaceRef interface)
4314 {
4315 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4316
4317 return interfacePrivate->unit;
4318 }
4319
4320
4321 CFStringRef
4322 _SCNetworkInterfaceGetIOPath(SCNetworkInterfaceRef interface)
4323 {
4324 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4325
4326 return interfacePrivate->path;
4327 }
4328
4329
4330 Boolean
4331 _SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface)
4332 {
4333 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4334
4335 return interfacePrivate->builtin;
4336 }
4337
4338
4339 #pragma mark -
4340 #pragma mark SCNetworkInterface SPIs
4341
4342 Boolean
4343 _SCNetworkInterfaceIsModemV92(SCNetworkInterfaceRef interface)
4344 {
4345 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4346
4347 return interfacePrivate->modemIsV92;
4348 }
4349
4350
4351 #pragma mark -
4352 #pragma mark SCNetworkInterface [internal] SPIs
4353
4354
4355 __private_extern__
4356 SCNetworkInterfacePrivateRef
4357 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator,
4358 SCNetworkInterfaceRef interface,
4359 SCPreferencesRef prefs,
4360 CFStringRef serviceID)
4361 {
4362 SCNetworkInterfacePrivateRef oldPrivate = (SCNetworkInterfacePrivateRef)interface;
4363 SCNetworkInterfacePrivateRef newPrivate;
4364
4365 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4366 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
4367
4368 newPrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, prefs, serviceID, NULL);
4369 newPrivate->interface_type = oldPrivate->interface_type;
4370 if (oldPrivate->interface != NULL) {
4371 newPrivate->interface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, // allocator
4372 oldPrivate->interface, // interface
4373 prefs, // [new] prefs
4374 serviceID); // [new] serviceID
4375 }
4376 if (oldPrivate->name != NULL) {
4377 newPrivate->name = CFRetain(oldPrivate->name);
4378 }
4379 if (oldPrivate->localized_name != NULL) {
4380 newPrivate->localized_name = CFRetain(oldPrivate->localized_name);
4381 }
4382 newPrivate->localized_key = oldPrivate->localized_key;
4383 if (oldPrivate->localized_arg1 != NULL) {
4384 newPrivate->localized_arg1 = CFRetain(oldPrivate->localized_arg1);
4385 }
4386 if (oldPrivate->localized_arg2 != NULL) {
4387 newPrivate->localized_arg2 = CFRetain(oldPrivate->localized_arg2);
4388 }
4389 if (oldPrivate->unsaved != NULL) {
4390 newPrivate->unsaved = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->unsaved);
4391 }
4392 if (oldPrivate->entity_device != NULL) {
4393 newPrivate->entity_device = CFRetain(oldPrivate->entity_device);
4394 }
4395 newPrivate->entity_type = oldPrivate->entity_type;
4396 newPrivate->entity_subtype = oldPrivate->entity_subtype;
4397 if (oldPrivate->supported_interface_types != NULL) {
4398 newPrivate->supported_interface_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_interface_types);
4399 }
4400 if (oldPrivate->supported_protocol_types != NULL) {
4401 newPrivate->supported_protocol_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_protocol_types);
4402 }
4403 if (oldPrivate->address != NULL) {
4404 newPrivate->address = CFRetain(oldPrivate->address);
4405 }
4406 newPrivate->builtin = oldPrivate->builtin;
4407 if (oldPrivate->location != NULL) {
4408 newPrivate->location = CFRetain(oldPrivate->location);
4409 }
4410 if (oldPrivate->path != NULL) {
4411 newPrivate->path = CFRetain(oldPrivate->path);
4412 }
4413 if (oldPrivate->overrides != NULL) {
4414 newPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->overrides);
4415 }
4416 newPrivate->modemIsV92 = oldPrivate->modemIsV92;
4417 newPrivate->supportsBond = oldPrivate->supportsBond;
4418 newPrivate->supportsVLAN = oldPrivate->supportsVLAN;
4419 if (oldPrivate->type != NULL) {
4420 newPrivate->type = CFRetain(oldPrivate->type);
4421 }
4422 if (oldPrivate->unit != NULL) {
4423 newPrivate->unit = CFRetain(oldPrivate->unit);
4424 }
4425 newPrivate->sort_order = oldPrivate->sort_order;
4426 if (oldPrivate->bond.interfaces != NULL) {
4427 newPrivate->bond.interfaces = CFRetain(oldPrivate->bond.interfaces);
4428 }
4429 if (oldPrivate->bond.mode != NULL) {
4430 newPrivate->bond.mode = CFRetain(oldPrivate->bond.mode);
4431 }
4432 if (oldPrivate->bond.options != NULL) {
4433 newPrivate->bond.options = CFRetain(oldPrivate->bond.options);
4434 }
4435 if (oldPrivate->vlan.interface != NULL) {
4436 newPrivate->vlan.interface = CFRetain(oldPrivate->vlan.interface);
4437 }
4438 if (oldPrivate->vlan.tag != NULL) {
4439 newPrivate->vlan.tag = CFRetain(oldPrivate->vlan.tag);
4440 }
4441 if (oldPrivate->vlan.options != NULL) {
4442 newPrivate->vlan.options = CFRetain(oldPrivate->vlan.options);
4443 }
4444
4445 return newPrivate;
4446 }
4447
4448
4449 __private_extern__
4450 CFArrayRef
4451 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkInterfaceRef interface)
4452 {
4453 CFMutableArrayRef configs;
4454
4455 configs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
4456
4457 while (interface != NULL) {
4458 CFStringRef defaultType;
4459 CFMutableDictionaryRef interfaceConfiguration;
4460
4461 interfaceConfiguration = CFDictionaryCreateMutable(NULL,
4462 0,
4463 &kCFTypeDictionaryKeyCallBacks,
4464 &kCFTypeDictionaryValueCallBacks);
4465
4466 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
4467 if (defaultType != NULL) {
4468 CFDictionaryRef config;
4469 CFArrayRef extendedTypes;
4470
4471 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType);
4472 if (config == NULL) {
4473 config = (CFDictionaryRef)kCFNull;
4474 }
4475 CFDictionarySetValue(interfaceConfiguration, defaultType, config);
4476
4477 extendedTypes = extendedConfigurationTypes(interface);
4478 if (extendedTypes != NULL) {
4479 CFIndex i;
4480 CFIndex n;
4481
4482 n = CFArrayGetCount(extendedTypes);
4483 for (i = 0; i < n; i++) {
4484 CFStringRef extendedType;
4485
4486 extendedType = CFArrayGetValueAtIndex(extendedTypes, i);
4487 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType);
4488 if (config == NULL) {
4489 config = (CFDictionaryRef)kCFNull;
4490 }
4491 CFDictionarySetValue(interfaceConfiguration, extendedType, config);
4492 }
4493
4494 CFRelease(extendedTypes);
4495 }
4496 }
4497
4498 CFArrayAppendValue(configs, interfaceConfiguration);
4499 CFRelease(interfaceConfiguration);
4500
4501 interface = SCNetworkInterfaceGetInterface(interface);
4502 }
4503
4504 return configs;
4505 }
4506
4507
4508 __private_extern__
4509 void
4510 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkInterfaceRef interface, CFArrayRef configs)
4511 {
4512 CFIndex i;
4513
4514 for (i = 0; interface != NULL; i++) {
4515 CFStringRef defaultType;
4516 CFDictionaryRef interfaceConfiguration;
4517
4518 interfaceConfiguration = (configs != NULL) ? CFArrayGetValueAtIndex(configs, i) : NULL;
4519
4520 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
4521 if (defaultType != NULL) {
4522 CFDictionaryRef config;
4523 CFArrayRef extendedTypes;
4524
4525 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, defaultType)
4526 : NULL;
4527 if (config == (CFDictionaryRef)kCFNull) {
4528 config = NULL;
4529 }
4530 if (!__SCNetworkInterfaceSetConfiguration(interface, defaultType, config, TRUE)) {
4531 SCLog(TRUE, LOG_DEBUG,
4532 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
4533 interface,
4534 defaultType);
4535 }
4536
4537 extendedTypes = extendedConfigurationTypes(interface);
4538 if (extendedTypes != NULL) {
4539 CFIndex j;
4540 CFIndex n;
4541
4542 n = CFArrayGetCount(extendedTypes);
4543 for (j = 0; j < n; j++) {
4544 CFStringRef extendedType;
4545
4546 extendedType = CFArrayGetValueAtIndex(extendedTypes, j);
4547 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, extendedType)
4548 : NULL;
4549 if (config == (CFDictionaryRef)kCFNull) {
4550 config = NULL;
4551 }
4552 if (!__SCNetworkInterfaceSetConfiguration(interface, extendedType, config, TRUE)) {
4553 SCLog(TRUE, LOG_DEBUG,
4554 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
4555 interface,
4556 defaultType);
4557 }
4558 }
4559
4560 CFRelease(extendedTypes);
4561 }
4562 }
4563
4564 interface = SCNetworkInterfaceGetInterface(interface);
4565 }
4566
4567 return;
4568 }