]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/BridgeConfiguration.c
configd-395.10.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / BridgeConfiguration.c
1 /*
2 * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * July 27, 2009 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
34
35 #include <SystemConfiguration/SystemConfiguration.h>
36 #include "SCNetworkConfigurationInternal.h"
37 #include <SystemConfiguration/SCValidation.h>
38 #include <SystemConfiguration/SCPrivate.h>
39
40 #include <ifaddrs.h>
41 #include <pthread.h>
42 #include <unistd.h>
43 #include <sys/types.h>
44 #include <sys/ioctl.h>
45 #include <sys/socket.h>
46 #include <sys/sysctl.h>
47 #include <net/ethernet.h>
48 #define KERNEL_PRIVATE
49 #include <net/if.h>
50 #include <net/if_var.h>
51 #undef KERNEL_PRIVATE
52 #include <net/if_types.h>
53 #include <net/if_media.h>
54 #include <net/route.h>
55
56 #ifdef IFT_BRIDGE
57 #include <net/if_bridgevar.h>
58 #endif // IFT_BRIDGE
59
60 /* ---------- Bridge support ---------- */
61
62 static int
63 inet_dgram_socket()
64 {
65 int s;
66
67 s = socket(AF_INET, SOCK_DGRAM, 0);
68 if (s == -1) {
69 SCLog(TRUE, LOG_ERR, CFSTR("socket() failed: %s"), strerror(errno));
70 }
71
72 return s;
73 }
74
75 #ifdef IFT_BRIDGE
76 static struct ifbifconf *
77 ifbifconf_copy(int s, const char * ifname)
78 {
79 void * buf;
80 size_t buflen;
81 struct ifbifconf * ibc_p = NULL;
82 struct ifdrv ifd;
83 uint32_t len = sizeof(struct ifbreq) * 16;
84
85 bzero(&ifd, sizeof(ifd));
86 strncpy(ifd.ifd_name, ifname, sizeof(ifd.ifd_name));
87 ifd.ifd_cmd = BRDGGIFS;
88
89 buflen = sizeof(struct ifbifconf) + len;
90 buf = malloc(buflen);
91 while (buf != NULL) {
92 bzero(buf, buflen);
93 ibc_p = (struct ifbifconf *)buf;
94 ibc_p->ifbic_len = len;
95 ibc_p->ifbic_buf = buf + sizeof(*ibc_p);
96
97 ifd.ifd_len = sizeof(*ibc_p);
98 ifd.ifd_data = ibc_p;
99 if (ioctl(s, SIOCGDRVSPEC, (caddr_t)&ifd) == -1) {
100 goto failed;
101 }
102
103 if ((ibc_p->ifbic_len + sizeof(struct ifbreq)) < len) {
104 // if we have room for all of the member interfaces
105 break;
106 }
107
108 len *= 2;
109 buflen = sizeof(struct ifbifconf) + len;
110 buf = reallocf(buf, buflen);
111 }
112
113 if (buf == NULL) {
114 goto failed;
115 }
116
117 return ibc_p;
118
119 failed:
120 if (buf != NULL) {
121 free(buf);
122 }
123 return NULL;
124 }
125 #endif // IFT_BRIDGE
126
127
128 static void
129 add_interface(CFMutableArrayRef *interfaces, CFStringRef if_name)
130 {
131 SCNetworkInterfaceRef interface;
132
133 if (*interfaces == NULL) {
134 *interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
135 }
136
137 interface = _SCNetworkInterfaceCreateWithBSDName(NULL, if_name,
138 kIncludeNoVirtualInterfaces);
139 CFArrayAppendValue(*interfaces, interface);
140 CFRelease(interface);
141 }
142
143
144 static Boolean
145 _SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge, CFArrayRef members);
146
147
148 typedef struct {
149 CFMutableArrayRef bridges;
150 SCPreferencesRef prefs;
151 } addContext, *addContextRef;
152
153
154 static void
155 add_configured_interface(const void *key, const void *value, void *context)
156 {
157 SCBridgeInterfaceRef bridge;
158 CFStringRef bridge_if = (CFStringRef)key;
159 CFDictionaryRef bridge_info = (CFDictionaryRef)value;
160 CFDictionaryRef bridge_options;
161 CFIndex i;
162 CFArrayRef interfaces;
163 SCNetworkInterfacePrivateRef interfacePrivate;
164 CFMutableArrayRef members = NULL;
165 addContextRef myContext = (addContextRef)context;
166 CFStringRef name;
167 CFIndex n;
168
169 // create the bridge interface
170 bridge = (SCBridgeInterfaceRef)_SCBridgeInterfaceCreatePrivate(NULL, bridge_if);
171
172 // add member interfaces
173 interfaces = CFDictionaryGetValue(bridge_info, kSCPropVirtualNetworkInterfacesBridgeInterfaces);
174 n = isA_CFArray(interfaces) ? CFArrayGetCount(interfaces) : 0;
175 for (i = 0; i < n; i++) {
176 CFStringRef member;
177
178 member = CFArrayGetValueAtIndex(interfaces, i);
179 if (isA_CFString(member)) {
180 add_interface(&members, member);
181 }
182 }
183 if (members != NULL) {
184 _SCBridgeInterfaceSetMemberInterfaces(bridge, members);
185 CFRelease(members);
186 }
187
188 // set display name
189 name = CFDictionaryGetValue(bridge_info, kSCPropUserDefinedName);
190 if (isA_CFString(name)) {
191 SCBridgeInterfaceSetLocalizedDisplayName(bridge, name);
192 }
193
194 // set options
195 bridge_options = CFDictionaryGetValue(bridge_info, kSCPropVirtualNetworkInterfacesBridgeOptions);
196 if (isA_CFDictionary(bridge_options)) {
197 SCBridgeInterfaceSetOptions(bridge, bridge_options);
198 }
199
200 // estabish link to the stored configuration
201 interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
202 interfacePrivate->prefs = CFRetain(myContext->prefs);
203
204 CFArrayAppendValue(myContext->bridges, bridge);
205 CFRelease(bridge);
206
207 return;
208 }
209
210
211 #pragma mark -
212 #pragma mark SCBridgeInterface APIs
213
214
215 CFArrayRef
216 SCBridgeInterfaceCopyAll(SCPreferencesRef prefs)
217 {
218 addContext context;
219 CFDictionaryRef dict;
220 CFStringRef path;
221
222 context.bridges = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
223 context.prefs = prefs;
224
225 path = CFStringCreateWithFormat(NULL,
226 NULL,
227 CFSTR("/%@/%@"),
228 kSCPrefVirtualNetworkInterfaces,
229 kSCNetworkInterfaceTypeBridge);
230 dict = SCPreferencesPathGetValue(prefs, path);
231 if (isA_CFDictionary(dict)) {
232 CFDictionaryApplyFunction(dict, add_configured_interface, &context);
233 }
234 CFRelease(path);
235
236 return context.bridges;
237 }
238
239
240 __private_extern__ void
241 __SCBridgeInterfaceListCollectMembers(CFArrayRef interfaces, CFMutableSetRef set)
242 {
243 CFIndex i;
244 CFIndex n;
245
246 n = CFArrayGetCount(interfaces);
247 for (i = 0; i < n; i++) {
248 SCBridgeInterfaceRef bridgeInterface;
249 CFArrayRef members;
250
251 bridgeInterface = CFArrayGetValueAtIndex(interfaces, i);
252 members = SCBridgeInterfaceGetMemberInterfaces(bridgeInterface);
253 if (members != NULL) {
254 CFIndex j;
255 CFIndex n_members;
256
257 // exclude the member interfaces of this bridge
258 n_members = CFArrayGetCount(members);
259 for (j = 0; j < n_members; j++) {
260 SCNetworkInterfaceRef member;
261
262 member = CFArrayGetValueAtIndex(members, j);
263 CFSetAddValue(set, member);
264 }
265 }
266
267 }
268 return;
269 }
270
271
272 CFArrayRef /* of SCNetworkInterfaceRef's */
273 SCBridgeInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs)
274 {
275 CFMutableArrayRef available;
276 CFMutableSetRef excluded;
277 CFArrayRef interfaces;
278
279 available = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
280 excluded = CFSetCreateMutable (NULL, 0, &kCFTypeSetCallBacks);
281
282 // exclude Bond [member] interfaces
283 interfaces = SCBondInterfaceCopyAll(prefs);
284 if (interfaces != NULL) {
285 __SCBondInterfaceListCollectMembers(interfaces, excluded);
286 CFRelease(interfaces);
287 }
288
289 // exclude Bridge [member] interfaces
290 interfaces = SCBridgeInterfaceCopyAll(prefs);
291 if (interfaces != NULL) {
292 __SCBridgeInterfaceListCollectMembers(interfaces, excluded);
293 CFRelease(interfaces);
294 }
295
296 // exclude VLAN [physical] interfaces
297 interfaces = SCVLANInterfaceCopyAll(prefs);
298 if (interfaces != NULL) {
299 CFIndex i;
300 CFIndex n;
301
302 n = CFArrayGetCount(interfaces);
303 for (i = 0; i < n; i++) {
304 SCVLANInterfaceRef vlanInterface;
305 SCNetworkInterfaceRef physical;
306
307 // exclude the physical interface of this VLAN
308 vlanInterface = CFArrayGetValueAtIndex(interfaces, i);
309 physical = SCVLANInterfaceGetPhysicalInterface(vlanInterface);
310 CFSetAddValue(excluded, physical);
311 }
312 CFRelease(interfaces);
313 }
314
315 // identify available interfaces
316 interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
317 if (interfaces != NULL) {
318 CFIndex i;
319 CFIndex n;
320
321 n = CFArrayGetCount(interfaces);
322 for (i = 0; i < n; i++) {
323 SCNetworkInterfaceRef interface;
324 SCNetworkInterfacePrivateRef interfacePrivate;
325
326 interface = CFArrayGetValueAtIndex(interfaces, i);
327 interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
328
329 if (!interfacePrivate->supportsBridge) {
330 // if this interface is not available
331 continue;
332 }
333
334 if (CFSetContainsValue(excluded, interface)) {
335 // if excluded
336 continue;
337 }
338
339 CFArrayAppendValue(available, interface);
340 }
341 CFRelease(interfaces);
342 }
343
344 CFRelease(excluded);
345
346 return available;
347 }
348
349
350 CFArrayRef
351 _SCBridgeInterfaceCopyActive(void)
352 {
353 struct ifaddrs *ifap;
354 struct ifaddrs *ifp;
355 int s;
356 CFMutableArrayRef bridges = NULL;
357
358 if (getifaddrs(&ifap) == -1) {
359 _SCErrorSet(errno);
360 SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
361 return NULL;
362 }
363
364 s = inet_dgram_socket();
365 if (s == -1) {
366 _SCErrorSet(errno);
367 goto done;
368 }
369
370 bridges = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
371
372 for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) {
373 #ifdef IFT_BRIDGE
374 SCBridgeInterfaceRef bridge;
375 CFStringRef bridge_if;
376 struct ifbifconf *ibc_p;
377 struct if_data *if_data;
378 CFMutableArrayRef members = NULL;
379
380 if_data = (struct if_data *)ifp->ifa_data;
381 if (if_data == NULL
382 || ifp->ifa_addr->sa_family != AF_LINK
383 || if_data->ifi_type != IFT_BRIDGE) {
384 continue;
385 }
386
387 ibc_p = ifbifconf_copy(s, ifp->ifa_name);
388 if (ibc_p == NULL) {
389 if (errno == EBUSY) {
390 continue;
391 }
392 _SCErrorSet(errno);
393 SCLog(TRUE, LOG_ERR,
394 CFSTR("ifbifconf_copy(%s) failed: %s"),
395 ifp->ifa_name,
396 strerror(errno));
397 CFRelease(bridges);
398 bridges = NULL;
399 goto done;
400 }
401
402 // create the bridge interface
403 bridge_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII);
404 bridge = (SCBridgeInterfaceRef)_SCBridgeInterfaceCreatePrivate(NULL, bridge_if);
405 CFRelease(bridge_if);
406
407 // add member interfaces
408 if (ibc_p->ifbic_len > 0) {
409 int i;
410
411 // iterate over each member interface
412 for (i = 0; i < ibc_p->ifbic_len / sizeof(struct ifbreq); i++) {
413 struct ifbreq *ibr_p;
414 CFStringRef member;
415
416 ibr_p = ibc_p->ifbic_req + i;
417 member = CFStringCreateWithCString(NULL, ibr_p->ifbr_ifsname, kCFStringEncodingASCII);
418 add_interface(&members, member);
419 CFRelease(member);
420 }
421 }
422 free(ibc_p);
423
424 if (members != NULL) {
425 _SCBridgeInterfaceSetMemberInterfaces(bridge, members);
426 CFRelease(members);
427 }
428
429 // add bridge
430 CFArrayAppendValue(bridges, bridge);
431 CFRelease(bridge);
432 #endif // IFT_BRIDGE
433 }
434
435 done :
436
437 (void) close(s);
438 freeifaddrs(ifap);
439 return bridges;
440 }
441
442
443 SCBridgeInterfaceRef
444 SCBridgeInterfaceCreate(SCPreferencesRef prefs)
445 {
446 CFAllocatorRef allocator;
447 SCBridgeInterfaceRef bridge = NULL;
448 CFIndex i;
449
450 if (prefs == NULL) {
451 _SCErrorSet(kSCStatusInvalidArgument);
452 return NULL;
453 }
454
455 allocator = CFGetAllocator(prefs);
456
457 // create a new bridge using an unused interface name
458 for (i = 0; bridge == NULL; i++) {
459 CFDictionaryRef dict;
460 CFStringRef bridge_if;
461 SCNetworkInterfacePrivateRef interfacePrivate;
462 CFMutableDictionaryRef newDict;
463 CFArrayRef newInterfaces;
464 Boolean ok;
465 CFStringRef path;
466
467 bridge_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("bridge%d"), i);
468 path = CFStringCreateWithFormat(allocator,
469 NULL,
470 CFSTR("/%@/%@/%@"),
471 kSCPrefVirtualNetworkInterfaces,
472 kSCNetworkInterfaceTypeBridge,
473 bridge_if);
474 dict = SCPreferencesPathGetValue(prefs, path);
475 if (dict != NULL) {
476 // if bridge interface name not available
477 CFRelease(path);
478 CFRelease(bridge_if);
479 continue;
480 }
481
482 // add the bridge to the stored preferences
483 newDict = CFDictionaryCreateMutable(allocator,
484 0,
485 &kCFTypeDictionaryKeyCallBacks,
486 &kCFTypeDictionaryValueCallBacks);
487 newInterfaces = CFArrayCreate(allocator, NULL, 0, &kCFTypeArrayCallBacks);
488 CFDictionaryAddValue(newDict, kSCPropVirtualNetworkInterfacesBridgeInterfaces, newInterfaces);
489 CFRelease(newInterfaces);
490 ok = SCPreferencesPathSetValue(prefs, path, newDict);
491 CFRelease(newDict);
492 CFRelease(path);
493 if (!ok) {
494 // if the bridge could not be saved
495 CFRelease(bridge_if);
496 break;
497 }
498
499 // create the SCBridgeInterfaceRef
500 bridge = (SCBridgeInterfaceRef)_SCBridgeInterfaceCreatePrivate(allocator, bridge_if);
501 CFRelease(bridge_if);
502
503 // estabish link to the stored configuration
504 interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
505 interfacePrivate->prefs = CFRetain(prefs);
506 }
507
508 return bridge;
509 }
510
511
512 Boolean
513 SCBridgeInterfaceRemove(SCBridgeInterfaceRef bridge)
514 {
515 CFStringRef bridge_if;
516 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
517 Boolean ok;
518 CFStringRef path;
519
520 if (!isA_SCBridgeInterface(bridge)) {
521 _SCErrorSet(kSCStatusInvalidArgument);
522 return FALSE;
523 }
524
525 if (interfacePrivate->prefs == NULL) {
526 _SCErrorSet(kSCStatusInvalidArgument);
527 return FALSE;
528 }
529
530 bridge_if = SCNetworkInterfaceGetBSDName(bridge);
531 path = CFStringCreateWithFormat(NULL,
532 NULL,
533 CFSTR("/%@/%@/%@"),
534 kSCPrefVirtualNetworkInterfaces,
535 kSCNetworkInterfaceTypeBridge,
536 bridge_if);
537 ok = SCPreferencesPathRemoveValue(interfacePrivate->prefs, path);
538 CFRelease(path);
539
540 return ok;
541 }
542
543
544 CFArrayRef
545 SCBridgeInterfaceGetMemberInterfaces(SCBridgeInterfaceRef bridge)
546 {
547 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
548
549 if (!isA_SCBridgeInterface(bridge)) {
550 _SCErrorSet(kSCStatusInvalidArgument);
551 return NULL;
552 }
553
554 return interfacePrivate->bridge.interfaces;
555 }
556
557
558 CFDictionaryRef
559 SCBridgeInterfaceGetOptions(SCBridgeInterfaceRef bridge)
560 {
561 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
562
563 if (!isA_SCBridgeInterface(bridge)) {
564 _SCErrorSet(kSCStatusInvalidArgument);
565 return NULL;
566 }
567
568 return interfacePrivate->bridge.options;
569 }
570
571
572 static Boolean
573 _SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge, CFArrayRef members)
574 {
575 CFIndex i;
576 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
577 CFIndex n;
578 CFMutableArrayRef newMembers;
579 Boolean ok = TRUE;
580
581 n = (members != NULL) ? CFArrayGetCount(members) : 0;
582
583 // set member interfaces in the stored preferences
584 if (interfacePrivate->prefs != NULL) {
585 CFDictionaryRef dict;
586 CFMutableDictionaryRef newDict;
587 CFStringRef path;
588
589 path = CFStringCreateWithFormat(NULL,
590 NULL,
591 CFSTR("/%@/%@/%@"),
592 kSCPrefVirtualNetworkInterfaces,
593 kSCNetworkInterfaceTypeBridge,
594 interfacePrivate->entity_device);
595 dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
596 if (!isA_CFDictionary(dict)) {
597 // if the prefs are confused
598 CFRelease(path);
599 _SCErrorSet(kSCStatusFailed);
600 return FALSE;
601 }
602
603 newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
604 for (i = 0; i < n; i++) {
605 SCNetworkInterfaceRef interface;
606 CFStringRef memberName;
607
608 interface = CFArrayGetValueAtIndex(members, i);
609 memberName = SCNetworkInterfaceGetBSDName(interface);
610 CFArrayAppendValue(newMembers, memberName);
611 }
612
613 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
614 CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesBridgeInterfaces, newMembers);
615 CFRelease(newMembers);
616
617 ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
618 CFRelease(newDict);
619 CFRelease(path);
620 }
621
622 if (ok) {
623 newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
624 for (i = 0; i < n; i++) {
625 SCNetworkInterfaceRef member;
626 SCNetworkInterfacePrivateRef newMember;
627
628 member = CFArrayGetValueAtIndex(members, i);
629 newMember = __SCNetworkInterfaceCreateCopy(NULL,
630 member,
631 interfacePrivate->prefs,
632 interfacePrivate->serviceID);
633 CFArrayAppendValue(newMembers, newMember);
634 CFRelease(newMember);
635 }
636 CFRelease(interfacePrivate->bridge.interfaces);
637 interfacePrivate->bridge.interfaces = newMembers;
638 }
639
640 return ok;
641 }
642
643
644 Boolean
645 SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge, CFArrayRef members)
646 {
647 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
648 Boolean ok;
649 int sc_status = kSCStatusOK;
650
651 if (!isA_SCBridgeInterface(bridge)) {
652 _SCErrorSet(kSCStatusInvalidArgument);
653 return FALSE;
654 }
655
656 if ((members != NULL) && !isA_CFArray(members)) {
657 _SCErrorSet(kSCStatusInvalidArgument);
658 return FALSE;
659 }
660
661 if (interfacePrivate->prefs != NULL) {
662 CFArrayRef available;
663 CFArrayRef current;
664 CFIndex i;
665 CFIndex n_available;
666 CFIndex n_current;
667 CFIndex n_members;
668 CFArrayRef services = NULL;
669
670 current = SCBridgeInterfaceGetMemberInterfaces(bridge);
671 n_current = (current != NULL) ? CFArrayGetCount(current) : 0;
672
673 available = SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate->prefs);
674 n_available = (available != NULL) ? CFArrayGetCount(available) : 0;
675
676 n_members = (members != NULL) ? CFArrayGetCount(members) : 0;
677 for (i = 0; i < n_members; i++) {
678 SCNetworkInterfaceRef member;
679
680 member = CFArrayGetValueAtIndex(members, i);
681
682 if ((current != NULL) &&
683 CFArrayContainsValue(current, CFRangeMake(0, n_current), member)) {
684 // current members are allowed
685 continue;
686 }
687
688 if ((available != NULL) &&
689 CFArrayContainsValue(available, CFRangeMake(0, n_available), member)) {
690 // available members are allowed but cannot be associated
691 // with any other network services.
692
693 if (services == NULL) {
694 services = __SCNetworkServiceCopyAllEnabled(interfacePrivate->prefs);
695 }
696 if ((services != NULL) &&
697 __SCNetworkServiceExistsForInterface(services, member)) {
698 sc_status = kSCStatusKeyExists;
699 break;
700 }
701
702 // if available
703 continue;
704 }
705
706 // if member not allowed
707 sc_status = kSCStatusInvalidArgument;
708 break;
709 }
710
711 if (available != NULL) CFRelease(available);
712 if (services != NULL) CFRelease(services);
713 }
714
715 if (sc_status != kSCStatusOK) {
716 _SCErrorSet(sc_status);
717 return FALSE;
718 }
719
720 ok = _SCBridgeInterfaceSetMemberInterfaces(bridge, members);
721 return ok;
722 }
723
724
725 Boolean
726 SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge, CFStringRef newName)
727 {
728 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
729 Boolean ok = TRUE;
730
731 if (!isA_SCBridgeInterface(bridge)) {
732 _SCErrorSet(kSCStatusInvalidArgument);
733 return FALSE;
734 }
735
736 if ((newName != NULL) && !isA_CFString(newName)) {
737 _SCErrorSet(kSCStatusInvalidArgument);
738 return FALSE;
739 }
740
741 // set name in the stored preferences
742 if (interfacePrivate->prefs != NULL) {
743 CFDictionaryRef dict;
744 CFMutableDictionaryRef newDict;
745 CFStringRef path;
746
747 path = CFStringCreateWithFormat(NULL,
748 NULL,
749 CFSTR("/%@/%@/%@"),
750 kSCPrefVirtualNetworkInterfaces,
751 kSCNetworkInterfaceTypeBridge,
752 interfacePrivate->entity_device);
753 dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
754 if (!isA_CFDictionary(dict)) {
755 // if the prefs are confused
756 CFRelease(path);
757 _SCErrorSet(kSCStatusFailed);
758 return FALSE;
759 }
760
761 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
762 if (newName != NULL) {
763 CFDictionarySetValue(newDict, kSCPropUserDefinedName, newName);
764 } else {
765 CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName);
766 }
767 ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
768 CFRelease(newDict);
769 CFRelease(path);
770 }
771
772 // set name in the SCBridgeInterfaceRef
773 if (ok) {
774 if (interfacePrivate->localized_name != NULL) {
775 CFRelease(interfacePrivate->localized_name);
776 interfacePrivate->localized_name = NULL;
777 }
778 if (newName != NULL) {
779 interfacePrivate->localized_name = CFStringCreateCopy(NULL, newName);
780 }
781 }
782
783 return ok;
784 }
785
786
787 Boolean
788 SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge, CFDictionaryRef newOptions)
789 {
790 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
791 Boolean ok = TRUE;
792
793 if (!isA_SCBridgeInterface(bridge)) {
794 _SCErrorSet(kSCStatusInvalidArgument);
795 return FALSE;
796 }
797
798 if ((newOptions != NULL) && !isA_CFDictionary(newOptions)) {
799 _SCErrorSet(kSCStatusInvalidArgument);
800 return FALSE;
801 }
802
803 // set options in the stored preferences
804 if (interfacePrivate->prefs != NULL) {
805 CFDictionaryRef dict;
806 CFMutableDictionaryRef newDict;
807 CFStringRef path;
808
809 path = CFStringCreateWithFormat(NULL,
810 NULL,
811 CFSTR("/%@/%@/%@"),
812 kSCPrefVirtualNetworkInterfaces,
813 kSCNetworkInterfaceTypeBridge,
814 interfacePrivate->entity_device);
815 dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
816 if (!isA_CFDictionary(dict)) {
817 // if the prefs are confused
818 CFRelease(path);
819 _SCErrorSet(kSCStatusFailed);
820 return FALSE;
821 }
822
823 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
824 if (newOptions != NULL) {
825 CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesBridgeOptions, newOptions);
826 } else {
827 CFDictionaryRemoveValue(newDict, kSCPropVirtualNetworkInterfacesBridgeOptions);
828 }
829 ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
830 CFRelease(newDict);
831 CFRelease(path);
832 }
833
834 // set options in the SCBridgeInterfaceRef
835 if (ok) {
836 if (interfacePrivate->bridge.options != NULL) {
837 CFRelease(interfacePrivate->bridge.options);
838 interfacePrivate->bridge.options = NULL;
839 }
840 if (newOptions != NULL) {
841 interfacePrivate->bridge.options = CFDictionaryCreateCopy(NULL, newOptions);
842 }
843 }
844
845 return ok;
846 }
847
848
849 #pragma mark -
850 #pragma mark SCBridgeInterface management
851
852
853 #ifdef IFT_BRIDGE
854 static Boolean
855 __bridge_add_interface(int s, CFStringRef bridge_if, CFStringRef interface_if)
856 {
857 struct ifbreq breq;
858 struct ifdrv ifd;
859
860 // bridge interface
861 bzero(&ifd, sizeof(ifd));
862 (void) _SC_cfstring_to_cstring(bridge_if,
863 ifd.ifd_name,
864 sizeof(ifd.ifd_name),
865 kCFStringEncodingASCII);
866 ifd.ifd_cmd = BRDGADD;
867 ifd.ifd_len = sizeof(breq);
868 ifd.ifd_data = (caddr_t)&breq;
869
870 // new bridge member
871 bzero(&breq, sizeof(breq));
872 (void) _SC_cfstring_to_cstring(interface_if,
873 breq.ifbr_ifsname,
874 sizeof(breq.ifbr_ifsname),
875 kCFStringEncodingASCII);
876
877 // add new bridge member
878 if (ioctl(s, SIOCSDRVSPEC, (caddr_t)&ifd) == -1) {
879 _SCErrorSet(errno);
880 SCLog(TRUE, LOG_ERR,
881 CFSTR("could not add interface \"%@\" to bridge \"%@\": %s"),
882 interface_if,
883 bridge_if,
884 strerror(errno));
885 return FALSE;
886 }
887
888 return TRUE;
889 }
890
891
892 static Boolean
893 __bridge_remove_interface(int s, CFStringRef bridge_if, CFStringRef interface_if)
894 {
895 struct ifbreq breq;
896 struct ifdrv ifd;
897
898 // bridge interface
899 bzero(&ifd, sizeof(ifd));
900 (void) _SC_cfstring_to_cstring(bridge_if,
901 ifd.ifd_name,
902 sizeof(ifd.ifd_name),
903 kCFStringEncodingASCII);
904 ifd.ifd_cmd = BRDGDEL;
905 ifd.ifd_len = sizeof(breq);
906 ifd.ifd_data = (caddr_t)&breq;
907
908 // bridge member to remove
909 bzero(&breq, sizeof(breq));
910 (void) _SC_cfstring_to_cstring(interface_if,
911 breq.ifbr_ifsname,
912 sizeof(breq.ifbr_ifsname),
913 kCFStringEncodingASCII);
914
915 // remove bridge member
916 if (ioctl(s, SIOCSDRVSPEC, (caddr_t)&ifd) == -1) {
917 _SCErrorSet(errno);
918 SCLog(TRUE, LOG_ERR,
919 CFSTR("could not add interface \"%@\" to bridge \"%@\": %s"),
920 interface_if,
921 bridge_if,
922 strerror(errno));
923 return FALSE;
924 }
925
926 return TRUE;
927 }
928 #endif // IFT_BRIDGE
929
930
931 Boolean
932 _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs)
933 {
934 #ifdef IFT_BRIDGE
935 CFArrayRef active = NULL;
936 CFArrayRef config = NULL;
937 CFIndex i;
938 CFIndex nActive;
939 CFIndex nConfig;
940 Boolean ok = TRUE;
941 int s = -1;
942
943 if (prefs == NULL) {
944 _SCErrorSet(kSCStatusInvalidArgument);
945 return FALSE;
946 }
947
948 /* configured Bridges */
949 config = SCBridgeInterfaceCopyAll(prefs);
950 nConfig = (config != NULL) ? CFArrayGetCount(config) : 0;
951
952 /* active Bridges */
953 active = _SCBridgeInterfaceCopyActive();
954 nActive = (active != NULL) ? CFArrayGetCount(active) : 0;
955
956 /*
957 * remove any no-longer-configured bridge interfaces and
958 * any devices associated with a bridge that are no longer
959 * associated with a bridge.
960 */
961 for (i = 0; i < nActive; i++) {
962 SCBridgeInterfaceRef a_bridge;
963 CFStringRef a_bridge_if;
964 CFIndex j;
965 Boolean found = FALSE;
966
967 a_bridge = CFArrayGetValueAtIndex(active, i);
968 a_bridge_if = SCNetworkInterfaceGetBSDName(a_bridge);
969
970 for (j = 0; j < nConfig; j++) {
971 SCBridgeInterfaceRef c_bridge;
972 CFStringRef c_bridge_if;
973
974 c_bridge = CFArrayGetValueAtIndex(config, j);
975 c_bridge_if = SCNetworkInterfaceGetBSDName(c_bridge);
976
977 if (CFEqual(a_bridge_if, c_bridge_if)) {
978 CFIndex a;
979 CFArrayRef a_bridge_interfaces;
980 CFIndex a_count;
981 CFArrayRef c_bridge_interfaces;
982 CFIndex c_count;
983
984 c_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(c_bridge);
985 c_count = (c_bridge_interfaces != NULL) ? CFArrayGetCount(c_bridge_interfaces) : 0;
986
987 a_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(a_bridge);
988 a_count = (a_bridge_interfaces != NULL) ? CFArrayGetCount(a_bridge_interfaces) : 0;
989
990 for (a = 0; a < a_count; a++) {
991 SCNetworkInterfaceRef a_interface;
992 CFStringRef a_interface_if;
993
994 a_interface = CFArrayGetValueAtIndex(a_bridge_interfaces, a);
995 if ((c_count == 0) ||
996 !CFArrayContainsValue(c_bridge_interfaces,
997 CFRangeMake(0, c_count),
998 a_interface)) {
999 /*
1000 * if this device is no longer part
1001 * of the bridge.
1002 */
1003 if (s == -1) {
1004 s = inet_dgram_socket();
1005 if (s == -1) {
1006 _SCErrorSet(errno);
1007 ok = FALSE;
1008 goto done;
1009 }
1010 }
1011
1012 a_interface_if = SCNetworkInterfaceGetBSDName(a_interface);
1013 if (!__bridge_remove_interface(s, a_bridge_if, a_interface_if)) {
1014 ok = FALSE;
1015 }
1016 }
1017 }
1018
1019 found = TRUE;
1020 break;
1021 }
1022 }
1023
1024 if (!found) {
1025 /*
1026 * if this interface is no longer configured
1027 */
1028 if (s == -1) {
1029 s = inet_dgram_socket();
1030 if (s == -1) {
1031 _SCErrorSet(errno);
1032 ok = FALSE;
1033 goto done;
1034 }
1035 }
1036
1037 if (!__destroyInterface(s, a_bridge_if)) {
1038 _SCErrorSet(errno);
1039 ok = FALSE;
1040 }
1041 }
1042 }
1043
1044 /*
1045 * add any newly-configured bridge interfaces and add any
1046 * devices that should now be associated with the bridge.
1047 */
1048 for (i = 0; i < nConfig; i++) {
1049 SCBridgeInterfaceRef c_bridge;
1050 CFArrayRef c_bridge_interfaces;
1051 CFStringRef c_bridge_if;
1052 CFIndex c_count;
1053 Boolean found = FALSE;
1054 CFIndex j;
1055
1056 c_bridge = CFArrayGetValueAtIndex(config, i);
1057 c_bridge_if = SCNetworkInterfaceGetBSDName(c_bridge);
1058 c_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(c_bridge);
1059 c_count = (c_bridge_interfaces != NULL) ? CFArrayGetCount(c_bridge_interfaces) : 0;
1060
1061 for (j = 0; j < nActive; j++) {
1062 SCBridgeInterfaceRef a_bridge;
1063 CFArrayRef a_bridge_interfaces;
1064 CFStringRef a_bridge_if;
1065 CFIndex a_count;
1066
1067 a_bridge = CFArrayGetValueAtIndex(active, j);
1068 a_bridge_if = SCNetworkInterfaceGetBSDName(a_bridge);
1069 a_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(a_bridge);
1070 a_count = (a_bridge_interfaces != NULL) ? CFArrayGetCount(a_bridge_interfaces) : 0;
1071
1072 if (CFEqual(c_bridge_if, a_bridge_if)) {
1073 CFIndex c;
1074 Boolean if_list_change = FALSE;
1075
1076 found = TRUE;
1077
1078 if (!_SC_CFEqual(c_bridge_interfaces, a_bridge_interfaces)) {
1079 if_list_change = TRUE;
1080 }
1081 if (!if_list_change) {
1082 break; // if no change
1083 }
1084 if (s == -1) {
1085 s = inet_dgram_socket();
1086 if (s == -1) {
1087 _SCErrorSet(errno);
1088 ok = FALSE;
1089 goto done;
1090 }
1091 }
1092 if (!if_list_change) {
1093 break; // no if list changes
1094 }
1095
1096 /*
1097 * ensure that the first device of the bridge matches, if
1098 * not then we remove all current devices and add them
1099 * back in the preferred order.
1100 */
1101 if ((c_count > 0) &&
1102 (a_count > 0) &&
1103 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces, 0),
1104 CFArrayGetValueAtIndex(a_bridge_interfaces, 0))) {
1105 CFIndex a;
1106
1107 for (a = 0; a < a_count; a++) {
1108 SCNetworkInterfaceRef a_interface;
1109 CFStringRef a_interface_if;
1110
1111 a_interface = CFArrayGetValueAtIndex(a_bridge_interfaces, a);
1112 if (!CFArrayContainsValue(c_bridge_interfaces,
1113 CFRangeMake(0, c_count),
1114 a_interface)) {
1115 continue; // if already removed
1116 }
1117
1118 a_interface_if = SCNetworkInterfaceGetBSDName(a_interface);
1119 if (!__bridge_remove_interface(s, a_bridge_if, a_interface_if)) {
1120 ok = FALSE;
1121 }
1122 }
1123
1124 a_count = 0; // all active devices have been removed
1125 }
1126
1127 /*
1128 * add any devices which are not currently associated
1129 * with the bridge interface.
1130 */
1131 for (c = 0; c < c_count; c++) {
1132 SCNetworkInterfaceRef c_interface;
1133 SCNetworkInterfacePrivateRef c_interfacePrivate;
1134 CFStringRef c_interface_if;
1135
1136 c_interface = CFArrayGetValueAtIndex(c_bridge_interfaces, c);
1137 if ((a_count == 0) ||
1138 !CFArrayContainsValue(a_bridge_interfaces,
1139 CFRangeMake(0, a_count),
1140 c_interface)) {
1141 /*
1142 * check if this member interface can be added to a bridge.
1143 */
1144 c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface;
1145 if (!c_interfacePrivate->supportsBridge) {
1146 // if member not supported
1147 continue;
1148 }
1149
1150 /*
1151 * if this member interface is not currently part of the bridge.
1152 */
1153 c_interface_if = SCNetworkInterfaceGetBSDName(c_interface);
1154 if (!__bridge_add_interface(s, c_bridge_if, c_interface_if)) {
1155 // if member could not be added
1156 ok = FALSE;
1157 }
1158 }
1159 }
1160
1161 break;
1162 }
1163 }
1164
1165 if (!found) {
1166 CFIndex c;
1167
1168 if (s == -1) {
1169 s = inet_dgram_socket();
1170 if (s == -1) {
1171 _SCErrorSet(errno);
1172 ok = FALSE;
1173 goto done;
1174 }
1175 }
1176
1177 /*
1178 * establish the new bridge interface.
1179 */
1180 if (!__createInterface(s, c_bridge_if)) {
1181 _SCErrorSet(errno);
1182 ok = FALSE;
1183 continue;
1184 }
1185
1186 /*
1187 * add the member interfaces
1188 */
1189 for (c = 0; c < c_count; c++) {
1190 SCNetworkInterfaceRef c_interface;
1191 SCNetworkInterfacePrivateRef c_interfacePrivate;
1192 CFStringRef c_interface_if;
1193
1194 c_interface = CFArrayGetValueAtIndex(c_bridge_interfaces, c);
1195 c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface;
1196 if (!c_interfacePrivate->supportsBridge) {
1197 // if member not supported
1198 continue;
1199 }
1200
1201 c_interface_if = SCNetworkInterfaceGetBSDName(c_interface);
1202 if (!__bridge_add_interface(s, c_bridge_if, c_interface_if)) {
1203 // if member could not be added
1204 ok = FALSE;
1205 }
1206 }
1207 }
1208
1209 }
1210
1211 done :
1212
1213 if (active != NULL) CFRelease(active);
1214 if (config != NULL) CFRelease(config);
1215 if (s != -1) (void) close(s);
1216
1217 return ok;
1218 #else // IFT_BRIDGE
1219 return TRUE;
1220 #endif // IFT_BRIDGE
1221 }