]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkInterface.c
d695a6a889ec4bca9cdf4fc88c7a300eb32efdda
[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 }
1346 CFRelease(provider);
1347 }
1348
1349 if (interfacePrivate->localized_key == NULL) {
1350 // if no provider, not a PCI device, or no slot information
1351 interfacePrivate->localized_key = CFSTR("generic-ether");
1352 interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
1353 }
1354 }
1355
1356 break;
1357 case IFT_IEEE1394 :
1358 // Type
1359 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
1360
1361 // Entity
1362 interfacePrivate->entity_type = kSCEntNetFireWire;
1363
1364 // built-in
1365 interfacePrivate->builtin = isBuiltin(interface);
1366
1367 // sort order
1368 interfacePrivate->sort_order = kSortFireWire;
1369
1370 // localized name
1371 if (interfacePrivate->builtin) {
1372 interfacePrivate->localized_key = CFSTR("firewire");
1373 } else {
1374 CFStringRef slot_name;
1375
1376 slot_name = pci_slot(interface, NULL);
1377 if (slot_name != NULL) {
1378 interfacePrivate->localized_key = CFSTR("pci-firewire");
1379 interfacePrivate->localized_arg1 = slot_name;
1380 }
1381 }
1382
1383 break;
1384 default :
1385 SCLog(TRUE, LOG_DEBUG, CFSTR("processNetworkInterface() failed, unknown interface type = %d"), ift);
1386 return FALSE;
1387 }
1388
1389 // Device
1390 interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
1391
1392 // Hardware (MAC) address
1393 data = CFDictionaryGetValue(controller_dict, CFSTR(kIOMACAddress));
1394 if (isA_CFData(data)) {
1395 interfacePrivate->address = CFRetain(data);
1396 }
1397
1398 // interface unit
1399 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceUnit));
1400 if (isA_CFNumber(num) &&
1401 CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
1402 interfacePrivate->unit = CFRetain(num);
1403 }
1404
1405 return TRUE;
1406 }
1407
1408
1409 static void
1410 set_connection_script(SCNetworkInterfacePrivateRef interfacePrivate, CFStringRef script)
1411 {
1412 CFDictionaryRef dict;
1413 CFMutableDictionaryRef newDict;
1414
1415 if (interfacePrivate->overrides == NULL) {
1416 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1417 0,
1418 &kCFTypeDictionaryKeyCallBacks,
1419 &kCFTypeDictionaryValueCallBacks);
1420 }
1421
1422 dict = CFDictionaryGetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
1423 if (dict != NULL) {
1424 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
1425 } else {
1426 newDict = CFDictionaryCreateMutable(NULL,
1427 0,
1428 &kCFTypeDictionaryKeyCallBacks,
1429 &kCFTypeDictionaryValueCallBacks);
1430 }
1431 if (script != NULL) {
1432 CFDictionarySetValue(newDict, kSCPropNetModemConnectionScript, script);
1433 } else {
1434 CFDictionaryRemoveValue(newDict, kSCPropNetModemConnectionScript);
1435 }
1436 if (CFDictionaryGetCount(newDict) > 0) {
1437 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem, newDict);
1438 } else {
1439 CFDictionaryRemoveValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem);
1440 }
1441 CFRelease(newDict);
1442
1443 if (CFDictionaryGetCount(interfacePrivate->overrides) == 0) {
1444 CFRelease(interfacePrivate->overrides);
1445 interfacePrivate->overrides = NULL;
1446 }
1447 return;
1448 }
1449
1450
1451 static Boolean
1452 is_valid_connection_script(CFStringRef script)
1453 {
1454 char ccl[MAXPATHLEN];
1455 char path[MAXPATHLEN];
1456 NSSearchPathEnumerationState state;
1457
1458 (void) _SC_cfstring_to_cstring(script,
1459 ccl,
1460 sizeof(ccl),
1461 kCFStringEncodingUTF8);
1462
1463 state = NSStartSearchPathEnumeration(NSLibraryDirectory,
1464 NSLocalDomainMask|NSSystemDomainMask);
1465 while ((state = NSGetNextSearchPathEnumeration(state, path))) {
1466 size_t n;
1467 struct stat statBuf;
1468
1469 if (ccl[0] == '/') {
1470 path[0] = '\0'; // if modemCCL is a full path
1471 } else {
1472 strlcat(path, "/Modem Scripts/", sizeof(path));
1473 }
1474 strlcat(path, ccl, sizeof(path));
1475
1476 if (stat(path, &statBuf) != 0) {
1477 if (errno == ENOENT) {
1478 goto bundle;
1479 }
1480
1481 SCLog(TRUE, LOG_DEBUG,
1482 CFSTR("processSerialInterface stat() failed: %s"),
1483 strerror(errno));
1484 continue;
1485 }
1486 if (S_ISREG(statBuf.st_mode)) {
1487 // if we have a valid CCL script
1488 return TRUE;
1489 }
1490
1491 #define BUNDLE_EXT ".ccl"
1492 #define BUNDLE_EXT_LEN sizeof(BUNDLE_EXT) - 1
1493
1494 bundle :
1495
1496 n = strlen(path);
1497 if ((n <= BUNDLE_EXT_LEN) ||
1498 (strstr(&path[n - BUNDLE_EXT_LEN], BUNDLE_EXT) == NULL)) {
1499 strlcat(path, BUNDLE_EXT, sizeof(path));
1500 if (stat(path, &statBuf) != 0) {
1501 if (errno == ENOENT) {
1502 continue;
1503 }
1504
1505 SCLog(TRUE, LOG_DEBUG,
1506 CFSTR("processSerialInterface stat() failed: %s"),
1507 strerror(errno));
1508 continue;
1509 }
1510 }
1511 if (S_ISDIR(statBuf.st_mode)) {
1512 // if we have a valid CCL bundle
1513 return TRUE;
1514 }
1515 }
1516
1517 return FALSE;
1518 }
1519
1520
1521 static Boolean
1522 processSerialInterface(SCNetworkInterfacePrivateRef interfacePrivate,
1523 io_registry_entry_t interface,
1524 CFDictionaryRef interface_dict,
1525 io_registry_entry_t controller,
1526 CFDictionaryRef controller_dict,
1527 io_registry_entry_t bus,
1528 CFDictionaryRef bus_dict)
1529 {
1530 CFStringRef ift;
1531 Boolean isModem = FALSE;
1532 CFStringRef modemCCL = NULL;
1533 CFStringRef str;
1534 CFTypeRef val;
1535
1536 // check if hidden
1537 val = IORegistryEntrySearchCFProperty(interface,
1538 kIOServicePlane,
1539 CFSTR("HiddenPort"),
1540 NULL,
1541 kIORegistryIterateRecursively | kIORegistryIterateParents);
1542 if (val != NULL) {
1543 CFRelease(val);
1544 return FALSE; // if this interface should not be exposed
1545 }
1546
1547 // Type
1548 str = CFDictionaryGetValue(interface_dict, CFSTR(kIOTTYBaseNameKey));
1549 if (str == NULL) {
1550 return FALSE;
1551 }
1552
1553 /*
1554 * From MoreSCF:
1555 *
1556 * Exclude ports named "irda" because otherwise the IrDA ports on the
1557 * original iMac (rev's A through D) show up as serial ports. Given
1558 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
1559 * even support it, these ports definitely shouldn't be listed.
1560 */
1561 if (CFStringCompare(str,
1562 CFSTR("irda"),
1563 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
1564 return FALSE;
1565 }
1566
1567 if (IOStringValueHasPrefix(str, CFSTR("bluetooth"))) {
1568 // Bluetooth
1569 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
1570 interfacePrivate->sort_order = kSortBluetooth;
1571 } else if (IOStringValueHasPrefix(str, CFSTR("irda-ircomm"))) {
1572 // IrDA
1573 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
1574 interfacePrivate->sort_order = kSortIrDA;
1575 } else if (IOStringValueHasPrefix(str, CFSTR("wwan"))) {
1576 // WWAN
1577 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN;
1578 interfacePrivate->sort_order = kSortWWAN;
1579 } else {
1580 // Modem
1581 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
1582 interfacePrivate->sort_order = kSortModem;
1583
1584 // V.92 support
1585 val = IORegistryEntrySearchCFProperty(interface,
1586 kIOServicePlane,
1587 CFSTR(kIODeviceSupportsHoldKey),
1588 NULL,
1589 kIORegistryIterateRecursively | kIORegistryIterateParents);
1590 if (val != NULL) {
1591 uint32_t v92;
1592
1593 if (isA_CFNumber(val) &&
1594 CFNumberGetValue(val, kCFNumberSInt32Type, &v92)) {
1595 interfacePrivate->modemIsV92 = (v92 == 1);
1596 }
1597 CFRelease(val);
1598 }
1599 }
1600
1601 // Entity (Type)
1602 interfacePrivate->entity_type = kSCEntNetModem;
1603
1604 // Entity (Hardware)
1605 ift = CFDictionaryGetValue(interface_dict, CFSTR(kIOSerialBSDTypeKey));
1606 if (!isA_CFString(ift)) {
1607 return FALSE;
1608 }
1609
1610 if (CFEqual(ift, CFSTR(kIOSerialBSDModemType))) {
1611 // if modem
1612 isModem = TRUE;
1613
1614 if (CFEqual(str, CFSTR("modem"))) {
1615 interfacePrivate->builtin = TRUE;
1616 interfacePrivate->sort_order = kSortInternalModem;
1617 } else if (CFEqual(str, CFSTR("usbmodem"))) {
1618 interfacePrivate->sort_order = kSortUSBModem;
1619 }
1620 } else if (CFEqual(ift, CFSTR(kIOSerialBSDRS232Type))) {
1621 // if serial port
1622 interfacePrivate->sort_order = kSortSerialPort;
1623 } else {
1624 return FALSE;
1625 }
1626
1627 // Entity (Device)
1628 interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYDeviceKey));
1629
1630 // configuration template overrides
1631 val = IORegistryEntrySearchCFProperty(interface,
1632 kIOServicePlane,
1633 CFSTR("DevicePPPOverrides"),
1634 NULL,
1635 kIORegistryIterateRecursively | kIORegistryIterateParents);
1636 if (val != NULL) {
1637 if (isA_CFDictionary(val)) {
1638 if (interfacePrivate->overrides == NULL) {
1639 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1640 0,
1641 &kCFTypeDictionaryKeyCallBacks,
1642 &kCFTypeDictionaryValueCallBacks);
1643 }
1644 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypePPP, val);
1645 }
1646 CFRelease(val);
1647 }
1648
1649 val = IORegistryEntrySearchCFProperty(interface,
1650 kIOServicePlane,
1651 CFSTR("DeviceModemOverrides"),
1652 NULL,
1653 kIORegistryIterateRecursively | kIORegistryIterateParents);
1654 if (val != NULL) {
1655 if (isA_CFDictionary(val)) {
1656 if (interfacePrivate->overrides == NULL) {
1657 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL,
1658 0,
1659 &kCFTypeDictionaryKeyCallBacks,
1660 &kCFTypeDictionaryValueCallBacks);
1661 }
1662 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem, val);
1663
1664 modemCCL = CFDictionaryGetValue(val, kSCPropNetModemConnectionScript);
1665 modemCCL = isA_CFString(modemCCL);
1666 }
1667 CFRelease(val);
1668 }
1669
1670 // modem CCL
1671 if (modemCCL == NULL) {
1672 val = IORegistryEntrySearchCFProperty(interface,
1673 kIOServicePlane,
1674 CFSTR("ModemCCL"),
1675 NULL,
1676 kIORegistryIterateRecursively | kIORegistryIterateParents);
1677 if (val != NULL) {
1678 modemCCL = IOCopyCFStringValue(val);
1679 if (modemCCL != NULL) {
1680 set_connection_script(interfacePrivate, modemCCL);
1681 CFRelease(modemCCL);
1682 }
1683
1684 CFRelease(val);
1685 }
1686 }
1687
1688 // localized name
1689 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIrDA)) {
1690 interfacePrivate->localized_key = CFSTR("irda");
1691 } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBluetooth)) {
1692 interfacePrivate->localized_key = CFSTR("bluetooth");
1693 } else {
1694 CFStringRef localized = NULL;
1695 CFStringRef name = NULL;
1696 CFMutableStringRef port;
1697
1698 port = CFStringCreateMutableCopy(NULL, 0, str);
1699 CFStringLowercase(port, NULL);
1700
1701 if (!isModem) {
1702 CFStringAppend(port, CFSTR("-port"));
1703 }
1704
1705 // set non-localized name
1706 if (bundle != NULL) {
1707 name = copy_interface_string(bundle, port, FALSE);
1708 }
1709 if (name != NULL) {
1710 if (!CFEqual(port, name)) {
1711 // if [English] localization available
1712 interfacePrivate->name = name;
1713 } else {
1714 // if no [English] localization available, use TTY base name
1715 CFRelease(name);
1716 interfacePrivate->name = CFStringCreateCopy(NULL, str);
1717 }
1718 } else {
1719 interfacePrivate->name = CFStringCreateCopy(NULL, str);
1720 }
1721
1722 // set localized name
1723 if (bundle != NULL) {
1724 localized = copy_interface_string(bundle, port, TRUE);
1725 }
1726 if (localized != NULL) {
1727 if (!CFEqual(port, localized)) {
1728 // if localization available
1729 interfacePrivate->localized_name = localized;
1730 } else {
1731 // if no localization available, use TTY base name
1732 CFRelease(localized);
1733 interfacePrivate->localized_name = CFStringCreateCopy(NULL, str);
1734 }
1735 } else {
1736 interfacePrivate->localized_name = CFStringCreateCopy(NULL, str);
1737 }
1738
1739 if (!isModem || !CFEqual(str, CFSTR("modem"))) {
1740 CFStringRef productName;
1741
1742 // check if a "Product Name" has been provided
1743 val = IORegistryEntrySearchCFProperty(interface,
1744 kIOServicePlane,
1745 CFSTR(kIOPropertyProductNameKey),
1746 NULL,
1747 kIORegistryIterateRecursively | kIORegistryIterateParents);
1748 if (val != NULL) {
1749 productName = IOCopyCFStringValue(val);
1750 CFRelease(val);
1751
1752 if (productName != NULL) {
1753 if (CFStringGetLength(productName) > 0) {
1754 // if we have a [somewhat reasonable?] product name
1755 if (interfacePrivate->name != NULL) {
1756 CFRelease(interfacePrivate->name);
1757 }
1758 interfacePrivate->name = CFRetain(productName);
1759 if (interfacePrivate->localized_name != NULL) {
1760 CFRelease(interfacePrivate->localized_name);
1761 }
1762 interfacePrivate->localized_name = CFRetain(productName);
1763
1764 // if not provided, also check if the product name
1765 // matches a CCL script
1766 if ((modemCCL == NULL) &&
1767 is_valid_connection_script(productName)) {
1768 set_connection_script(interfacePrivate, productName);
1769 modemCCL = productName;
1770 }
1771 }
1772
1773 CFRelease(productName);
1774 }
1775 }
1776 }
1777
1778 CFRelease(port);
1779 }
1780
1781 return TRUE;
1782 }
1783
1784
1785 static SCNetworkInterfaceRef
1786 createInterface(io_registry_entry_t interface, processInterface func)
1787 {
1788 io_registry_entry_t bus = MACH_PORT_NULL;
1789 CFMutableDictionaryRef bus_dict = NULL;
1790 io_registry_entry_t controller = MACH_PORT_NULL;
1791 CFMutableDictionaryRef controller_dict = NULL;
1792 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
1793 CFMutableDictionaryRef interface_dict = NULL;
1794 kern_return_t kr;
1795 io_string_t path;
1796
1797 kr = IORegistryEntryGetPath(interface, kIOServicePlane, path);
1798 if (kr != kIOReturnSuccess) {
1799 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetPath() failed, kr = 0x%x"), kr);
1800 goto done;
1801 }
1802
1803 kr = IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions);
1804 if (kr != kIOReturnSuccess) {
1805 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
1806 goto done;
1807 }
1808
1809 /* get the controller node */
1810 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &controller);
1811 if (kr != KERN_SUCCESS) {
1812 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
1813 goto done;
1814 }
1815
1816 /* get the dictionary associated with the node */
1817 kr = IORegistryEntryCreateCFProperties(controller, &controller_dict, NULL, kNilOptions);
1818 if (kr != KERN_SUCCESS) {
1819 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
1820 goto done;
1821 }
1822
1823 /* get the bus node */
1824 kr = IORegistryEntryGetParentEntry(controller, kIOServicePlane, &bus);
1825 if (kr != KERN_SUCCESS) {
1826 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
1827 goto done;
1828 }
1829
1830 /* get the dictionary associated with the node */
1831 kr = IORegistryEntryCreateCFProperties(bus, &bus_dict, NULL, kNilOptions);
1832 if (kr != KERN_SUCCESS) {
1833 SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
1834 goto done;
1835 }
1836
1837 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL, path);
1838
1839 if (!(*func)(interfacePrivate, interface, interface_dict, controller, controller_dict, bus, bus_dict)) {
1840 CFRelease(interfacePrivate);
1841 interfacePrivate = NULL;
1842 }
1843
1844 done :
1845
1846 if (interface_dict != NULL) CFRelease(interface_dict);
1847
1848 if (controller != MACH_PORT_NULL) IOObjectRelease(controller);
1849 if (controller_dict != NULL) CFRelease(controller_dict);
1850
1851 if (bus != MACH_PORT_NULL) IOObjectRelease(bus);
1852 if (bus_dict != NULL) CFRelease(bus_dict);
1853
1854 return (SCNetworkInterfaceRef)interfacePrivate;
1855 }
1856
1857
1858 static CFArrayRef
1859 findMatchingInterfaces(CFDictionaryRef matching, processInterface func)
1860 {
1861 CFMutableArrayRef interfaces;
1862 io_registry_entry_t interface;
1863 kern_return_t kr;
1864 io_iterator_t iterator = MACH_PORT_NULL;
1865
1866 kr = IOServiceGetMatchingServices(masterPort, matching, &iterator);
1867 if (kr != kIOReturnSuccess) {
1868 SCLog(TRUE, LOG_DEBUG, CFSTR("findMatchingInterfaces IOServiceGetMatchingServices() failed, kr = 0x%x"), kr);
1869 return NULL;
1870 }
1871
1872 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1873
1874 while ((interface = IOIteratorNext(iterator)) != MACH_PORT_NULL) {
1875 SCNetworkInterfaceRef match;
1876
1877 match = createInterface(interface, func);
1878 if (match != NULL) {
1879 CFArrayAppendValue(interfaces, match);
1880 CFRelease(match);
1881 }
1882
1883 IOObjectRelease(interface);
1884 }
1885
1886 IOObjectRelease(iterator);
1887
1888 return interfaces;
1889 }
1890
1891
1892 #pragma mark -
1893 #pragma mark helper functions
1894
1895
1896 static CFIndex
1897 findConfiguration(CFStringRef interface_type)
1898 {
1899 CFIndex i;
1900
1901 for (i = 0; i < sizeof(configurations)/sizeof(configurations[0]); i++) {
1902 if (CFEqual(interface_type, *configurations[i].interface_type)) {
1903 return i;
1904 }
1905 }
1906
1907 return kCFNotFound;
1908 }
1909
1910
1911 __private_extern__
1912 CFStringRef
1913 __SCNetworkInterfaceGetDefaultConfigurationType(SCNetworkInterfaceRef interface)
1914 {
1915 CFIndex interfaceIndex;
1916 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
1917
1918 if (interfacePrivate->serviceID == NULL) {
1919 // if not associated with a service (yet)
1920 _SCErrorSet(kSCStatusInvalidArgument);
1921 return NULL;
1922 }
1923
1924 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
1925 if (interfaceIndex == kCFNotFound) {
1926 // unknown interface type, use per-service configuration preferences
1927 return interfacePrivate->interface_type; // entity
1928 }
1929
1930 if (configurations[interfaceIndex].entity_hardware != NULL) {
1931 // if configuration information can be associated with this interface type
1932 return *configurations[interfaceIndex].entity_hardware;
1933 }
1934
1935 _SCErrorSet(kSCStatusInvalidArgument);
1936 return NULL;
1937 }
1938
1939
1940 __private_extern__
1941 Boolean
1942 __SCNetworkInterfaceIsValidExtendedConfigurationType(SCNetworkInterfaceRef interface,
1943 CFStringRef extendedType,
1944 Boolean requirePerInterface)
1945 {
1946 CFStringRef defaultType;
1947 CFIndex extendedIndex;
1948 CFIndex interfaceIndex;
1949 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
1950 Boolean ok = FALSE;
1951
1952 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
1953 if (defaultType == NULL) {
1954 goto done;
1955 }
1956
1957 if (CFEqual(extendedType, defaultType)) {
1958 // extended and default configuration types cannot conflict
1959 goto done;
1960 }
1961
1962 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
1963 if (interfaceIndex == kCFNotFound) {
1964 // configuration information for unknown interface type's
1965 // are stored along with the service and we don't allow
1966 // per-service extended configurations
1967 goto done;
1968 }
1969
1970 // It turns out that, for PPP interfaces, we want to be able to store
1971 // some extended interface configuration (e.g. IPSec [for L2TP]). For
1972 // now, I'm commenting out the following test.
1973 //
1974 // if (requirePerInterface && !configurations[interfaceIndex].per_interface_config) {
1975 // // we don't allow per-service extended configurations
1976 // goto done;
1977 // }
1978
1979 extendedIndex = findConfiguration(extendedType);
1980 if (extendedIndex != kCFNotFound) {
1981 // extended type cannot match a known interface type
1982 goto done;
1983 }
1984
1985 /*
1986 * ???
1987 * Do we match specific/known extended configuration types (e.g. EAPOL)
1988 * and ensure that any non-standard extended configuration types be of
1989 * the form com.myCompany.myType?
1990 * ???
1991 */
1992
1993 ok = TRUE;
1994
1995 done :
1996
1997 if (!ok) {
1998 _SCErrorSet(kSCStatusInvalidArgument);
1999 }
2000 return ok;
2001 }
2002
2003
2004 typedef struct {
2005 CFStringRef defaultType;
2006 CFMutableArrayRef types;
2007 } extendedConfiguration, *extendedConfigurationRef;
2008
2009
2010 static void
2011 __addExtendedConfigurationType(const void *key, const void *value, void *context)
2012 {
2013 CFStringRef extendedType = (CFStringRef)key;
2014 extendedConfigurationRef myContextRef = (extendedConfigurationRef)context;
2015
2016 if (CFEqual(extendedType, myContextRef->defaultType)) {
2017 // do not include the default configuration type
2018 return;
2019 }
2020
2021 if (CFArrayContainsValue(myContextRef->types,
2022 CFRangeMake(0, CFArrayGetCount(myContextRef->types)),
2023 extendedType)) {
2024 // if extendedType already has already been added
2025 return;
2026 }
2027
2028 CFArrayAppendValue(myContextRef->types, extendedType);
2029
2030 return;
2031 }
2032
2033
2034 static CFArrayRef
2035 extendedConfigurationTypes(SCNetworkInterfaceRef interface)
2036 {
2037 CFIndex i;
2038 CFIndex interfaceIndex;
2039 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2040 extendedConfiguration myContext;
2041 SCNetworkServiceRef service;
2042 CFArrayRef sets;
2043 CFIndex n;
2044
2045 myContext.defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
2046 if (myContext.defaultType == NULL) {
2047 myContext.types = NULL;
2048 goto done;
2049 }
2050
2051 myContext.types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2052
2053 if (interfacePrivate->serviceID == NULL) {
2054 // if not associated with a service (yet)
2055 goto done;
2056 }
2057
2058 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2059 if (interfaceIndex == kCFNotFound) {
2060 // we don't allow per-service extended configurations
2061 goto done;
2062 }
2063
2064 if (!configurations[interfaceIndex].per_interface_config) {
2065 // known interface type but we still don't allow
2066 // per-service extended configurations
2067 goto done;
2068 }
2069
2070 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
2071 interfacePrivate->prefs,
2072 interfacePrivate->serviceID,
2073 interface);
2074
2075 sets = SCNetworkSetCopyAll(interfacePrivate->prefs);
2076 n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
2077
2078 for (i = 0; i < n; i++) {
2079 CFDictionaryRef configs;
2080 Boolean found;
2081 CFStringRef path;
2082 CFArrayRef services;
2083 SCNetworkSetRef set;
2084
2085 set = CFArrayGetValueAtIndex(sets, i);
2086 services = SCNetworkSetCopyServices(set);
2087 found = CFArrayContainsValue(services,
2088 CFRangeMake(0, CFArrayGetCount(services)),
2089 service);
2090 CFRelease(services);
2091
2092 if (!found) {
2093 continue;
2094 }
2095
2096 // add stored extended configuration types
2097 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
2098 SCNetworkSetGetSetID(set), // set
2099 interfacePrivate->entity_device, // service
2100 NULL); // entity
2101 configs = __getPrefsConfiguration(interfacePrivate->prefs, path);
2102 CFRelease(path);
2103 if (isA_CFDictionary(configs)) {
2104 CFDictionaryApplyFunction(configs,
2105 __addExtendedConfigurationType,
2106 &myContext);
2107 }
2108
2109 // add not-yet-stored extended configuration types
2110 if (interfacePrivate->unsaved != NULL) {
2111 CFDictionaryApplyFunction(interfacePrivate->unsaved,
2112 __addExtendedConfigurationType,
2113 &myContext);
2114 }
2115
2116 break;
2117 }
2118
2119 CFRelease(service);
2120 if (sets != NULL) CFRelease(sets);
2121
2122 done :
2123
2124 return myContext.types;
2125 }
2126
2127
2128 static CFArrayRef
2129 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate,
2130 CFStringRef extendedType)
2131 {
2132 CFMutableArrayRef array;
2133 CFIndex i;
2134 CFIndex interfaceIndex;
2135 CFIndex n;
2136 CFStringRef path;
2137 SCNetworkServiceRef service;
2138 CFArrayRef sets;
2139
2140 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2141
2142 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2143 if (interfaceIndex == kCFNotFound) {
2144 // unknown interface type, use per-service configuration preferences
2145 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
2146 interfacePrivate->serviceID, // service
2147 extendedType); // entity
2148 CFArrayAppendValue(array, path);
2149 CFRelease(path);
2150 return array;
2151 }
2152
2153 if (!configurations[interfaceIndex].per_interface_config) {
2154 // known interface type, per-service configuration preferences
2155 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
2156 interfacePrivate->serviceID, // service
2157 extendedType); // entity
2158 CFArrayAppendValue(array, path);
2159 CFRelease(path);
2160 return array;
2161 }
2162
2163 // known interface type, per-interface configuration preferences
2164 //
2165 // 1. look for all sets which contain the associated service
2166 // 2. add a per-set path for the interface configuration for
2167 // each set.
2168
2169 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
2170 interfacePrivate->prefs,
2171 interfacePrivate->serviceID,
2172 (SCNetworkInterfaceRef)interfacePrivate);
2173
2174 sets = SCNetworkSetCopyAll(interfacePrivate->prefs);
2175 n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
2176
2177 for (i = 0; i < n; i++) {
2178 CFArrayRef services;
2179 SCNetworkSetRef set;
2180
2181 set = CFArrayGetValueAtIndex(sets, i);
2182 services = SCNetworkSetCopyServices(set);
2183 if (CFArrayContainsValue(services,
2184 CFRangeMake(0, CFArrayGetCount(services)),
2185 service)) {
2186 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
2187 SCNetworkSetGetSetID(set), // set
2188 interfacePrivate->entity_device, // service
2189 extendedType); // entity
2190 CFArrayAppendValue(array, path);
2191 CFRelease(path);
2192 }
2193 CFRelease(services);
2194 }
2195
2196 if (CFArrayGetCount(array) == 0) {
2197 CFRelease(array);
2198 array = NULL;
2199 }
2200
2201 CFRelease(service);
2202 if (sets != NULL) CFRelease(sets);
2203 return array;
2204 }
2205
2206
2207 #pragma mark -
2208 #pragma mark SCNetworkInterface <--> preferences entity
2209
2210
2211 __private_extern__
2212 CFDictionaryRef
2213 __SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface)
2214 {
2215 CFMutableDictionaryRef entity;
2216 CFIndex interfaceIndex;
2217 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2218
2219 entity = CFDictionaryCreateMutable(NULL,
2220 0,
2221 &kCFTypeDictionaryKeyCallBacks,
2222 &kCFTypeDictionaryValueCallBacks);
2223 if (interfacePrivate->entity_type != NULL) {
2224 CFDictionarySetValue(entity,
2225 kSCPropNetInterfaceType,
2226 interfacePrivate->entity_type);
2227 }
2228 if (interfacePrivate->entity_subtype != NULL) {
2229 CFDictionarySetValue(entity,
2230 kSCPropNetInterfaceSubType,
2231 interfacePrivate->entity_subtype);
2232 }
2233 if (interfacePrivate->entity_device != NULL) {
2234 CFDictionarySetValue(entity,
2235 kSCPropNetInterfaceDeviceName,
2236 interfacePrivate->entity_device);
2237 }
2238
2239 // match the "hardware" with the lowest layer
2240 while (TRUE) {
2241 SCNetworkInterfaceRef nextInterface;
2242
2243 nextInterface = SCNetworkInterfaceGetInterface(interface);
2244 if (nextInterface == NULL) {
2245 break;
2246 }
2247
2248 interface = nextInterface;
2249 }
2250 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2251
2252 interfaceIndex = findConfiguration(interfacePrivate->interface_type);
2253 if (interfaceIndex != kCFNotFound) {
2254 if (configurations[interfaceIndex].entity_hardware != NULL) {
2255 CFDictionarySetValue(entity,
2256 kSCPropNetInterfaceHardware,
2257 *configurations[interfaceIndex].entity_hardware);
2258 }
2259 } else {
2260 CFDictionarySetValue(entity,
2261 kSCPropNetInterfaceHardware,
2262 interfacePrivate->interface_type);
2263 }
2264
2265 // add the localized display name (which will only be used when/if the
2266 // interface is removed from the system)
2267 CFDictionarySetValue(entity,
2268 kSCPropUserDefinedName,
2269 SCNetworkInterfaceGetLocalizedDisplayName(interface));
2270
2271 // note that this is a V.92 capable modem
2272 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeModem) &&
2273 interfacePrivate->modemIsV92) {
2274 int one = 1;
2275 CFNumberRef num;
2276
2277 num = CFNumberCreate(NULL, kCFNumberIntType, &one);
2278 CFDictionarySetValue(entity,
2279 kSCPropNetInterfaceSupportsModemOnHold,
2280 num);
2281 CFRelease(num);
2282 }
2283
2284 return entity;
2285 }
2286
2287
2288 static SCNetworkInterfaceRef
2289 findInterface(CFArrayRef interfaces, CFStringRef match_if)
2290 {
2291 CFIndex i;
2292 CFIndex n;
2293
2294 n = CFArrayGetCount(interfaces);
2295 for (i = 0; i < n; i++) {
2296 SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(interfaces, i);
2297 CFStringRef interfaceName;
2298
2299 interfaceName = SCNetworkInterfaceGetBSDName(interface);
2300 if ((interfaceName != NULL) && CFEqual(interfaceName, match_if)) {
2301 CFRetain(interface);
2302 return interface;
2303 }
2304 }
2305
2306 return NULL;
2307 }
2308
2309
2310 static SCNetworkInterfaceRef
2311 findBondInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
2312 {
2313 CFArrayRef bonds;
2314 SCNetworkInterfaceRef interface = NULL;
2315
2316 if (prefs == NULL) {
2317 return (NULL);
2318 }
2319
2320 // check if the interface is an Ethernet Bond
2321 bonds = SCBondInterfaceCopyAll(prefs);
2322 if (bonds != NULL) {
2323 interface = findInterface(bonds, ifDevice);
2324 CFRelease(bonds);
2325 }
2326 return interface;
2327 }
2328
2329 static SCNetworkInterfaceRef
2330 findVLANInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
2331 {
2332 SCNetworkInterfaceRef interface = NULL;
2333 CFArrayRef vlans;
2334
2335 if (prefs == NULL) {
2336 return (NULL);
2337 }
2338
2339 // check if the interface is a VLAN
2340 vlans = SCVLANInterfaceCopyAll(prefs);
2341 if (vlans != NULL) {
2342 interface = findInterface(vlans, ifDevice);
2343 CFRelease(vlans);
2344 }
2345 return interface;
2346 }
2347
2348
2349 SCNetworkInterfaceRef
2350 _SCNetworkInterfaceCreateWithBSDName(CFAllocatorRef allocator,
2351 CFStringRef bsdName,
2352 UInt32 flags)
2353 {
2354 CFMutableDictionaryRef entity;
2355 SCNetworkInterfaceRef interface;
2356
2357 entity = CFDictionaryCreateMutable(NULL,
2358 0,
2359 &kCFTypeDictionaryKeyCallBacks,
2360 &kCFTypeDictionaryValueCallBacks);
2361 CFDictionarySetValue(entity, kSCPropNetInterfaceDeviceName, bsdName);
2362 if ((flags & kIncludeVLANInterfaces) == 0) {
2363 CFDictionarySetValue(entity, CFSTR("_NO_VLAN_INTERFACES_"), kCFBooleanTrue);
2364 }
2365 if ((flags & kIncludeBondInterfaces) == 0) {
2366 CFDictionarySetValue(entity, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue);
2367 }
2368 interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL);
2369 CFRelease(entity);
2370
2371 return interface;
2372 }
2373
2374
2375 SCNetworkInterfaceRef
2376 _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator,
2377 CFDictionaryRef interface_entity,
2378 SCNetworkServiceRef service)
2379 {
2380 SCNetworkInterfacePrivateRef interfacePrivate = NULL;
2381 CFStringRef ifDevice;
2382 CFStringRef ifSubType;
2383 CFStringRef ifType;
2384 CFArrayRef matching_interfaces = NULL;
2385
2386 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2387 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
2388
2389 ifType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceType);
2390 if (ifType == NULL) {
2391 /*
2392 * The interface "Type" was not specified. We'll make an
2393 * assumption that this is an "Ethernet" interface. If a
2394 * real interface exists with the provided interface name
2395 * then the actual type will be set accordingly. If not, we'll
2396 * end up crafting an "Ethernet" SCNetworkInterface which
2397 * will keep the rest of the configuration APIs happy.
2398 */
2399 ifType = kSCValNetInterfaceTypeEthernet;
2400 }
2401
2402 if (!isA_CFString(ifType)) {
2403 return NULL;
2404 }
2405
2406 ifSubType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceSubType);
2407 if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2408 if (!isA_CFString(ifSubType)) {
2409 return NULL;
2410 }
2411 }
2412
2413 ifDevice = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceDeviceName);
2414
2415 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet) ||
2416 CFEqual(ifType, kSCValNetInterfaceTypeFireWire) ||
2417 (CFEqual(ifType, kSCValNetInterfaceTypePPP) && CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE))) {
2418 char bsdName[IFNAMSIZ + 1];
2419 CFMutableDictionaryRef matching;
2420
2421 if (!isA_CFString(ifDevice)) {
2422 return NULL;
2423 }
2424
2425 if (_SC_cfstring_to_cstring(ifDevice, bsdName, sizeof(bsdName), kCFStringEncodingASCII) == NULL) {
2426 goto done;
2427 }
2428
2429 matching = IOBSDNameMatching(masterPort, 0, bsdName);
2430 if (matching == NULL) {
2431 goto done;
2432 }
2433
2434 // note: the "matching" dictionary will be consumed by the following
2435 matching_interfaces = findMatchingInterfaces(matching, processNetworkInterface);
2436
2437 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2438 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
2439 CFDictionaryRef matching;
2440 CFStringRef match_keys[2];
2441 CFStringRef match_vals[2];
2442
2443 if (!isA_CFString(ifDevice)) {
2444 return NULL;
2445 }
2446
2447 match_keys[0] = CFSTR(kIOProviderClassKey);
2448 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
2449
2450 match_keys[1] = CFSTR(kIOTTYDeviceKey);
2451 match_vals[1] = ifDevice;
2452
2453 matching = CFDictionaryCreate(NULL,
2454 (const void **)match_keys,
2455 (const void **)match_vals,
2456 sizeof(match_keys)/sizeof(match_keys[0]),
2457 &kCFTypeDictionaryKeyCallBacks,
2458 &kCFTypeDictionaryValueCallBacks);
2459
2460 // note: the "matching" dictionary will be consumed by the following
2461 matching_interfaces = findMatchingInterfaces(matching, processSerialInterface);
2462
2463 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypeL2TP)) {
2464 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2465 kSCNetworkInterfaceTypeL2TP);
2466 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPTP)) {
2467 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2468 kSCNetworkInterfaceTypePPTP);
2469 } else {
2470 // XXX do we allow non-Apple variants of PPP??? XXX
2471 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2472 ifSubType);
2473 }
2474 } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) {
2475 if (!isA_CFString(ifDevice)) {
2476 return NULL;
2477 }
2478
2479 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2480 kSCNetworkInterfaceType6to4);
2481 } else if ((CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) && (ifDevice == NULL)) {
2482 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
2483 ifType);
2484 }
2485
2486 if (matching_interfaces != NULL) {
2487 CFIndex n;
2488 SCPreferencesRef prefs;
2489
2490 n = CFArrayGetCount(matching_interfaces);
2491 switch (n) {
2492 case 0 :
2493 if (!CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
2494 break;
2495 }
2496 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), NULL);
2497 if (prefs == NULL) {
2498 break;
2499 }
2500 if (!CFDictionaryContainsKey(interface_entity, CFSTR("_NO_VLAN_INTERFACES_"))) {
2501 interfacePrivate = (SCNetworkInterfacePrivateRef)findVLANInterface(prefs, ifDevice);
2502 }
2503 if ((interfacePrivate == NULL)
2504 && !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BOND_INTERFACES_"))) {
2505 interfacePrivate = (SCNetworkInterfacePrivateRef)findBondInterface(prefs, ifDevice);
2506 }
2507 CFRelease(prefs);
2508 break;
2509 case 1 :
2510 interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0);
2511 CFRetain(interfacePrivate);
2512 break;
2513 default :
2514 SCLog(TRUE, LOG_DEBUG, CFSTR("_SCNetworkInterfaceCreateWithEntity() failed, more than one interface matches %@"), ifDevice);
2515 CFRelease(matching_interfaces);
2516 _SCErrorSet(kSCStatusFailed);
2517 return NULL;
2518 }
2519 CFRelease(matching_interfaces);
2520 }
2521
2522 done :
2523
2524 if (interfacePrivate == NULL) {
2525 /*
2526 * if device not present on this system
2527 */
2528 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL, NULL);
2529 interfacePrivate->entity_type = ifType;
2530 interfacePrivate->entity_subtype = ifSubType;
2531 interfacePrivate->entity_device = (ifDevice != NULL) ? CFStringCreateCopy(NULL, ifDevice) : NULL;
2532
2533 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
2534 CFStringRef entity_hardware;
2535
2536 entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware);
2537 if ((entity_hardware != NULL) &&
2538 CFEqual(entity_hardware, kSCEntNetAirPort)) {
2539 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
2540 } else {
2541 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
2542 }
2543 } else if (CFEqual(ifType, kSCValNetInterfaceTypeFireWire)) {
2544 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
2545 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2546 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE)) {
2547 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
2548 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
2549 if (CFStringHasPrefix(ifDevice, CFSTR("Bluetooth"))) {
2550 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
2551 } else if (CFStringHasPrefix(ifDevice, CFSTR("irda"))) {
2552 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
2553 } else if (CFStringHasPrefix(ifDevice, CFSTR("wwan"))) {
2554 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN;
2555 } else {
2556 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
2557 }
2558 } else {
2559 // PPTP, L2TP, ...
2560 CFRelease(interfacePrivate);
2561 interfacePrivate = (SCNetworkInterfacePrivateRef)kSCNetworkInterfaceIPv4;
2562 CFRetain(interfacePrivate);
2563 }
2564 } else if (CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) {
2565 // if vendor interface
2566 interfacePrivate->interface_type = ifType;
2567 } else {
2568 // if unknown interface
2569 CFRelease(interfacePrivate);
2570 interfacePrivate = NULL;
2571 }
2572 }
2573
2574 if ((interfacePrivate != NULL) && (service != NULL)) {
2575 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
2576
2577 if (interfacePrivate->prefs != NULL)
2578 CFRelease(interfacePrivate->prefs);
2579 if (interfacePrivate->serviceID != NULL)
2580 CFRelease(interfacePrivate->serviceID);
2581
2582 interfacePrivate->prefs = CFRetain(servicePrivate->prefs);
2583 interfacePrivate->serviceID = CFRetain(servicePrivate->serviceID);
2584 }
2585
2586 if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
2587 SCNetworkInterfaceRef parent;
2588
2589 parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate,
2590 kSCNetworkInterfaceTypePPP);
2591 CFRelease(interfacePrivate);
2592 interfacePrivate = (SCNetworkInterfacePrivateRef)parent;
2593 }
2594
2595 return (SCNetworkInterfaceRef)interfacePrivate;
2596 }
2597
2598
2599 #pragma mark -
2600 #pragma mark SCNetworkInterface APIs
2601
2602
2603 __private_extern__
2604 CFArrayRef
2605 __SCNetworkInterfaceCopyAll_IONetworkInterface(void)
2606 {
2607 CFDictionaryRef matching;
2608 CFArrayRef new_interfaces;
2609
2610 // get Ethernet, Firewire, and AirPort interfaces
2611
2612 matching = IOServiceMatching(kIONetworkInterfaceClass);
2613 new_interfaces = findMatchingInterfaces(matching, processNetworkInterface);
2614
2615 return new_interfaces;
2616 }
2617
2618
2619 static
2620 CFArrayRef
2621 __SCNetworkInterfaceCopyAll_Modem()
2622 {
2623 CFDictionaryRef matching;
2624 CFStringRef match_keys[2];
2625 CFStringRef match_vals[2];
2626 CFArrayRef new_interfaces;
2627
2628 match_keys[0] = CFSTR(kIOProviderClassKey);
2629 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
2630
2631 match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
2632 match_vals[1] = CFSTR(kIOSerialBSDModemType);
2633
2634 matching = CFDictionaryCreate(NULL,
2635 (const void **)match_keys,
2636 (const void **)match_vals,
2637 sizeof(match_keys)/sizeof(match_keys[0]),
2638 &kCFTypeDictionaryKeyCallBacks,
2639 &kCFTypeDictionaryValueCallBacks);
2640 new_interfaces = findMatchingInterfaces(matching, processSerialInterface);
2641
2642 return new_interfaces;
2643 }
2644
2645
2646 static
2647 CFArrayRef
2648 __SCNetworkInterfaceCopyAll_RS232()
2649 {
2650 CFDictionaryRef matching;
2651 CFStringRef match_keys[2];
2652 CFStringRef match_vals[2];
2653 CFArrayRef new_interfaces;
2654
2655 match_keys[0] = CFSTR(kIOProviderClassKey);
2656 match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
2657
2658 match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
2659 match_vals[1] = CFSTR(kIOSerialBSDRS232Type);
2660
2661 matching = CFDictionaryCreate(NULL,
2662 (const void **)match_keys,
2663 (const void **)match_vals,
2664 sizeof(match_keys)/sizeof(match_keys[0]),
2665 &kCFTypeDictionaryKeyCallBacks,
2666 &kCFTypeDictionaryValueCallBacks);
2667 new_interfaces = findMatchingInterfaces(matching, processSerialInterface);
2668
2669 return new_interfaces;
2670 }
2671
2672
2673 static void
2674 add_interfaces(CFMutableArrayRef all_interfaces, CFArrayRef new_interfaces)
2675 {
2676 CFIndex i;
2677 CFIndex n;
2678
2679 n = CFArrayGetCount(new_interfaces);
2680 for (i = 0; i < n; i++) {
2681 CFStringRef bsdName;
2682 SCNetworkInterfaceRef interface;
2683
2684 interface = CFArrayGetValueAtIndex(new_interfaces, i);
2685 bsdName = SCNetworkInterfaceGetBSDName(interface);
2686 if (bsdName != NULL) {
2687 CFArrayAppendValue(all_interfaces, interface);
2688 }
2689 }
2690
2691 return;
2692 }
2693
2694
2695 static void
2696 __waitForInterfaces()
2697 {
2698 CFStringRef key;
2699 CFArrayRef keys;
2700 Boolean ok;
2701 SCDynamicStoreRef store;
2702
2703 store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL, NULL);
2704 if (store == NULL) {
2705 return;
2706 }
2707
2708 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin);
2709 keys = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
2710 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
2711 CFRelease(keys);
2712 if (!ok) {
2713 SCLog(TRUE, LOG_ERR,
2714 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"), SCErrorString(SCError()));
2715 goto done;
2716 }
2717
2718 while (TRUE) {
2719 CFDictionaryRef dict;
2720 Boolean quiet = FALSE;
2721
2722 // check if quiet
2723 dict = SCDynamicStoreCopyValue(store, key);
2724 if (dict != NULL) {
2725 if (isA_CFDictionary(dict) &&
2726 (CFDictionaryContainsKey(dict, CFSTR("*QUIET*")) ||
2727 CFDictionaryContainsKey(dict, CFSTR("*TIMEOUT*")))) {
2728 quiet = TRUE;
2729 }
2730 CFRelease(dict);
2731 }
2732 if (quiet) {
2733 break;
2734 }
2735
2736 ok = SCDynamicStoreNotifyWait(store);
2737 if (!ok) {
2738 SCLog(TRUE, LOG_ERR,
2739 CFSTR("SCDynamicStoreNotifyWait() failed: %s"), SCErrorString(SCError()));
2740 goto done;
2741 }
2742 }
2743
2744 done :
2745
2746 CFRelease(key);
2747 CFRelease(store);
2748 return;
2749 }
2750
2751
2752 CFArrayRef /* of SCNetworkInterfaceRef's */
2753 SCNetworkInterfaceCopyAll()
2754 {
2755 CFMutableArrayRef all_interfaces;
2756 CFArrayRef new_interfaces;
2757 SCPreferencesRef prefs;
2758
2759 /* initialize runtime */
2760 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
2761
2762 /* wait for IOKit to quiesce */
2763 pthread_once(&iokit_quiet, __waitForInterfaces);
2764
2765 all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2766
2767 // get Ethernet, Firewire, and AirPort interfaces
2768 new_interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
2769 if (new_interfaces != NULL) {
2770 add_interfaces(all_interfaces, new_interfaces);
2771 CFRelease(new_interfaces);
2772 }
2773
2774 // get Modem interfaces
2775 new_interfaces = __SCNetworkInterfaceCopyAll_Modem();
2776 if (new_interfaces != NULL) {
2777 add_interfaces(all_interfaces, new_interfaces);
2778 CFRelease(new_interfaces);
2779 }
2780
2781 // get serial (RS232) interfaces
2782 new_interfaces = __SCNetworkInterfaceCopyAll_RS232();
2783 if (new_interfaces != NULL) {
2784 add_interfaces(all_interfaces, new_interfaces);
2785 CFRelease(new_interfaces);
2786 }
2787
2788 // get virtual network interfaces (Bond, VLAN)
2789 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL);
2790 if (prefs != NULL) {
2791 new_interfaces = SCBondInterfaceCopyAll(prefs);
2792 if (new_interfaces != NULL) {
2793 add_interfaces(all_interfaces, new_interfaces);
2794 CFRelease(new_interfaces);
2795 }
2796
2797 new_interfaces = SCVLANInterfaceCopyAll(prefs);
2798 if (new_interfaces != NULL) {
2799 add_interfaces(all_interfaces, new_interfaces);
2800 CFRelease(new_interfaces);
2801 }
2802
2803 CFRelease(prefs);
2804 }
2805
2806 // all interfaces have been identified, order and return
2807 sort_interfaces(all_interfaces);
2808
2809 return all_interfaces;
2810 }
2811
2812
2813 CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */
2814 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface)
2815 {
2816 CFIndex i;
2817 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2818
2819 if (!isA_SCNetworkInterface(interface)) {
2820 _SCErrorSet(kSCStatusInvalidArgument);
2821 return NULL;
2822 }
2823
2824 if (interfacePrivate->supported_interface_types != NULL) {
2825 goto done;
2826 }
2827
2828 i = findConfiguration(interfacePrivate->interface_type);
2829 if (i != kCFNotFound) {
2830 if (configurations[i].supported_interfaces != doNone) {
2831 interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2832 if (configurations[i].supported_interfaces & do6to4) {
2833 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceType6to4);
2834 }
2835 if (configurations[i].supported_interfaces & doL2TP) {
2836 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeL2TP);
2837 }
2838 if (configurations[i].supported_interfaces & doPPP) {
2839 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPP);
2840 }
2841 if (configurations[i].supported_interfaces & doPPTP) {
2842 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPTP);
2843 }
2844 }
2845 }
2846
2847 done :
2848
2849 return interfacePrivate->supported_interface_types;
2850 }
2851
2852
2853 CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */
2854 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface)
2855 {
2856 CFIndex i;
2857 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
2858
2859 if (!isA_SCNetworkInterface(interface)) {
2860 _SCErrorSet(kSCStatusInvalidArgument);
2861 return NULL;
2862 }
2863
2864 if (interfacePrivate->supported_protocol_types != NULL) {
2865 goto done;
2866 }
2867
2868 i = findConfiguration(interfacePrivate->interface_type);
2869 if (i != kCFNotFound) {
2870 if (configurations[i].supported_protocols != doNone) {
2871 interfacePrivate->supported_protocol_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2872 if (configurations[i].supported_protocols & doAppleTalk) {
2873 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeAppleTalk);
2874 }
2875 if (configurations[i].supported_protocols & doDNS) {
2876 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeDNS);
2877 }
2878 if (configurations[i].supported_protocols & doIPv4) {
2879 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv4);
2880 }
2881 if (configurations[i].supported_protocols & doIPv6) {
2882 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv6);
2883 }
2884 if (configurations[i].supported_protocols & doProxies) {
2885 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeProxies);
2886 }
2887 if (configurations[i].supported_protocols & doSMB) {
2888 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeSMB);
2889 }
2890 }
2891 }
2892
2893 done :
2894
2895 return interfacePrivate->supported_protocol_types;
2896 }
2897
2898
2899 SCNetworkInterfaceRef
2900 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child, CFStringRef interfaceType)
2901 {
2902 SCNetworkInterfacePrivateRef childPrivate = (SCNetworkInterfacePrivateRef)child;
2903 CFIndex childIndex;
2904 SCNetworkInterfacePrivateRef parentPrivate;
2905
2906 if (!isA_SCNetworkInterface(child)) {
2907 _SCErrorSet(kSCStatusInvalidArgument);
2908 return NULL;
2909 }
2910
2911 if (!isA_CFString(interfaceType)) {
2912 _SCErrorSet(kSCStatusInvalidArgument);
2913 return NULL;
2914 }
2915
2916 childIndex = findConfiguration(childPrivate->interface_type);
2917
2918 parentPrivate = __SCNetworkInterfaceCreatePrivate(NULL,
2919 child,
2920 childPrivate->prefs,
2921 childPrivate->serviceID,
2922 NULL);
2923 if (parentPrivate == NULL) {
2924 _SCErrorSet(kSCStatusFailed);
2925 return NULL;
2926 }
2927
2928 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
2929 parentPrivate->interface_type = kSCNetworkInterfaceTypePPP;
2930 parentPrivate->entity_type = kSCEntNetPPP;
2931
2932 // entity subtype
2933 if (childIndex != kCFNotFound) {
2934 if (configurations[childIndex].ppp_subtype != NULL) {
2935 parentPrivate->entity_subtype = *configurations[childIndex].ppp_subtype;
2936 } else {
2937 // sorry, the child interface does not support PPP
2938 goto fail;
2939 }
2940 } else {
2941 // if the child's interface type not known, use the child entities "Type"
2942 parentPrivate->entity_subtype = childPrivate->entity_type;
2943 }
2944
2945 if (childPrivate->entity_device != NULL) {
2946 parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device);
2947 }
2948 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
2949 if ((childIndex == kCFNotFound) ||
2950 ((configurations[childIndex].supported_interfaces & doL2TP) != doL2TP)) {
2951 // if the child interface does not support L2TP
2952 goto fail;
2953 }
2954 parentPrivate->interface_type = kSCNetworkInterfaceTypeL2TP;
2955 parentPrivate->localized_key = CFSTR("l2tp");
2956 parentPrivate->entity_type = kSCValNetInterfaceSubTypeL2TP; // interface config goes into "L2TP"
2957 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) {
2958 if ((childIndex == kCFNotFound) ||
2959 ((configurations[childIndex].supported_interfaces & doPPTP) != doPPTP)) {
2960 // if the child interface does not support PPTP
2961 goto fail;
2962 }
2963 parentPrivate->interface_type = kSCNetworkInterfaceTypePPTP;
2964 parentPrivate->localized_key = CFSTR("pptp");
2965 parentPrivate->entity_type = kSCValNetInterfaceSubTypePPTP; // interface config goes into "PPTP"
2966 } else if (CFEqual(interfaceType, kSCNetworkInterfaceType6to4)) {
2967 if ((childIndex == kCFNotFound) ||
2968 ((configurations[childIndex].supported_interfaces & do6to4) != do6to4)) {
2969 // if the child interface does not support 6to4
2970 goto fail;
2971 }
2972
2973 parentPrivate->interface_type = kSCNetworkInterfaceType6to4;
2974 parentPrivate->localized_key = CFSTR("6to4");
2975 parentPrivate->entity_type = kSCEntNet6to4;
2976 parentPrivate->entity_device = CFRetain(CFSTR("stf0"));
2977 } else if (CFStringFind(interfaceType, CFSTR("."), 0).location != kCFNotFound) {
2978 // if custom interface type
2979 parentPrivate->interface_type = interfaceType;
2980 parentPrivate->entity_type = interfaceType; // interface config goes into a
2981 // a dictionary with the same
2982 // name as the interfaceType
2983 } else {
2984 // unknown interface type
2985 goto fail;
2986 }
2987
2988 if (childPrivate->overrides != NULL) {
2989 parentPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, childPrivate->overrides);
2990 };
2991 parentPrivate->sort_order = childPrivate->sort_order;
2992
2993 return (SCNetworkInterfaceRef)parentPrivate;
2994
2995 fail :
2996
2997 CFRelease(parentPrivate);
2998 _SCErrorSet(kSCStatusInvalidArgument);
2999 return NULL;
3000 }
3001
3002
3003 static CFDictionaryRef
3004 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface,
3005 CFStringRef extendedType)
3006 {
3007 CFDictionaryRef config = NULL;
3008 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3009 CFArrayRef paths;
3010
3011 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3012 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3013
3014 paths = copyConfigurationPaths(interfacePrivate, extendedType);
3015 if (paths != NULL) {
3016 CFStringRef path;
3017
3018 path = CFArrayGetValueAtIndex(paths, 0);
3019 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
3020
3021 CFRelease(paths);
3022 } else {
3023 if (interfacePrivate->unsaved != NULL) {
3024 config = CFDictionaryGetValue(interfacePrivate->unsaved, extendedType);
3025 if (config == (CFDictionaryRef)kCFNull) {
3026 config = NULL;
3027 }
3028 }
3029 }
3030
3031 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
3032 config = NULL;
3033 }
3034
3035 return config;
3036 }
3037
3038
3039 CFDictionaryRef
3040 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface)
3041 {
3042 CFDictionaryRef config;
3043 CFStringRef defaultType;
3044
3045 if (!isA_SCNetworkInterface(interface)) {
3046 _SCErrorSet(kSCStatusInvalidArgument);
3047 return NULL;
3048 }
3049
3050 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
3051 if (defaultType == NULL) {
3052 return NULL;
3053 }
3054
3055 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType);
3056 if (config == NULL) {
3057 if (CFEqual(defaultType, kSCEntNetAirPort)) {
3058 SCNetworkInterfacePrivateRef interfacePrivate;
3059 CFStringRef path;
3060
3061 // if AirPort interface, check for a per-service config
3062 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3063 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
3064 interfacePrivate->serviceID, // service
3065 kSCEntNetAirPort); // entity
3066 config = __getPrefsConfiguration(interfacePrivate->prefs, path);
3067 CFRelease(path);
3068 }
3069 }
3070 if (config == NULL) {
3071 _SCErrorSet(kSCStatusOK);
3072 }
3073
3074 return config;
3075 }
3076
3077
3078 CFDictionaryRef
3079 SCNetworkInterfaceGetExtendedConfiguration(SCNetworkInterfaceRef interface,
3080 CFStringRef extendedType)
3081 {
3082 CFDictionaryRef config;
3083
3084 if (!isA_SCNetworkInterface(interface)) {
3085 _SCErrorSet(kSCStatusInvalidArgument);
3086 return NULL;
3087 }
3088
3089 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) {
3090 _SCErrorSet(kSCStatusInvalidArgument);
3091 return NULL;
3092 }
3093
3094 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType);
3095 if (config == NULL) {
3096 _SCErrorSet(kSCStatusOK);
3097 }
3098
3099 return config;
3100 }
3101
3102
3103 CFStringRef
3104 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface)
3105 {
3106 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3107
3108 if (!isA_SCNetworkInterface(interface)) {
3109 _SCErrorSet(kSCStatusInvalidArgument);
3110 return NULL;
3111 }
3112
3113 if ((interfacePrivate->interface != NULL) &&
3114 (interfacePrivate->interface != kSCNetworkInterfaceIPv4)) {
3115 _SCErrorSet(kSCStatusOK);
3116 return NULL;
3117 }
3118
3119 return interfacePrivate->entity_device;
3120 }
3121
3122
3123 CFStringRef
3124 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface)
3125 {
3126 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3127
3128 if (!isA_SCNetworkInterface(interface)) {
3129 _SCErrorSet(kSCStatusInvalidArgument);
3130 return NULL;
3131 }
3132
3133 if ((interfacePrivate->address != NULL) &&
3134 (interfacePrivate->addressString == NULL)) {
3135 uint8_t *bp;
3136 char *cp;
3137 CFIndex n;
3138 char mac[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
3139 char *mac_p = mac;
3140
3141 bp = (uint8_t *)CFDataGetBytePtr(interfacePrivate->address);
3142 n = CFDataGetLength(interfacePrivate->address) * 3;
3143
3144 if (n > sizeof(mac)) {
3145 mac_p = CFAllocatorAllocate(NULL, 0, n);
3146 }
3147
3148 for (cp = mac_p; n > 0; n -= 3) {
3149 cp += snprintf(cp, n, "%2.2x:", *bp++);
3150 }
3151
3152 interfacePrivate->addressString = CFStringCreateWithCString(NULL, mac_p, kCFStringEncodingUTF8);
3153 if (mac_p != mac) CFAllocatorDeallocate(NULL, mac_p);
3154 }
3155
3156 return interfacePrivate->addressString;
3157 }
3158
3159
3160 SCNetworkInterfaceRef
3161 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface)
3162 {
3163 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3164
3165 if (!isA_SCNetworkInterface(interface)) {
3166 _SCErrorSet(kSCStatusInvalidArgument);
3167 return NULL;
3168 }
3169
3170 return interfacePrivate->interface;
3171 }
3172
3173
3174 CFStringRef
3175 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface)
3176 {
3177 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3178
3179 if (!isA_SCNetworkInterface(interface)) {
3180 _SCErrorSet(kSCStatusInvalidArgument);
3181 return NULL;
3182 }
3183
3184 return interfacePrivate->interface_type;
3185 }
3186
3187
3188 static CFStringRef
3189 copy_interface_string(CFBundleRef bundle, CFStringRef key, Boolean localized)
3190 {
3191 CFStringRef str = NULL;
3192
3193 if (localized) {
3194 str = CFBundleCopyLocalizedString(bundle,
3195 key,
3196 key,
3197 NETWORKINTERFACE_LOCALIZATIONS);
3198 } else {
3199 str = _SC_CFBundleCopyNonLocalizedString(bundle,
3200 key,
3201 key,
3202 NETWORKINTERFACE_LOCALIZATIONS);
3203 }
3204
3205 return str;
3206 }
3207
3208
3209 static CFStringRef
3210 copy_display_name(SCNetworkInterfaceRef interface, Boolean localized)
3211 {
3212 CFMutableStringRef local;
3213 CFStringRef name;
3214
3215 local = CFStringCreateMutable(NULL, 0);
3216
3217 while (interface != NULL) {
3218 Boolean added = FALSE;
3219 SCNetworkInterfaceRef child = NULL;
3220 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3221
3222 if ((interfacePrivate->interface != NULL) &&
3223 (interfacePrivate->interface != kSCNetworkInterfaceIPv4)) {
3224 child = interfacePrivate->interface;
3225 }
3226
3227 if ((bundle != NULL) && (interfacePrivate->localized_key != NULL)) {
3228 CFStringRef fmt;
3229
3230 fmt = copy_interface_string(bundle, interfacePrivate->localized_key, localized);
3231 if (fmt != NULL) {
3232 CFStringAppendFormat(local,
3233 NULL,
3234 fmt,
3235 interfacePrivate->localized_arg1,
3236 interfacePrivate->localized_arg2);
3237 CFRelease(fmt);
3238 added = TRUE;
3239 }
3240 }
3241
3242 if (!added &&
3243 (interfacePrivate->prefs != NULL) &&
3244 (interfacePrivate->serviceID != NULL) &&
3245 (child == NULL)) {
3246 CFDictionaryRef entity;
3247 CFStringRef path;
3248
3249 // check for (and use) the name of the interface when it
3250 // was last available
3251 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,
3252 interfacePrivate->serviceID,
3253 kSCEntNetInterface);
3254 entity = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
3255 CFRelease(path);
3256 if (isA_CFDictionary(entity)) {
3257 CFStringRef name;
3258
3259 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
3260 if (isA_CFString(name)) {
3261 CFStringAppend(local, name);
3262 added = TRUE;
3263 }
3264 }
3265 }
3266
3267 if (!added) {
3268 // create (non-)localized name based on the interface type
3269 CFStringAppend(local, interfacePrivate->interface_type);
3270
3271 // ... and, if this is a leaf node, the interface device
3272 if ((interfacePrivate->entity_device != NULL) && (child == NULL)) {
3273 CFStringAppendFormat(local, NULL, CFSTR(" (%@)"), interfacePrivate->entity_device);
3274 }
3275 }
3276
3277 if (child != NULL) {
3278 // if this interface is layered over another
3279 CFStringAppend(local, CFSTR(" --> "));
3280 }
3281
3282 interface = child;
3283 }
3284
3285 name = CFStringCreateCopy(NULL, local);
3286 CFRelease(local);
3287
3288 return name;
3289 }
3290
3291
3292 __private_extern__
3293 CFStringRef
3294 __SCNetworkInterfaceGetNonLocalizedDisplayName(SCNetworkInterfaceRef interface)
3295 {
3296 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3297
3298 if (!isA_SCNetworkInterface(interface)) {
3299 _SCErrorSet(kSCStatusInvalidArgument);
3300 return NULL;
3301 }
3302
3303 if (interfacePrivate->name == NULL) {
3304 interfacePrivate->name = copy_display_name(interface, FALSE);
3305 }
3306
3307 return interfacePrivate->name;
3308 }
3309
3310
3311 CFStringRef
3312 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface)
3313 {
3314 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3315
3316 if (!isA_SCNetworkInterface(interface)) {
3317 _SCErrorSet(kSCStatusInvalidArgument);
3318 return NULL;
3319 }
3320
3321 if (interfacePrivate->localized_name == NULL) {
3322 interfacePrivate->localized_name = copy_display_name(interface, TRUE);
3323 }
3324
3325 return interfacePrivate->localized_name;
3326 }
3327
3328
3329 __private_extern__
3330 CFDictionaryRef
3331 __SCNetworkInterfaceGetTemplateOverrides(SCNetworkInterfaceRef interface, CFStringRef interfaceType)
3332 {
3333 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3334 CFDictionaryRef overrides = NULL;
3335
3336 if (interfacePrivate->overrides != NULL) {
3337 overrides = CFDictionaryGetValue(interfacePrivate->overrides, interfaceType);
3338 }
3339
3340 return overrides;
3341 }
3342
3343
3344 CFTypeID
3345 SCNetworkInterfaceGetTypeID(void)
3346 {
3347 pthread_once(&initialized, __SCNetworkInterfaceInitialize); /* initialize runtime */
3348 return __kSCNetworkInterfaceTypeID;
3349 }
3350
3351
3352 __private_extern__
3353 Boolean
3354 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface,
3355 CFStringRef extendedType,
3356 CFDictionaryRef config,
3357 Boolean okToHold)
3358 {
3359 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3360 Boolean ok = FALSE;
3361 CFArrayRef paths;
3362
3363 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3364 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
3365
3366 if (extendedType == NULL) {
3367 extendedType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
3368 if (extendedType == NULL) {
3369 return FALSE;
3370 }
3371 }
3372
3373 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) {
3374 config = NULL;
3375 }
3376
3377 paths = copyConfigurationPaths(interfacePrivate, extendedType);
3378 if (paths != NULL) {
3379 CFIndex i;
3380 CFIndex n;
3381
3382 n = CFArrayGetCount(paths);
3383 for (i = 0; i < n; i++) {
3384 CFStringRef path;
3385
3386 path = CFArrayGetValueAtIndex(paths, i);
3387 ok = __setPrefsConfiguration(interfacePrivate->prefs, path, config, FALSE);
3388 if (!ok) {
3389 break;
3390 }
3391 }
3392
3393 if (ok) {
3394 // if configuration has been saved
3395 if (interfacePrivate->unsaved != NULL) {
3396 CFDictionaryRemoveValue(interfacePrivate->unsaved, extendedType);
3397 if (CFDictionaryGetCount(interfacePrivate->unsaved) == 0) {
3398 CFRelease(interfacePrivate->unsaved);
3399 interfacePrivate->unsaved = NULL;
3400 }
3401 }
3402 }
3403
3404 CFRelease(paths);
3405 } else {
3406 if (okToHold) {
3407 if (config == NULL) {
3408 // remember that we are clearing the configuration
3409 config = (CFDictionaryRef)kCFNull;
3410 }
3411
3412 if (interfacePrivate->unsaved == NULL) {
3413 interfacePrivate->unsaved = CFDictionaryCreateMutable(NULL,
3414 0,
3415 &kCFTypeDictionaryKeyCallBacks,
3416 &kCFTypeDictionaryValueCallBacks);
3417 }
3418 CFDictionarySetValue(interfacePrivate->unsaved, extendedType, config);
3419 ok = TRUE;
3420 } else {
3421 _SCErrorSet(kSCStatusNoKey);
3422 }
3423 }
3424
3425 return ok;
3426 }
3427
3428
3429 Boolean
3430 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config)
3431 {
3432 CFStringRef defaultType;
3433
3434 if (!isA_SCNetworkInterface(interface)) {
3435 _SCErrorSet(kSCStatusInvalidArgument);
3436 return FALSE;
3437 }
3438
3439 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
3440 if (defaultType == NULL) {
3441 return FALSE;
3442 }
3443
3444 return __SCNetworkInterfaceSetConfiguration(interface, defaultType, config, FALSE);
3445 }
3446
3447
3448 Boolean
3449 SCNetworkInterfaceSetExtendedConfiguration(SCNetworkInterfaceRef interface,
3450 CFStringRef extendedType,
3451 CFDictionaryRef config)
3452 {
3453 if (!isA_SCNetworkInterface(interface)) {
3454 _SCErrorSet(kSCStatusInvalidArgument);
3455 return FALSE;
3456 }
3457
3458 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) {
3459 return FALSE;
3460 }
3461
3462 return __SCNetworkInterfaceSetConfiguration(interface, extendedType, config, FALSE);
3463 }
3464
3465
3466 #pragma mark -
3467 #pragma mark SCNetworkInterface [Refresh Configuration] API
3468
3469
3470 #ifndef kSCEntNetRefreshConfiguration
3471 #define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration")
3472 #endif // kSCEntNetRefreshConfiguration
3473
3474 Boolean
3475 _SCNetworkInterfaceForceConfigurationRefresh(CFStringRef ifName)
3476 {
3477 CFStringRef key;
3478 Boolean ok = FALSE;
3479 SCDynamicStoreRef store;
3480
3481 if (!isA_CFString(ifName)) {
3482 _SCErrorSet(kSCStatusInvalidArgument);
3483 return FALSE;
3484 }
3485
3486 store = SCDynamicStoreCreate(NULL, CFSTR("_SCNetworkInterfaceForceConfigurationRefresh"), NULL, NULL);
3487 if (store == NULL) {
3488 return FALSE;
3489 }
3490
3491 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
3492 kSCDynamicStoreDomainState,
3493 ifName,
3494 kSCEntNetRefreshConfiguration);
3495 ok = SCDynamicStoreNotifyValue(store, key);
3496 CFRelease(key);
3497 CFRelease(store);
3498 return ok;
3499 }
3500
3501
3502 static Boolean
3503 __SCNetworkInterfaceForceConfigurationRefresh_helper(SCPreferencesRef prefs, CFStringRef ifName)
3504 {
3505 CFDataRef data = NULL;
3506 Boolean ok;
3507 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
3508 uint32_t status = kSCStatusOK;
3509 CFDataRef reply = NULL;
3510
3511 if (prefsPrivate->helper == -1) {
3512 ok = __SCPreferencesCreate_helper(prefs);
3513 if (!ok) {
3514 return FALSE;
3515 }
3516 }
3517
3518 // serialize the interface name
3519 ok = _SCSerializeString(ifName, &data, NULL, NULL);
3520 if (!ok) {
3521 goto fail;
3522 }
3523
3524 // have the helper "refresh" the configuration
3525 status = kSCStatusOK;
3526 reply = NULL;
3527 ok = _SCHelperExec(prefsPrivate->helper,
3528 SCHELPER_MSG_INTERFACE_REFRESH,
3529 data,
3530 &status,
3531 NULL);
3532 if (data != NULL) CFRelease(data);
3533 if (!ok) {
3534 goto fail;
3535 }
3536
3537 if (status != kSCStatusOK) {
3538 goto error;
3539 }
3540
3541 return TRUE;
3542
3543 fail :
3544
3545 // close helper
3546 if (prefsPrivate->helper != -1) {
3547 _SCHelperClose(prefsPrivate->helper);
3548 prefsPrivate->helper = -1;
3549 }
3550
3551 status = kSCStatusAccessError;
3552
3553 error :
3554
3555 // return error
3556 _SCErrorSet(status);
3557 return FALSE;
3558 }
3559
3560
3561 Boolean
3562 SCNetworkInterfaceForceConfigurationRefresh(SCNetworkInterfaceRef interface)
3563 {
3564 CFStringRef ifName;
3565 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3566
3567 if (!isA_SCNetworkInterface(interface)) {
3568 _SCErrorSet(kSCStatusInvalidArgument);
3569 return FALSE;
3570 }
3571
3572 ifName = SCNetworkInterfaceGetBSDName(interface);
3573 if (ifName == NULL) {
3574 _SCErrorSet(kSCStatusInvalidArgument);
3575 return FALSE;
3576 }
3577
3578 if (interfacePrivate->prefs != NULL) {
3579 SCPreferencesRef prefs = interfacePrivate->prefs;
3580 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
3581
3582 if (prefsPrivate->authorizationData != NULL) {
3583 return __SCNetworkInterfaceForceConfigurationRefresh_helper(prefs, ifName);
3584 }
3585 }
3586
3587 return _SCNetworkInterfaceForceConfigurationRefresh(ifName);
3588 }
3589
3590
3591 Boolean
3592 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName)
3593 {
3594 return _SCNetworkInterfaceForceConfigurationRefresh(ifName);
3595 }
3596
3597
3598 #pragma mark -
3599 #pragma mark SCNetworkInterface Password APIs
3600
3601
3602 static CFStringRef
3603 getPasswordID(CFDictionaryRef config, CFStringRef serviceID)
3604 {
3605 CFStringRef unique_id = NULL;
3606
3607 if (config != NULL) {
3608 CFStringRef encryption;
3609
3610 encryption = CFDictionaryGetValue(config, kSCPropNetPPPAuthPasswordEncryption);
3611 if (isA_CFString(encryption) &&
3612 CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
3613 unique_id = CFDictionaryGetValue(config, kSCPropNetPPPAuthPassword);
3614 }
3615 }
3616 if (unique_id == NULL) {
3617 unique_id = serviceID;
3618 }
3619
3620 return unique_id;
3621 }
3622
3623
3624 static CFStringRef
3625 copySharedSecretID(CFDictionaryRef config, CFStringRef serviceID)
3626 {
3627 CFMutableStringRef sharedSecret = NULL;
3628
3629 if (config != NULL) {
3630 CFStringRef encryption;
3631
3632 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecretEncryption);
3633 if (isA_CFString(encryption) &&
3634 CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
3635 sharedSecret = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecret);
3636 if (sharedSecret != NULL) {
3637 CFRetain(sharedSecret);
3638 }
3639 }
3640 }
3641
3642 if (sharedSecret == NULL) {
3643 CFStringRef unique_id;
3644
3645 unique_id = getPasswordID(config, serviceID);
3646 sharedSecret = CFStringCreateMutableCopy(NULL, 0, unique_id);
3647 CFStringAppend(sharedSecret, CFSTR(".SS"));
3648 }
3649
3650 return sharedSecret;
3651 }
3652
3653
3654 static Boolean
3655 checkInterfacePassword(SCNetworkInterfaceRef interface,
3656 SCNetworkInterfacePasswordType passwordType,
3657 SCPreferencesRef *prefs,
3658 CFStringRef *serviceID)
3659 {
3660 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
3661
3662 if (!isA_SCNetworkInterface(interface)) {
3663 _SCErrorSet(kSCStatusInvalidArgument);
3664 return FALSE;
3665 }
3666
3667 *serviceID = interfacePrivate->serviceID;
3668 if (*serviceID == NULL) {
3669 _SCErrorSet(kSCStatusInvalidArgument);
3670 return FALSE;
3671 }
3672
3673 *prefs = interfacePrivate->prefs;
3674 if (*prefs == NULL) {
3675 _SCErrorSet(kSCStatusInvalidArgument);
3676 return FALSE;
3677 }
3678
3679 switch (passwordType) {
3680 case kSCNetworkInterfacePasswordTypePPP : {
3681 CFStringRef interfaceType;
3682
3683 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
3684 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
3685 _SCErrorSet(kSCStatusInvalidArgument);
3686 return FALSE;
3687 }
3688 break;
3689 }
3690
3691 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
3692 CFStringRef interfaceType;
3693
3694 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
3695 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
3696 _SCErrorSet(kSCStatusInvalidArgument);
3697 return FALSE;
3698 }
3699
3700 interface = SCNetworkInterfaceGetInterface(interface);
3701 if (interface == NULL) {
3702 _SCErrorSet(kSCStatusInvalidArgument);
3703 return FALSE;
3704 }
3705
3706 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
3707 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
3708 _SCErrorSet(kSCStatusInvalidArgument);
3709 return FALSE;
3710 }
3711 break;
3712 }
3713
3714 case kSCNetworkInterfacePasswordTypeEAPOL : {
3715 break;
3716 }
3717
3718 default :
3719 break;
3720 }
3721
3722 return TRUE;
3723 }
3724
3725
3726 Boolean
3727 SCNetworkInterfaceCheckPassword(SCNetworkInterfaceRef interface,
3728 SCNetworkInterfacePasswordType passwordType)
3729 {
3730 Boolean exists = FALSE;
3731 SCPreferencesRef prefs = NULL;
3732 CFStringRef serviceID = NULL;
3733
3734 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
3735 return FALSE;
3736 }
3737
3738 switch (passwordType) {
3739 case kSCNetworkInterfacePasswordTypePPP : {
3740 CFDictionaryRef config;
3741 CFStringRef unique_id;
3742
3743 // get configuration
3744 config = SCNetworkInterfaceGetConfiguration(interface);
3745
3746 // get serviceID
3747 unique_id = getPasswordID(config, serviceID);
3748
3749 // check
3750 exists = __extract_password(prefs,
3751 config,
3752 kSCPropNetPPPAuthPassword,
3753 kSCPropNetPPPAuthPasswordEncryption,
3754 kSCValNetPPPAuthPasswordEncryptionKeychain,
3755 unique_id,
3756 NULL);
3757 break;
3758 }
3759
3760 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
3761 CFDictionaryRef config;
3762 CFStringRef shared_id;
3763
3764 // get configuration
3765 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
3766
3767 // get sharedSecret ID
3768 shared_id = copySharedSecretID(config, serviceID);
3769
3770 // check
3771 exists = __extract_password(prefs,
3772 config,
3773 kSCPropNetIPSecSharedSecret,
3774 kSCPropNetIPSecSharedSecretEncryption,
3775 kSCValNetIPSecSharedSecretEncryptionKeychain,
3776 shared_id,
3777 NULL);
3778 CFRelease(shared_id);
3779 break;
3780 }
3781
3782 case kSCNetworkInterfacePasswordTypeEAPOL : {
3783 CFDictionaryRef config;
3784 CFStringRef unique_id = NULL;
3785
3786 // get configuration
3787 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
3788
3789 // get 802.1X identifier
3790 if (config != NULL) {
3791 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
3792 }
3793 if (!isA_CFString(unique_id)) {
3794 return FALSE;
3795 }
3796
3797 // check password
3798 exists = _SCPreferencesSystemKeychainPasswordItemExists(prefs, unique_id);
3799 break;
3800 }
3801
3802 default :
3803 _SCErrorSet(kSCStatusInvalidArgument);
3804 return FALSE;
3805 }
3806
3807 return exists;
3808 }
3809
3810
3811 CFDataRef
3812 SCNetworkInterfaceCopyPassword(SCNetworkInterfaceRef interface,
3813 SCNetworkInterfacePasswordType passwordType)
3814 {
3815 CFDataRef password = NULL;
3816 SCPreferencesRef prefs = NULL;
3817 CFStringRef serviceID = NULL;
3818
3819 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
3820 return NULL;
3821 }
3822
3823 switch (passwordType) {
3824 case kSCNetworkInterfacePasswordTypePPP : {
3825 CFDictionaryRef config;
3826 CFStringRef unique_id;
3827
3828 // get configuration
3829 config = SCNetworkInterfaceGetConfiguration(interface);
3830
3831 // get serviceID
3832 unique_id = getPasswordID(config, serviceID);
3833
3834 // extract
3835 (void) __extract_password(prefs,
3836 config,
3837 kSCPropNetPPPAuthPassword,
3838 kSCPropNetPPPAuthPasswordEncryption,
3839 kSCValNetPPPAuthPasswordEncryptionKeychain,
3840 unique_id,
3841 &password);
3842 break;
3843 }
3844
3845 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
3846 CFDictionaryRef config;
3847 CFStringRef shared_id;
3848
3849 // get configuration
3850 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
3851
3852 // get sharedSecret ID
3853 shared_id = copySharedSecretID(config, serviceID);
3854
3855 // extract
3856 (void) __extract_password(prefs,
3857 config,
3858 kSCPropNetIPSecSharedSecret,
3859 kSCPropNetIPSecSharedSecretEncryption,
3860 kSCValNetIPSecSharedSecretEncryptionKeychain,
3861 shared_id,
3862 &password);
3863
3864 CFRelease(shared_id);
3865 break;
3866 }
3867
3868 case kSCNetworkInterfacePasswordTypeEAPOL : {
3869 CFDictionaryRef config;
3870 CFStringRef unique_id = NULL;
3871
3872 // get configuration
3873 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
3874
3875 // get 802.1X identifier
3876 if (config != NULL) {
3877 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
3878 }
3879 if (!isA_CFString(unique_id)) {
3880 _SCErrorSet(kSCStatusFailed);
3881 return NULL;
3882 }
3883
3884 // copy password
3885 password = _SCPreferencesSystemKeychainPasswordItemCopy(prefs, unique_id);
3886 break;
3887 }
3888
3889 default :
3890 _SCErrorSet(kSCStatusInvalidArgument);
3891 return NULL;
3892 }
3893
3894 return password;
3895 }
3896
3897
3898 Boolean
3899 SCNetworkInterfaceRemovePassword(SCNetworkInterfaceRef interface,
3900 SCNetworkInterfacePasswordType passwordType)
3901 {
3902 Boolean ok = FALSE;
3903 SCPreferencesRef prefs = NULL;
3904 CFStringRef serviceID = NULL;
3905
3906 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
3907 return FALSE;
3908 }
3909
3910 switch (passwordType) {
3911 case kSCNetworkInterfacePasswordTypePPP : {
3912 CFDictionaryRef config;
3913 CFStringRef unique_id;
3914
3915 // get configuration
3916 config = SCNetworkInterfaceGetConfiguration(interface);
3917
3918 // get serviceID
3919 unique_id = getPasswordID(config, serviceID);
3920
3921 // remove password
3922 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, unique_id);
3923 if (ok) {
3924 CFMutableDictionaryRef newConfig;
3925
3926 if (config != NULL) {
3927 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
3928 CFDictionaryRemoveValue(newConfig, kSCPropNetPPPAuthPassword);
3929 CFDictionaryRemoveValue(newConfig, kSCPropNetPPPAuthPasswordEncryption);
3930 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
3931 CFRelease(newConfig);
3932 }
3933 }
3934 break;
3935 }
3936
3937 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
3938 CFDictionaryRef config;
3939 CFStringRef shared_id;
3940
3941 // get configuration
3942 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
3943
3944 // get sharedSecret ID
3945 shared_id = copySharedSecretID(config, serviceID);
3946
3947 // remove password
3948 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, shared_id);
3949 if (ok) {
3950 CFMutableDictionaryRef newConfig;
3951
3952 if (config != NULL) {
3953 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
3954 CFDictionaryRemoveValue(newConfig, kSCPropNetIPSecSharedSecret);
3955 CFDictionaryRemoveValue(newConfig, kSCPropNetIPSecSharedSecretEncryption);
3956 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
3957 kSCEntNetIPSec,
3958 newConfig);
3959 CFRelease(newConfig);
3960 }
3961 }
3962
3963 CFRelease(shared_id);
3964 break;
3965 }
3966
3967 case kSCNetworkInterfacePasswordTypeEAPOL : {
3968 CFDictionaryRef config;
3969 CFStringRef unique_id = NULL;
3970
3971 // get configuration
3972 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
3973
3974 // get 802.1X identifier
3975 if (config != NULL) {
3976 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
3977 }
3978 if (!isA_CFString(unique_id)) {
3979 _SCErrorSet(kSCStatusFailed);
3980 return FALSE;
3981 }
3982
3983 // remove password
3984 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, unique_id);
3985 break;
3986 }
3987
3988 default :
3989 _SCErrorSet(kSCStatusInvalidArgument);
3990 return FALSE;
3991 }
3992
3993 return ok;
3994 }
3995
3996
3997 Boolean
3998 SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface,
3999 SCNetworkInterfacePasswordType passwordType,
4000 CFDataRef password,
4001 CFDictionaryRef options)
4002 {
4003 CFStringRef account = NULL;
4004 CFDictionaryRef config;
4005 CFStringRef description = NULL;
4006 CFStringRef label = NULL;
4007 Boolean ok = FALSE;
4008 SCPreferencesRef prefs = NULL;
4009 CFStringRef serviceID = NULL;
4010
4011 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) {
4012 return FALSE;
4013 }
4014
4015 switch (passwordType) {
4016 case kSCNetworkInterfacePasswordTypePPP : {
4017 SCNetworkServiceRef service = NULL;
4018 CFStringRef unique_id;
4019
4020 // get configuration
4021 config = SCNetworkInterfaceGetConfiguration(interface);
4022
4023 // get serviceID
4024 unique_id = getPasswordID(config, serviceID);
4025
4026 // get "Account", "Name", "Kind"
4027 if (config != NULL) {
4028 // auth name --> keychain "Account"
4029 account = CFDictionaryGetValue(config, kSCPropNetPPPAuthName);
4030
4031 // PPP [user defined] "name" --> keychain "Name"
4032 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
4033 }
4034
4035 if (label == NULL) {
4036 // service name --> keychain "Name"
4037 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
4038 prefs,
4039 serviceID,
4040 interface);
4041
4042 label = SCNetworkServiceGetName(service);
4043 if (label == NULL) {
4044 // interface name --> keychain "Name"
4045 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
4046 }
4047 }
4048
4049 if (bundle != NULL) {
4050 // "PPP Password" --> keychain "Kind"
4051 description = CFBundleCopyLocalizedString(bundle,
4052 CFSTR("KEYCHAIN_PPP_PASSWORD"),
4053 CFSTR("PPP Password"),
4054 NULL);
4055 }
4056
4057 // store password
4058 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
4059 unique_id,
4060 (label != NULL) ? label : CFSTR("PPP"),
4061 (description != NULL) ? description : CFSTR("PPP Password"),
4062 account,
4063 password,
4064 options);
4065 if (ok) {
4066 CFMutableDictionaryRef newConfig;
4067
4068 if (config != NULL) {
4069 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
4070 } else {
4071 newConfig = CFDictionaryCreateMutable(NULL,
4072 0,
4073 &kCFTypeDictionaryKeyCallBacks,
4074 &kCFTypeDictionaryValueCallBacks);
4075 }
4076 CFDictionarySetValue(newConfig,
4077 kSCPropNetPPPAuthPassword,
4078 unique_id);
4079 CFDictionarySetValue(newConfig,
4080 kSCPropNetPPPAuthPasswordEncryption,
4081 kSCValNetPPPAuthPasswordEncryptionKeychain);
4082 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig);
4083 CFRelease(newConfig);
4084 }
4085
4086 if (description != NULL) CFRelease(description);
4087 if (service != NULL) CFRelease(service);
4088 break;
4089 }
4090
4091 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
4092 SCNetworkServiceRef service = NULL;
4093 CFStringRef shared_id;
4094
4095 // get configuration
4096 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
4097
4098 // get sharedSecret ID
4099 shared_id = copySharedSecretID(config, serviceID);
4100
4101 // get "Name", "Kind"
4102 if (config != NULL) {
4103 // PPP [user defined] "name" --> keychain "Name"
4104 label = CFDictionaryGetValue(config, kSCPropUserDefinedName);
4105 }
4106
4107 if (label == NULL) {
4108 // service name --> keychain "Name"
4109 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL,
4110 prefs,
4111 serviceID,
4112 interface);
4113
4114 label = SCNetworkServiceGetName(service);
4115 if (label == NULL) {
4116 // interface name --> keychain "Name"
4117 label = SCNetworkInterfaceGetLocalizedDisplayName(interface);
4118 }
4119 }
4120
4121 if (bundle != NULL) {
4122 // "IPSec Shared Secret" --> keychain "Kind"
4123 description = CFBundleCopyLocalizedString(bundle,
4124 CFSTR("KEYCHAIN_IPSEC_SHARED_SECRET"),
4125 CFSTR("IPSec Shared Secret"),
4126 NULL);
4127 }
4128
4129 // set password
4130 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
4131 shared_id,
4132 (label != NULL) ? label : CFSTR("PPP"),
4133 (description != NULL) ? description : CFSTR("IPSec Shared Secret"),
4134 NULL,
4135 password,
4136 options);
4137 if (ok) {
4138 CFMutableDictionaryRef newConfig = NULL;
4139
4140 if (config != NULL) {
4141 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
4142 } else {
4143 newConfig = CFDictionaryCreateMutable(NULL,
4144 0,
4145 &kCFTypeDictionaryKeyCallBacks,
4146 &kCFTypeDictionaryValueCallBacks);
4147 }
4148 CFDictionarySetValue(newConfig,
4149 kSCPropNetIPSecSharedSecret,
4150 shared_id);
4151 CFDictionarySetValue(newConfig,
4152 kSCPropNetIPSecSharedSecretEncryption,
4153 kSCValNetIPSecSharedSecretEncryptionKeychain);
4154 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
4155 kSCEntNetIPSec,
4156 newConfig);
4157 CFRelease(newConfig);
4158 }
4159
4160 if (description != NULL) CFRelease(description);
4161 if (service != NULL) CFRelease(service);
4162 CFRelease(shared_id);
4163 break;
4164 }
4165
4166 case kSCNetworkInterfacePasswordTypeEAPOL : {
4167 CFStringRef unique_id = NULL;
4168
4169 // get configuration
4170 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL);
4171
4172 // get 802.1X identifier
4173 if (config != NULL) {
4174 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID);
4175 }
4176 if (isA_CFString(unique_id)) {
4177 CFRetain(unique_id);
4178 } else {
4179 CFUUIDRef uuid;
4180
4181 uuid = CFUUIDCreate(NULL);
4182 unique_id = CFUUIDCreateString(NULL, uuid);
4183 CFRelease(uuid);
4184 }
4185
4186 // get "Name", "Kind"
4187 if (bundle != NULL) {
4188 // "802.1X Password" --> keychain "Name"
4189 label = CFBundleCopyLocalizedString(bundle,
4190 CFSTR("KEYCHAIN_EAPOL_PASSWORD"),
4191 CFSTR("802.1X Password"),
4192 NULL);
4193 // "Internet Connect" --> keychain "Kind"
4194 description = CFBundleCopyLocalizedString(bundle,
4195 CFSTR("KEYCHAIN_INTERNET_CONNECT"),
4196 CFSTR("Internet Connect"),
4197 NULL);
4198 }
4199
4200 // set password
4201 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs,
4202 unique_id,
4203 (label != NULL) ? label : CFSTR("802.1X Password"),
4204 (description != NULL) ? description : CFSTR("Internet Connect"),
4205 NULL,
4206 password,
4207 options);
4208 if (ok) {
4209 CFMutableDictionaryRef newConfig = NULL;
4210
4211 if (config != NULL) {
4212 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
4213 } else {
4214 newConfig = CFDictionaryCreateMutable(NULL,
4215 0,
4216 &kCFTypeDictionaryKeyCallBacks,
4217 &kCFTypeDictionaryValueCallBacks);
4218 }
4219 CFDictionarySetValue(newConfig,
4220 kEAPClientPropUserPasswordKeychainItemID,
4221 unique_id);
4222 ok = SCNetworkInterfaceSetExtendedConfiguration(interface,
4223 kSCEntNetEAPOL,
4224 newConfig);
4225 CFRelease(newConfig);
4226 }
4227
4228 CFRelease(unique_id);
4229 if (label != NULL) CFRelease(label);
4230 if (description != NULL) CFRelease(description);
4231 break;
4232 }
4233
4234 default :
4235 _SCErrorSet(kSCStatusInvalidArgument);
4236 break;
4237 }
4238
4239 return ok;
4240 }
4241
4242
4243 #pragma mark -
4244 #pragma mark SCNetworkInterface [InterfaceNamer] SPIs
4245
4246
4247 SCNetworkInterfaceRef
4248 _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj)
4249 {
4250 SCNetworkInterfaceRef interface;
4251
4252 /* initialize runtime */
4253 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
4254
4255 interface = createInterface(if_obj, processNetworkInterface);
4256 return interface;
4257 }
4258
4259
4260 CFDataRef
4261 _SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface)
4262 {
4263 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4264
4265 return interfacePrivate->address;
4266 }
4267
4268
4269 CFNumberRef
4270 _SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface)
4271 {
4272 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4273
4274 return interfacePrivate->type;
4275 }
4276
4277
4278 CFNumberRef
4279 _SCNetworkInterfaceGetIOInterfaceUnit(SCNetworkInterfaceRef interface)
4280 {
4281 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4282
4283 return interfacePrivate->unit;
4284 }
4285
4286
4287 CFStringRef
4288 _SCNetworkInterfaceGetIOPath(SCNetworkInterfaceRef interface)
4289 {
4290 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4291
4292 return interfacePrivate->path;
4293 }
4294
4295
4296 Boolean
4297 _SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface)
4298 {
4299 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4300
4301 return interfacePrivate->builtin;
4302 }
4303
4304
4305 #pragma mark -
4306 #pragma mark SCNetworkInterface SPIs
4307
4308 Boolean
4309 _SCNetworkInterfaceIsModemV92(SCNetworkInterfaceRef interface)
4310 {
4311 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
4312
4313 return interfacePrivate->modemIsV92;
4314 }
4315
4316
4317 #pragma mark -
4318 #pragma mark SCNetworkInterface [internal] SPIs
4319
4320
4321 __private_extern__
4322 SCNetworkInterfacePrivateRef
4323 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator,
4324 SCNetworkInterfaceRef interface,
4325 SCPreferencesRef prefs,
4326 CFStringRef serviceID)
4327 {
4328 SCNetworkInterfacePrivateRef oldPrivate = (SCNetworkInterfacePrivateRef)interface;
4329 SCNetworkInterfacePrivateRef newPrivate;
4330
4331 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4332 pthread_once(&initialized, __SCNetworkInterfaceInitialize);
4333
4334 newPrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, prefs, serviceID, NULL);
4335 newPrivate->interface_type = oldPrivate->interface_type;
4336 if (oldPrivate->interface != NULL) {
4337 newPrivate->interface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, // allocator
4338 oldPrivate->interface, // interface
4339 prefs, // [new] prefs
4340 serviceID); // [new] serviceID
4341 }
4342 if (oldPrivate->name != NULL) {
4343 newPrivate->name = CFRetain(oldPrivate->name);
4344 }
4345 if (oldPrivate->localized_name != NULL) {
4346 newPrivate->localized_name = CFRetain(oldPrivate->localized_name);
4347 }
4348 newPrivate->localized_key = oldPrivate->localized_key;
4349 if (oldPrivate->localized_arg1 != NULL) {
4350 newPrivate->localized_arg1 = CFRetain(oldPrivate->localized_arg1);
4351 }
4352 if (oldPrivate->localized_arg2 != NULL) {
4353 newPrivate->localized_arg2 = CFRetain(oldPrivate->localized_arg2);
4354 }
4355 if (oldPrivate->unsaved != NULL) {
4356 newPrivate->unsaved = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->unsaved);
4357 }
4358 if (oldPrivate->entity_device != NULL) {
4359 newPrivate->entity_device = CFRetain(oldPrivate->entity_device);
4360 }
4361 newPrivate->entity_type = oldPrivate->entity_type;
4362 newPrivate->entity_subtype = oldPrivate->entity_subtype;
4363 if (oldPrivate->supported_interface_types != NULL) {
4364 newPrivate->supported_interface_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_interface_types);
4365 }
4366 if (oldPrivate->supported_protocol_types != NULL) {
4367 newPrivate->supported_protocol_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_protocol_types);
4368 }
4369 if (oldPrivate->address != NULL) {
4370 newPrivate->address = CFRetain(oldPrivate->address);
4371 }
4372 newPrivate->builtin = oldPrivate->builtin;
4373 if (oldPrivate->location != NULL) {
4374 newPrivate->location = CFRetain(oldPrivate->location);
4375 }
4376 if (oldPrivate->path != NULL) {
4377 newPrivate->path = CFRetain(oldPrivate->path);
4378 }
4379 if (oldPrivate->overrides != NULL) {
4380 newPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->overrides);
4381 }
4382 newPrivate->modemIsV92 = oldPrivate->modemIsV92;
4383 newPrivate->supportsBond = oldPrivate->supportsBond;
4384 newPrivate->supportsVLAN = oldPrivate->supportsVLAN;
4385 if (oldPrivate->type != NULL) {
4386 newPrivate->type = CFRetain(oldPrivate->type);
4387 }
4388 if (oldPrivate->unit != NULL) {
4389 newPrivate->unit = CFRetain(oldPrivate->unit);
4390 }
4391 newPrivate->sort_order = oldPrivate->sort_order;
4392 if (oldPrivate->bond.interfaces != NULL) {
4393 newPrivate->bond.interfaces = CFRetain(oldPrivate->bond.interfaces);
4394 }
4395 if (oldPrivate->bond.mode != NULL) {
4396 newPrivate->bond.mode = CFRetain(oldPrivate->bond.mode);
4397 }
4398 if (oldPrivate->bond.options != NULL) {
4399 newPrivate->bond.options = CFRetain(oldPrivate->bond.options);
4400 }
4401 if (oldPrivate->vlan.interface != NULL) {
4402 newPrivate->vlan.interface = CFRetain(oldPrivate->vlan.interface);
4403 }
4404 if (oldPrivate->vlan.tag != NULL) {
4405 newPrivate->vlan.tag = CFRetain(oldPrivate->vlan.tag);
4406 }
4407 if (oldPrivate->vlan.options != NULL) {
4408 newPrivate->vlan.options = CFRetain(oldPrivate->vlan.options);
4409 }
4410
4411 return newPrivate;
4412 }
4413
4414
4415 __private_extern__
4416 CFArrayRef
4417 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkInterfaceRef interface)
4418 {
4419 CFMutableArrayRef configs;
4420
4421 configs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
4422
4423 while (interface != NULL) {
4424 CFStringRef defaultType;
4425 CFMutableDictionaryRef interfaceConfiguration;
4426
4427 interfaceConfiguration = CFDictionaryCreateMutable(NULL,
4428 0,
4429 &kCFTypeDictionaryKeyCallBacks,
4430 &kCFTypeDictionaryValueCallBacks);
4431
4432 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
4433 if (defaultType != NULL) {
4434 CFDictionaryRef config;
4435 CFArrayRef extendedTypes;
4436
4437 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType);
4438 if (config == NULL) {
4439 config = (CFDictionaryRef)kCFNull;
4440 }
4441 CFDictionarySetValue(interfaceConfiguration, defaultType, config);
4442
4443 extendedTypes = extendedConfigurationTypes(interface);
4444 if (extendedTypes != NULL) {
4445 CFIndex i;
4446 CFIndex n;
4447
4448 n = CFArrayGetCount(extendedTypes);
4449 for (i = 0; i < n; i++) {
4450 CFStringRef extendedType;
4451
4452 extendedType = CFArrayGetValueAtIndex(extendedTypes, i);
4453 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType);
4454 if (config == NULL) {
4455 config = (CFDictionaryRef)kCFNull;
4456 }
4457 CFDictionarySetValue(interfaceConfiguration, extendedType, config);
4458 }
4459
4460 CFRelease(extendedTypes);
4461 }
4462 }
4463
4464 CFArrayAppendValue(configs, interfaceConfiguration);
4465 CFRelease(interfaceConfiguration);
4466
4467 interface = SCNetworkInterfaceGetInterface(interface);
4468 }
4469
4470 return configs;
4471 }
4472
4473
4474 __private_extern__
4475 void
4476 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkInterfaceRef interface, CFArrayRef configs)
4477 {
4478 CFIndex i;
4479
4480 for (i = 0; interface != NULL; i++) {
4481 CFStringRef defaultType;
4482 CFDictionaryRef interfaceConfiguration;
4483
4484 interfaceConfiguration = (configs != NULL) ? CFArrayGetValueAtIndex(configs, i) : NULL;
4485
4486 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
4487 if (defaultType != NULL) {
4488 CFDictionaryRef config;
4489 CFArrayRef extendedTypes;
4490
4491 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, defaultType)
4492 : NULL;
4493 if (config == (CFDictionaryRef)kCFNull) {
4494 config = NULL;
4495 }
4496 if (!__SCNetworkInterfaceSetConfiguration(interface, defaultType, config, TRUE)) {
4497 SCLog(TRUE, LOG_DEBUG,
4498 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
4499 interface,
4500 defaultType);
4501 }
4502
4503 extendedTypes = extendedConfigurationTypes(interface);
4504 if (extendedTypes != NULL) {
4505 CFIndex j;
4506 CFIndex n;
4507
4508 n = CFArrayGetCount(extendedTypes);
4509 for (j = 0; j < n; j++) {
4510 CFStringRef extendedType;
4511
4512 extendedType = CFArrayGetValueAtIndex(extendedTypes, j);
4513 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, extendedType)
4514 : NULL;
4515 if (config == (CFDictionaryRef)kCFNull) {
4516 config = NULL;
4517 }
4518 if (!__SCNetworkInterfaceSetConfiguration(interface, extendedType, config, TRUE)) {
4519 SCLog(TRUE, LOG_DEBUG,
4520 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
4521 interface,
4522 defaultType);
4523 }
4524 }
4525
4526 CFRelease(extendedTypes);
4527 }
4528 }
4529
4530 interface = SCNetworkInterfaceGetInterface(interface);
4531 }
4532
4533 return;
4534 }