PRIVATE_EXTERN int interface_set_mtu(const char * ifname, int mtu) { int ret = 0; int s = inet_dgram_socket(); if (s < 0) { ret = errno; } else { if (siocsifmtu(s, ifname, mtu) < 0) { ret = errno; my_log(LOG_NOTICE, "siocsifmtu(%s, %d) failed, %s (%d)", ifname, mtu, strerror(ret), ret); } close(s); } return (ret); }
PRIVATE_EXTERN int inet_detach_interface(const char * ifname) { int ret = 0; int s = inet_dgram_socket(); if (s < 0) { ret = errno; goto done; } if (siocprotodetach(s, ifname) < 0) { ret = errno; if (ret != ENXIO) { my_log(LOG_ERR, "siocprotodetach(%s) failed, %s (%d)", ifname, strerror(errno), errno); } } close(s); done: return (ret); }
PRIVATE_EXTERN int inet_set_autoaddr(const char * ifname, int val) { int s = inet_dgram_socket(); int ret = 0; if (s < 0) { ret = errno; my_log(LOG_ERR, "inet_set_autoaddr(%s, %d): socket() failed, %s (%d)", ifname, val, strerror(errno), errno); } else { if (siocautoaddr(s, ifname, val) < 0) { ret = errno; if (ret != ENXIO) { my_log(LOG_ERR, "inet_set_autoaddr(%s, %d) failed, %s (%d)", ifname, val, strerror(errno), errno); } } close(s); } return (ret); }
PRIVATE_EXTERN int inet_attach_interface(const char * ifname) { int ret = 0; int s = inet_dgram_socket(); if (s < 0) { ret = errno; goto done; } if (siocprotoattach(s, ifname) < 0) { ret = errno; if (ret != EEXIST && ret != ENXIO) { my_log(LOG_DEBUG, "siocprotoattach(%s) failed, %s (%d)", ifname, strerror(errno), errno); } } (void)siocsifflags(s, ifname, IFF_UP); close(s); done: return (ret); }
Boolean _SCVLANInterfaceUpdateConfiguration(SCPreferencesRef prefs) { CFArrayRef active = NULL; CFArrayRef config = NULL; CFMutableDictionaryRef devices = NULL; CFIndex i; CFIndex nActive; CFIndex nConfig; Boolean ok = TRUE; int s = -1; if (prefs == NULL) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } /* configured VLANs */ config = SCVLANInterfaceCopyAll(prefs); nConfig = (config != NULL) ? CFArrayGetCount(config) : 0; /* physical interfaces */ devices = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); /* active VLANs */ active = _SCVLANInterfaceCopyActive(); nActive = (active != NULL) ? CFArrayGetCount(active) : 0; /* remove any no-longer-configured VLAN interfaces */ for (i = 0; i < nActive; i++) { SCVLANInterfaceRef a_vlan; CFStringRef a_vlan_if; CFIndex j; Boolean found = FALSE; a_vlan = CFArrayGetValueAtIndex(active, i); a_vlan_if = SCNetworkInterfaceGetBSDName(a_vlan); for (j = 0; j < nConfig; j++) { SCVLANInterfaceRef c_vlan; CFStringRef c_vlan_if; c_vlan = CFArrayGetValueAtIndex(config, j); c_vlan_if = SCNetworkInterfaceGetBSDName(c_vlan); if (CFEqual(a_vlan_if, c_vlan_if)) { found = TRUE; break; } } if (!found) { // remove VLAN interface if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } if (!__destroyInterface(s, a_vlan_if)) { ok = FALSE; _SCErrorSet(errno); } } } /* create (and update) configured VLAN interfaces */ for (i = 0; i < nConfig; i++) { SCVLANInterfaceRef c_vlan; CFStringRef c_vlan_if; SCNetworkInterfaceRef c_vlan_physical; Boolean found = FALSE; CFIndex j; CFBooleanRef supported; c_vlan = CFArrayGetValueAtIndex(config, i); c_vlan_if = SCNetworkInterfaceGetBSDName(c_vlan); c_vlan_physical = SCVLANInterfaceGetPhysicalInterface(c_vlan); if (c_vlan_physical == NULL) { continue; } // determine if the physical interface supports VLANs supported = CFDictionaryGetValue(devices, c_vlan_physical); if (supported == NULL) { SCNetworkInterfacePrivateRef c_vlan_physicalPrivate = (SCNetworkInterfacePrivateRef)c_vlan_physical; supported = c_vlan_physicalPrivate->supportsVLAN ? kCFBooleanTrue : kCFBooleanFalse; CFDictionaryAddValue(devices, c_vlan_physical, supported); } for (j = 0; j < nActive; j++) { SCVLANInterfaceRef a_vlan; CFStringRef a_vlan_if; a_vlan = CFArrayGetValueAtIndex(active, j); a_vlan_if = SCNetworkInterfaceGetBSDName(a_vlan); if (CFEqual(c_vlan_if, a_vlan_if)) { if (!CFEqual(c_vlan, a_vlan)) { // update VLAN interface if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } if (!CFBooleanGetValue(supported) || !__vlan_clear(s, c_vlan_if) || !__vlan_set(s, c_vlan_if, SCNetworkInterfaceGetBSDName(c_vlan_physical), SCVLANInterfaceGetTag(c_vlan))) { // something went wrong, try to blow the VLAN away if (!CFBooleanGetValue(supported)) { _SCErrorSet(kSCStatusFailed); } (void)__destroyInterface(s, c_vlan_if); ok = FALSE; } } found = TRUE; break; } } if (!found && CFBooleanGetValue(supported)) { // if the physical interface supports VLANs, add new interface Boolean created; if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } created = __createInterface(s, c_vlan_if); if (!created || !__vlan_set(s, c_vlan_if, SCNetworkInterfaceGetBSDName(c_vlan_physical), SCVLANInterfaceGetTag(c_vlan))) { if (created) { // something went wrong, try to blow the VLAN away (void)__destroyInterface(s, c_vlan_if); } else { _SCErrorSet(errno); } ok = FALSE; } } } done : if (active) CFRelease(active); if (config) CFRelease(config); if (devices) CFRelease(devices); if (s != -1) (void) close(s); return ok; }
CFArrayRef _SCVLANInterfaceCopyActive(void) { struct ifaddrs *ifap; struct ifaddrs *ifp; int s; CFMutableArrayRef vlans = NULL; if (getifaddrs(&ifap) == -1) { SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno)); _SCErrorSet(kSCStatusFailed); return NULL; } s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); goto done; } vlans = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) { struct if_data *if_data; struct ifreq ifr; SCVLANInterfaceRef vlan; CFStringRef vlan_if; SCNetworkInterfaceRef vlan_physical; CFStringRef vlan_physical_if; CFNumberRef vlan_tag; char vlr_parent[IFNAMSIZ]; int vlr_tag; struct vlanreq vreq; if_data = (struct if_data *)ifp->ifa_data; if (if_data == NULL || ifp->ifa_addr->sa_family != AF_LINK || if_data->ifi_type != IFT_L2VLAN) { continue; } bzero(&ifr, sizeof(ifr)); bzero(&vreq, sizeof(vreq)); strlcpy(ifr.ifr_name, ifp->ifa_name, sizeof(ifr.ifr_name)); ifr.ifr_data = (caddr_t)&vreq; if (ioctl(s, SIOCGIFVLAN, (caddr_t)&ifr) == -1) { SCLog(TRUE, LOG_ERR, CFSTR("ioctl() failed: %s"), strerror(errno)); CFRelease(vlans); vlans = NULL; _SCErrorSet(kSCStatusFailed); goto done; } // create the VLAN interface vlan_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII); vlan = (SCVLANInterfaceRef)_SCVLANInterfaceCreatePrivate(NULL, vlan_if); assert(vlan != NULL); CFRelease(vlan_if); // set the physical interface and tag strlcpy(vlr_parent, vreq.vlr_parent, sizeof(vlr_parent)); vlan_physical_if = CFStringCreateWithCString(NULL, vlr_parent, kCFStringEncodingASCII); vlan_physical = _SCNetworkInterfaceCreateWithBSDName(NULL, vlan_physical_if, kIncludeBondInterfaces); assert(vlan_physical != NULL); CFRelease(vlan_physical_if); vlr_tag = vreq.vlr_tag; vlan_tag = CFNumberCreate(NULL, kCFNumberIntType, &vlr_tag); assert(vlan_tag != NULL); SCVLANInterfaceSetPhysicalInterfaceAndTag(vlan, vlan_physical, vlan_tag); CFRelease(vlan_physical); CFRelease(vlan_tag); // add VLAN CFArrayAppendValue(vlans, vlan); CFRelease(vlan); } done : if (s != -1) { (void) close(s); } freeifaddrs(ifap); return vlans; }
CFArrayRef _SCBondInterfaceCopyActive(void) { struct ifaddrs *ifap; struct ifaddrs *ifp; int s; CFMutableArrayRef bonds = NULL; if (getifaddrs(&ifap) == -1) { _SCErrorSet(errno); SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno)); return NULL; } s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); goto done; } bonds = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) { SCBondInterfaceRef bond; CFStringRef bond_if; struct if_bond_status_req *ibsr_p; struct if_data *if_data; int int_val; CFNumberRef mode; CFMutableArrayRef members = NULL; if_data = (struct if_data *)ifp->ifa_data; if (if_data == NULL || ifp->ifa_addr->sa_family != AF_LINK || if_data->ifi_type != IFT_IEEE8023ADLAG) { continue; } ibsr_p = if_bond_status_req_copy(s, ifp->ifa_name); if (ibsr_p == NULL) { if (errno == EBUSY) { continue; } _SCErrorSet(errno); SCLog(TRUE, LOG_ERR, CFSTR("if_bond_status_req_copy(%s) failed: %s"), ifp->ifa_name, strerror(errno)); CFRelease(bonds); bonds = NULL; goto done; } // create the bond interface bond_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII); bond = (SCBondInterfaceRef)_SCBondInterfaceCreatePrivate(NULL, bond_if); CFRelease(bond_if); // set the mode int_val = ibsr_p->ibsr_mode; mode = CFNumberCreate(NULL, kCFNumberIntType, &int_val); assert(mode != NULL); _SCBondInterfaceSetMode(bond, mode); CFRelease(mode); // add member interfaces if (ibsr_p->ibsr_total > 0) { int i; struct if_bond_status * ibs_p; // iterate over each member interface ibs_p = (struct if_bond_status *)ibsr_p->ibsr_buffer; for (i = 0; i < ibsr_p->ibsr_total; i++) { CFStringRef member; member = CFStringCreateWithCString(NULL, ibs_p[i].ibs_if_name, kCFStringEncodingASCII); add_interface(&members, member); CFRelease(member); } } free(ibsr_p); if (members != NULL) { _SCBondInterfaceSetMemberInterfaces(bond, members); CFRelease(members); } // add bond CFArrayAppendValue(bonds, bond); CFRelease(bond); } done : if (s != -1) { (void) close(s); } freeifaddrs(ifap); return bonds; }
Boolean _SCBondInterfaceUpdateConfiguration(SCPreferencesRef prefs) { CFArrayRef active = NULL; CFArrayRef config = NULL; CFIndex i; CFIndex nActive; CFIndex nConfig; Boolean ok = TRUE; int s = -1; if (prefs == NULL) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } /* configured Bonds */ config = SCBondInterfaceCopyAll(prefs); nConfig = (config != NULL) ? CFArrayGetCount(config) : 0; /* active Bonds */ active = _SCBondInterfaceCopyActive(); nActive = (active != NULL) ? CFArrayGetCount(active) : 0; /* * remove any no-longer-configured bond interfaces and * any devices associated with a bond that are no longer * associated with a bond. */ for (i = 0; i < nActive; i++) { SCBondInterfaceRef a_bond; CFStringRef a_bond_if; CFIndex j; Boolean found = FALSE; a_bond = CFArrayGetValueAtIndex(active, i); a_bond_if = SCNetworkInterfaceGetBSDName(a_bond); for (j = 0; j < nConfig; j++) { SCBondInterfaceRef c_bond; CFStringRef c_bond_if; c_bond = CFArrayGetValueAtIndex(config, j); c_bond_if = SCNetworkInterfaceGetBSDName(c_bond); if (CFEqual(a_bond_if, c_bond_if)) { CFIndex a; CFArrayRef a_bond_interfaces; CFIndex a_count; CFArrayRef c_bond_interfaces; CFIndex c_count; c_bond_interfaces = SCBondInterfaceGetMemberInterfaces(c_bond); c_count = (c_bond_interfaces != NULL) ? CFArrayGetCount(c_bond_interfaces) : 0; a_bond_interfaces = SCBondInterfaceGetMemberInterfaces(a_bond); a_count = (a_bond_interfaces != NULL) ? CFArrayGetCount(a_bond_interfaces) : 0; for (a = 0; a < a_count; a++) { SCNetworkInterfaceRef a_interface; CFStringRef a_interface_if; a_interface = CFArrayGetValueAtIndex(a_bond_interfaces, a); if ((c_count == 0) || !CFArrayContainsValue(c_bond_interfaces, CFRangeMake(0, c_count), a_interface)) { /* * if this device is no longer part * of the bond. */ if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } a_interface_if = SCNetworkInterfaceGetBSDName(a_interface); if (!__bond_remove_interface(s, a_bond_if, a_interface_if)) { ok = FALSE; } } } found = TRUE; break; } } if (!found) { /* * if this interface is no longer configured */ if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } if (!__destroyInterface(s, a_bond_if)) { _SCErrorSet(errno); ok = FALSE; } } } /* * add any newly-configured bond interfaces and add any * devices that should now be associated with the bond. */ for (i = 0; i < nConfig; i++) { CFNumberRef c_bond_mode; SCBondInterfaceRef c_bond; CFArrayRef c_bond_interfaces; CFStringRef c_bond_if; CFIndex c_count; Boolean found = FALSE; CFIndex j; c_bond = CFArrayGetValueAtIndex(config, i); c_bond_if = SCNetworkInterfaceGetBSDName(c_bond); c_bond_interfaces = SCBondInterfaceGetMemberInterfaces(c_bond); c_bond_mode = SCBondInterfaceGetMode(c_bond); c_count = (c_bond_interfaces != NULL) ? CFArrayGetCount(c_bond_interfaces) : 0; for (j = 0; j < nActive; j++) { SCBondInterfaceRef a_bond; CFArrayRef a_bond_interfaces; CFNumberRef a_bond_mode; CFStringRef a_bond_if; CFIndex a_count; a_bond = CFArrayGetValueAtIndex(active, j); a_bond_if = SCNetworkInterfaceGetBSDName(a_bond); a_bond_interfaces = SCBondInterfaceGetMemberInterfaces(a_bond); a_bond_mode = SCBondInterfaceGetMode(a_bond); a_count = (a_bond_interfaces != NULL) ? CFArrayGetCount(a_bond_interfaces) : 0; if (CFEqual(c_bond_if, a_bond_if)) { CFIndex c; Boolean if_list_change = FALSE; Boolean mode_change = FALSE; found = TRUE; if (!_SC_CFEqual(a_bond_mode, c_bond_mode)) { mode_change = TRUE; } if (!_SC_CFEqual(c_bond_interfaces, a_bond_interfaces)) { if_list_change = TRUE; } if (!mode_change && !if_list_change) { break; // if no change } if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } if (mode_change) { __bond_set_mode(s, a_bond_if, c_bond_mode); } if (!if_list_change) { break; // no if list changes } /* * ensure that the first device of the bond matches, if * not then we remove all current devices and add them * back in the preferred order. */ if ((c_count > 0) && (a_count > 0) && !CFEqual(CFArrayGetValueAtIndex(c_bond_interfaces, 0), CFArrayGetValueAtIndex(a_bond_interfaces, 0))) { CFIndex a; for (a = 0; a < a_count; a++) { SCNetworkInterfaceRef a_interface; CFStringRef a_interface_if; a_interface = CFArrayGetValueAtIndex(a_bond_interfaces, a); if (!CFArrayContainsValue(c_bond_interfaces, CFRangeMake(0, c_count), a_interface)) { continue; // if already removed } a_interface_if = SCNetworkInterfaceGetBSDName(a_interface); if (!__bond_remove_interface(s, a_bond_if, a_interface_if)) { ok = FALSE; } } a_count = 0; // all active devices have been removed } /* * add any devices which are not currently associated * with the bond interface. */ for (c = 0; c < c_count; c++) { SCNetworkInterfaceRef c_interface; SCNetworkInterfacePrivateRef c_interfacePrivate; CFStringRef c_interface_if; c_interface = CFArrayGetValueAtIndex(c_bond_interfaces, c); if ((a_count == 0) || !CFArrayContainsValue(a_bond_interfaces, CFRangeMake(0, a_count), c_interface)) { /* * check if this member interface can be added to a bond. */ c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface; if (!c_interfacePrivate->supportsBond) { // if member not supported continue; } /* * if this member interface is not currently part of the bond. */ c_interface_if = SCNetworkInterfaceGetBSDName(c_interface); if (!__bond_add_interface(s, c_bond_if, c_interface_if)) { // if member could not be added ok = FALSE; } } } break; } } if (!found) { CFIndex c; if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } /* * establish the new bond interface. */ if (!__createInterface(s, c_bond_if)) { _SCErrorSet(errno); ok = FALSE; continue; } /* set the mode */ __bond_set_mode(s, c_bond_if, c_bond_mode); /* * add the member interfaces */ for (c = 0; c < c_count; c++) { SCNetworkInterfaceRef c_interface; SCNetworkInterfacePrivateRef c_interfacePrivate; CFStringRef c_interface_if; c_interface = CFArrayGetValueAtIndex(c_bond_interfaces, c); c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface; if (!c_interfacePrivate->supportsBond) { // if member not supported continue; } c_interface_if = SCNetworkInterfaceGetBSDName(c_interface); if (!__bond_add_interface(s, c_bond_if, c_interface_if)) { // if member could not be added ok = FALSE; } } } } done : if (active != NULL) CFRelease(active); if (config != NULL) CFRelease(config); if (s != -1) (void) close(s); return ok; }
SCBondStatusRef SCBondInterfaceCopyStatus(SCBondInterfaceRef bond) { int bond_if_active; int bond_if_status; CFIndex i; struct if_bond_status_req *ibsr_p = NULL; char if_name[IFNAMSIZ]; CFIndex n; CFNumberRef num; int s; struct if_bond_status *scan_p; SCBondStatusRef status = NULL; CFMutableDictionaryRef status_bond; CFMutableDictionaryRef status_interfaces; if (!isA_SCBondInterface(bond)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; } s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); goto done; } _SC_cfstring_to_cstring(SCNetworkInterfaceGetBSDName(bond), if_name, sizeof(if_name), kCFStringEncodingASCII); if (siocgifmedia(s, if_name, &bond_if_status, &bond_if_active) == -1) { _SCErrorSet(errno); switch (errno) { case EBUSY : case ENXIO : break; default : SCLog(TRUE, LOG_ERR, CFSTR("siocgifmedia(%s) failed: %s"), if_name, strerror(errno)); } goto done; } ibsr_p = if_bond_status_req_copy(s, if_name); if (ibsr_p == NULL) { _SCErrorSet(errno); goto done; } status_bond = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); status_interfaces = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); n = ibsr_p->ibsr_total; for (i = 0, scan_p = (struct if_bond_status *)ibsr_p->ibsr_buffer; i < n; i++, scan_p++) { int collecting = 0; int distributing = 0; SCNetworkInterfaceRef interface; CFStringRef interface_name; struct if_bond_partner_state * ps; CFMutableDictionaryRef status_interface; int status_val; ps = &scan_p->ibs_partner_state; if (lacp_actor_partner_state_in_sync(scan_p->ibs_state)) { /* we're in-sync */ status_val = kSCBondStatusOK; if (lacp_actor_partner_state_in_sync(ps->ibps_state)) { /* partner is also in-sync */ if (lacp_actor_partner_state_collecting(scan_p->ibs_state) && lacp_actor_partner_state_distributing(ps->ibps_state)) { /* we're able to collect (receive) frames */ collecting = 1; } if (lacp_actor_partner_state_distributing(scan_p->ibs_state) && lacp_actor_partner_state_collecting(ps->ibps_state)) { /* we're able to distribute (transmit) frames */ distributing = 1; } } } else { int active = 0; int status = 0; static lacp_system zeroes = { {0, 0, 0, 0, 0, 0}}; if (siocgifmedia(s, scan_p->ibs_if_name, &status, &active) == -1) { switch (errno) { case EBUSY : case ENXIO : break; default : SCLog(TRUE, LOG_ERR, CFSTR("siocgifmedia(%s) failed: %s"), if_name, strerror(errno)); break; } } if (((status & IFM_AVALID) == 0) || ((status & IFM_ACTIVE) == 0) || ((active & IFM_FDX ) == 0)) { /* link down or not full-duplex */ status_val = kSCBondStatusLinkInvalid; } else if ((ps->ibps_system_priority == 0) && (bcmp(&zeroes, &ps->ibps_system, sizeof(zeroes)) == 0)) { /* no one on the other end of the link */ status_val = kSCBondStatusNoPartner; } else if (active != bond_if_active) { /* the link speed was different */ status_val = kSCBondStatusLinkInvalid; } else { /* partner is not in the active group */ status_val = kSCBondStatusNotInActiveGroup; } } // interface strlcpy(if_name, scan_p->ibs_if_name, sizeof(if_name)); interface_name = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII); interface = _SCNetworkInterfaceCreateWithBSDName(NULL, interface_name, kIncludeNoVirtualInterfaces); CFRelease(interface_name); // interface status status_interface = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); num = CFNumberCreate(NULL, kCFNumberIntType, &status_val); CFDictionarySetValue(status_interface, kSCBondStatusDeviceAggregationStatus, num); CFRelease(num); num = CFNumberCreate(NULL, kCFNumberIntType, &collecting); CFDictionarySetValue(status_interface, kSCBondStatusDeviceCollecting, num); CFRelease(num); num = CFNumberCreate(NULL, kCFNumberIntType, &distributing); CFDictionarySetValue(status_interface, kSCBondStatusDeviceDistributing, num); CFRelease(num); CFDictionarySetValue(status_interfaces, interface, status_interface); CFRelease(interface); CFRelease(status_interface); } status = __SCBondStatusCreatePrivate(NULL, bond, status_bond, status_interfaces); CFRelease(status_bond); CFRelease(status_interfaces); done: if (s != -1) { close(s); } if (ibsr_p != NULL) { free(ibsr_p); } return (SCBondStatusRef)status; }