| 1 | // Copyright (C) Microsoft Corporation. All rights reserved. |
| 2 | |
| 3 | #include "precomp.h" |
| 4 | #include "BridgedNetworking.h" |
| 5 | #include "hcs.hpp" |
| 6 | |
| 7 | using wsl::core::BridgedNetworking; |
| 8 | using wsl::core::networking::NetworkSettings; |
| 9 | using namespace wsl::windows::common; |
| 10 | |
| 11 | BridgedNetworking::BridgedNetworking(HCS_SYSTEM system, const Config& config) : m_system(system), m_config(config) |
| 12 | { |
| 13 | } |
| 14 | |
| 15 | void BridgedNetworking::Initialize() |
| 16 | { |
| 17 | if (m_config.VmSwitch.empty()) |
| 18 | { |
| 19 | THROW_HR_WITH_USER_ERROR(WSL_E_VMSWITCH_NOT_SET, wsl::shared::Localization::MessageVmSwitchNotSet()); |
| 20 | } |
| 21 | |
| 22 | std::vector<std::wstring> availableSwitches; |
| 23 | wsl::windows::common::hcs::unique_hcn_network network; |
| 24 | std::optional<GUID> switchId; |
| 25 | for (const auto& id : wsl::core::networking::EnumerateNetworks()) |
| 26 | { |
| 27 | try |
| 28 | { |
| 29 | network = wsl::core::networking::OpenNetwork(id); |
| 30 | auto [networkProperties, propertiesString] = wsl::core::networking::QueryNetworkProperties(network.get()); |
| 31 | if (networkProperties.Name == m_config.VmSwitch) |
| 32 | { |
| 33 | switchId = id; |
| 34 | break; |
| 35 | } |
| 36 | |
| 37 | availableSwitches.emplace_back(std::move(networkProperties.Name)); |
| 38 | } |
| 39 | CATCH_LOG() |
| 40 | } |
| 41 | |
| 42 | if (!switchId.has_value()) |
| 43 | { |
| 44 | THROW_HR_WITH_USER_ERROR( |
| 45 | WSL_E_VMSWITCH_NOT_FOUND, |
| 46 | wsl::shared::Localization::MessageVmSwitchNotFound( |
| 47 | m_config.VmSwitch.c_str(), wsl::shared::string::Join<wchar_t>(availableSwitches, ',').c_str())); |
| 48 | } |
| 49 | |
| 50 | wsl::shared::hns::HostComputeEndpoint hnsEndpoint{}; |
| 51 | hnsEndpoint.SchemaVersion.Major = 2; |
| 52 | hnsEndpoint.SchemaVersion.Minor = 16; |
| 53 | hnsEndpoint.HostComputeNetwork = switchId.value(); |
| 54 | wsl::shared::hns::EndpointPolicy<wsl::shared::hns::PortnameEndpointPolicySetting> endpointPortNamePolicy{}; |
| 55 | endpointPortNamePolicy.Type = wsl::shared::hns::EndpointPolicyType::PortName; |
| 56 | hnsEndpoint.Policies.emplace_back(std::move(endpointPortNamePolicy)); |
| 57 | m_endpoint = wsl::core::networking::CreateEphemeralHcnEndpoint(network.get(), hnsEndpoint); |
| 58 | |
| 59 | hcs::ModifySettingRequest<hcs::NetworkAdapter> networkRequest{}; |
| 60 | networkRequest.Settings.MacAddress = m_config.MacAddress; |
| 61 | networkRequest.Settings.EndpointId = m_endpoint.Id; |
| 62 | networkRequest.Settings.InstanceId = m_endpoint.Id; |
| 63 | networkRequest.RequestType = hcs::ModifyRequestType::Add; |
| 64 | networkRequest.ResourcePath = networking::c_networkAdapterPrefix + |
| 65 | wsl::shared::string::GuidToString<wchar_t>(m_endpoint.Id, wsl::shared::string::GuidToStringFlags::None); |
| 66 | |
| 67 | windows::common::hcs::ModifyComputeSystem(m_system, wsl::shared::ToJsonW(networkRequest).c_str()); |
| 68 | } |
| 69 | |
| 70 | void BridgedNetworking::TraceLoggingRundown() noexcept |
| 71 | { |
| 72 | // No-op. |
| 73 | } |
| 74 | |
| 75 | void BridgedNetworking::FillInitialConfiguration(LX_MINI_INIT_NETWORKING_CONFIGURATION& message) |
| 76 | { |
| 77 | message.NetworkingMode = LxMiniInitNetworkingModeBridged; |
| 78 | message.DisableIpv6 = !m_config.EnableIpv6; |
| 79 | message.EnableDhcpClient = m_config.EnableDhcp; |
| 80 | message.DhcpTimeout = static_cast<int>(std::round(m_config.DhcpTimeout / 1000.0)); |
| 81 | message.PortTrackerType = m_config.EnableLocalhostRelay ? LxMiniInitPortTrackerTypeRelay : LxMiniInitPortTrackerTypeNone; |
| 82 | } |
| 83 | |
| 84 | void BridgedNetworking::StartPortTracker(wil::unique_socket&&) |
| 85 | { |
| 86 | WI_ASSERT(false); |
| 87 | } |