status_t add_interface(const char* name, net_domain_private* domain, const ifaliasreq& request, net_device_interface* deviceInterface) { RecursiveLocker locker(sLock); if (find_interface(name) != NULL) return B_NAME_IN_USE; Interface* interface = new(std::nothrow) Interface(name, deviceInterface); if (interface == NULL) return B_NO_MEMORY; sInterfaces.Add(interface); interface->AcquireReference(); // We need another reference to be able to use the interface without // holding sLock. locker.Unlock(); status_t status = add_interface_address(interface, domain, request); if (status == B_OK) notify_interface_added(interface); else { locker.Lock(); sInterfaces.Remove(interface); locker.Unlock(); interface->ReleaseReference(); } interface->ReleaseReference(); return status; }
status_t add_interface_to_domain(net_domain* _domain, struct ifreq& request) { net_domain_private* domain = (net_domain_private*)_domain; const char* deviceName = request.ifr_parameter.device[0] ? request.ifr_parameter.device : request.ifr_name; const char* baseName = request.ifr_parameter.base_name[0] ? request.ifr_parameter.base_name : request.ifr_name; net_device_interface* deviceInterface = get_device_interface(deviceName); if (deviceInterface == NULL) return ENODEV; RecursiveLocker locker(domain->lock); net_interface_private* interface = NULL; status_t status; if (find_interface(domain, request.ifr_name) == NULL) { // We must not hold the domain's link when creating the interface: // this will call get_module() which might want to access a network // device when booting from network. locker.Unlock(); status = create_interface(domain, request.ifr_name, baseName, deviceInterface, &interface); locker.Lock(); if (find_interface(domain, request.ifr_name) != NULL) { delete_interface(interface); status = B_NAME_IN_USE; } } else status = B_NAME_IN_USE; put_device_interface(deviceInterface); if (status == B_OK) { list_add_item(&domain->interfaces, interface); notify_interface_added(interface); } return status; }