Interface::~Interface() { TRACE("Interface %p: destructor\n", this); put_device_interface(fDeviceInterface); // Uninitialize the domain datalink protocols DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); while (domain_datalink* datalink = iterator.Next()) { put_domain_datalink_protocols(this, datalink->domain); } // Free domain datalink objects domain_datalink* next = fDatalinkTable.Clear(true); while (next != NULL) { domain_datalink* datalink = next; next = next->hash_link; delete datalink; } recursive_lock_destroy(&fLock); // Release reference of the stack - at this point, our stack may be unloaded // if no other interfaces or sockets are left put_module(gNetStackInterfaceModule.info.name); }
status_t domain_interface_control(net_domain_private* domain, int32 option, ifreq* request) { const char* name = request->ifr_name; status_t status = B_OK; net_device_interface* device = get_device_interface(name, false); if (device == NULL) return ENODEV; RecursiveLocker _(domain->lock); net_interface* interface = find_interface(domain, name); if (interface != NULL) { switch (option) { case SIOCDIFADDR: remove_interface_from_domain(interface); break; case SIOCSIFFLAGS: { uint32 requestFlags = request->ifr_flags; request->ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST); if ((requestFlags & IFF_UP) != (interface->flags & IFF_UP)) { if (requestFlags & IFF_UP) { status = interface->first_info->interface_up( interface->first_protocol); if (status == B_OK) interface->flags |= IFF_UP; } else { interface_set_down(interface); } } if (status == B_OK) { // TODO: why shouldn't we able to delete IFF_BROADCAST? interface->flags &= IFF_UP | IFF_LINK | IFF_BROADCAST; interface->flags |= request->ifr_flags; } break; } } } // If the SIOCDIFADDR call above removed the last interface associated with // the device interface, this will effectively remove the interface put_device_interface(device); 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; }