diff --git a/repos/gems/src/app/sculpt_manager/model/nic_target.h b/repos/gems/src/app/sculpt_manager/model/nic_target.h index 18b58b5220..91c1e7ad00 100644 --- a/repos/gems/src/app/sculpt_manager/model/nic_target.h +++ b/repos/gems/src/app/sculpt_manager/model/nic_target.h @@ -21,20 +21,55 @@ namespace Sculpt { struct Nic_target; } struct Sculpt::Nic_target : Noncopyable { - enum Type { OFF, LOCAL, WIRED, WIFI } type { OFF }; - enum Policy { MANAGED, MANUAL } policy { MANAGED }; bool manual() const { return policy == MANUAL; } bool managed() const { return policy == MANAGED; } - bool local() const { return type == LOCAL; } - bool wired() const { return type == WIRED; } - bool wifi() const { return type == WIFI; } + /* + * The 'UNDEFINED' state is used solely at the startup when neither a + * managed or manual policy is known. Once a manually managed 'nic_router' + * config is provided, it takes precedence over the 'UNDEFINED' managed + * state. + */ + enum Type { UNDEFINED, OFF, LOCAL, WIRED, WIFI }; - bool nic_router_needed() const { return type != OFF; } + /** + * Interactive selection by the user, used when managed policy is in effect + */ + Type managed_type { UNDEFINED }; - bool ready() const { return type == WIRED || type == WIFI; } + /** + * Selection by the manually-provided NIC-router configuration + */ + Type manual_type { UNDEFINED }; + + /** + * Return currently active NIC target type + * + * This method never returns 'UNDEFINED'. + */ + Type type() const + { + /* + * Enforce the user's interactive choice to disable networking + * even if the NIC target is manually managed. + */ + if (managed_type == OFF) + return OFF; + + Type const result = manual() ? manual_type : managed_type; + + return (result == UNDEFINED) ? OFF : result; + } + + bool local() const { return type() == LOCAL; } + bool wired() const { return type() == WIRED; } + bool wifi() const { return type() == WIFI; } + + bool nic_router_needed() const { return type() != OFF; } + + bool ready() const { return type() == WIRED || type() == WIFI; } }; #endif /* _MODEL__NIC_TARGET_H_ */ diff --git a/repos/gems/src/app/sculpt_manager/network.cc b/repos/gems/src/app/sculpt_manager/network.cc index 5f7b0ad923..52c22b0647 100644 --- a/repos/gems/src/app/sculpt_manager/network.cc +++ b/repos/gems/src/app/sculpt_manager/network.cc @@ -70,9 +70,9 @@ void Sculpt::Network::_generate_nic_router_config() xml.node("default-policy", [&] () { xml.attribute("domain", "default"); }); - if (_nic_target.type != Nic_target::LOCAL) { + if (_nic_target.type() != Nic_target::LOCAL) { gen_named_node(xml, "domain", "uplink", [&] () { - switch (_nic_target.type) { + switch (_nic_target.type()) { case Nic_target::WIRED: xml.attribute("label", "wired"); break; case Nic_target::WIFI: xml.attribute("label", "wifi"); break; default: break; @@ -92,11 +92,11 @@ void Sculpt::Network::_generate_nic_router_config() xml.node("dhcp-server", [&] () { xml.attribute("ip_first", "10.0.1.2"); xml.attribute("ip_last", "10.0.1.200"); - if (_nic_target.type != Nic_target::LOCAL) { + if (_nic_target.type() != Nic_target::LOCAL) { xml.attribute("dns_server_from", "uplink"); } }); - if (_nic_target.type != Nic_target::LOCAL) { + if (_nic_target.type() != Nic_target::LOCAL) { xml.node("tcp", [&] () { xml.attribute("dst", "0.0.0.0/0"); xml.node("permit-any", [&] () { @@ -158,28 +158,34 @@ void Sculpt::Network::_handle_nic_router_state() void Sculpt::Network::_handle_nic_router_config(Xml_node config) { + Nic_target::Type target = _nic_target.managed_type; + _nic_target.policy = config.has_type("empty") ? Nic_target::MANAGED : Nic_target::MANUAL; - /* obtain uplink information from configuration */ - Nic_target::Type target = Nic_target::LOCAL; - target = Nic_target::LOCAL; + if (_nic_target.manual()) { - if (!config.has_sub_node("domain")) - target = Nic_target::OFF; + /* obtain uplink information from configuration */ + target = Nic_target::LOCAL; - config.for_each_sub_node("domain", [&] (Xml_node domain) { + if (!config.has_sub_node("domain")) + target = Nic_target::OFF; - /* skip non-uplink domains */ - if (domain.attribute_value("name", String<16>()) != "uplink") - return; + config.for_each_sub_node("domain", [&] (Xml_node domain) { - if (domain.attribute_value("label", String<16>()) == "wired") - target = Nic_target::WIRED; + /* skip non-uplink domains */ + if (domain.attribute_value("name", String<16>()) != "uplink") + return; - if (domain.attribute_value("label", String<16>()) == "wifi") - target = Nic_target::WIFI; - }); + if (domain.attribute_value("label", String<16>()) == "wired") + target = Nic_target::WIRED; + + if (domain.attribute_value("label", String<16>()) == "wifi") + target = Nic_target::WIFI; + }); + + _nic_target.manual_type = target; + } nic_target(target); _generate_nic_router_config(); @@ -196,7 +202,7 @@ void Sculpt::Network::gen_runtime_start_nodes(Xml_generator &xml) const if (_use_wifi_drv) xml.node("start", [&] () { gen_wifi_drv_start_content(xml); }); - if (_nic_target.type != Nic_target::OFF) + if (_nic_target.type() != Nic_target::OFF) xml.node("start", [&] () { gen_nic_router_start_content(xml); }); } diff --git a/repos/gems/src/app/sculpt_manager/network.h b/repos/gems/src/app/sculpt_manager/network.h index 03257527a2..3cb1c9404d 100644 --- a/repos/gems/src/app/sculpt_manager/network.h +++ b/repos/gems/src/app/sculpt_manager/network.h @@ -135,8 +135,8 @@ struct Sculpt::Network : Network_dialog::Action if (type == Nic_target::WIFI) _use_wifi_drv = true; if (type == Nic_target::WIRED) _use_nic_drv = true; - if (type != _nic_target.type) { - _nic_target.type = type; + if (type != _nic_target.managed_type) { + _nic_target.managed_type = type; _generate_nic_router_config(); _runtime_config_generator.generate_runtime_config(); _dialog_generator.generate_dialog(); diff --git a/repos/gems/src/app/sculpt_manager/view/network_dialog.cc b/repos/gems/src/app/sculpt_manager/view/network_dialog.cc index d578163a8e..bce0bc826b 100644 --- a/repos/gems/src/app/sculpt_manager/view/network_dialog.cc +++ b/repos/gems/src/app/sculpt_manager/view/network_dialog.cc @@ -204,7 +204,7 @@ void Sculpt::Network_dialog::generate(Xml_generator &xml) const _nic_item.gen_button_attr(xml, id); - if (_nic_target.type == type) + if (_nic_target.type() == type) xml.attribute("selected", "yes"); xml.node("label", [&] () { xml.attribute("text", label); }); @@ -217,18 +217,18 @@ void Sculpt::Network_dialog::generate(Xml_generator &xml) const * Allow interactive selection only if NIC-router configuration * is not manually maintained. */ - if (_nic_target.managed() || _nic_target.local()) + if (_nic_target.managed() || _nic_target.manual_type == Nic_target::LOCAL) gen_nic_button("local", Nic_target::LOCAL, "Local"); - if (_nic_target.managed() || _nic_target.wired()) + if (_nic_target.managed() || _nic_target.manual_type == Nic_target::WIRED) gen_nic_button("wired", Nic_target::WIRED, "Wired"); - if (_nic_target.managed() || _nic_target.wifi()) + if (_nic_target.managed() || _nic_target.manual_type == Nic_target::WIFI) if (_pci_info.wifi_present) gen_nic_button("wifi", Nic_target::WIFI, "Wifi"); }); - if (_nic_target.type == Nic_target::WIFI || _nic_target.type == Nic_target::WIRED) { + if (_nic_target.wifi() || _nic_target.wired()) { gen_named_node(xml, "frame", "nic_info", [&] () { xml.node("vbox", [&] () { @@ -238,7 +238,7 @@ void Sculpt::Network_dialog::generate(Xml_generator &xml) const * the complete list of access points with the option * to select one. */ - if (_nic_target.type == Nic_target::WIFI) { + if (_nic_target.wifi()) { if (_wifi_connection.connected()) _gen_connected_ap(xml); else diff --git a/repos/gems/src/app/sculpt_manager/view/network_dialog.h b/repos/gems/src/app/sculpt_manager/view/network_dialog.h index 66704db18f..6da9a8abf9 100644 --- a/repos/gems/src/app/sculpt_manager/view/network_dialog.h +++ b/repos/gems/src/app/sculpt_manager/view/network_dialog.h @@ -47,7 +47,7 @@ struct Sculpt::Network_dialog : Dialog Hoverable_item _nic_info { }; Hoverable_item _connect_item { }; /* confirm WPA passphrase */ - bool ap_list_hovered() const { return _nic_target.type == Nic_target::WIFI + bool ap_list_hovered() const { return _nic_target.wifi() && _nic_info.hovered("nic_info"); } /*