+ __interface_set_down(iface, true);
+}
+
+void
+interface_add_user(struct interface_user *dep, struct interface *iface)
+{
+ dep->iface = iface;
+ list_add(&dep->list, &iface->users);
+ if (iface->state == IFS_UP)
+ dep->cb(dep, IFEV_UP);
+}
+
+void
+interface_remove_user(struct interface_user *dep)
+{
+ list_del_init(&dep->list);
+ dep->iface = NULL;
+}
+
+static void
+interface_claim_device(struct interface *iface)
+{
+ struct device *dev;
+
+ if (iface->proto_handler &&
+ !(iface->proto_handler->flags & PROTO_FLAG_NODEV)) {
+ dev = device_get(iface->ifname, true);
+ if (dev)
+ device_add_user(&iface->main_dev, dev);
+ }
+}
+
+
+static void
+interface_cleanup(struct interface *iface)
+{
+ struct interface_user *dep, *tmp;
+
+ list_for_each_entry_safe(dep, tmp, &iface->users, list)
+ interface_remove_user(dep);
+
+ interface_clear_dns(iface);
+ interface_clear_errors(iface);
+ if (iface->main_dev.dev)
+ device_remove_user(&iface->main_dev);
+ interface_set_proto_state(iface, NULL);
+}
+
+static void
+interface_do_free(struct interface *iface)
+{
+ interface_cleanup(iface);
+ free(iface->config);
+ netifd_ubus_remove_interface(iface);
+ avl_delete(&interfaces.avl, &iface->node.avl);
+ free(iface);
+}
+
+static void
+interface_do_reload(struct interface *iface)
+{
+ interface_cleanup(iface);
+
+ interface_claim_device(iface);
+ proto_init_interface(iface, iface->config);
+
+ if (iface->autostart && !config_init)
+ interface_set_up(iface);
+}
+
+static void
+interface_handle_config_change(struct interface *iface)
+{
+ switch(iface->config_state) {
+ case IFC_NORMAL:
+ break;
+ case IFC_RELOAD:
+ interface_do_reload(iface);
+ break;
+ case IFC_REMOVE:
+ interface_do_free(iface);
+ break;
+ }