master
cpp 174 lines 5.88 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 NetworkService.cpp
8
9 Abstract:
10
11 This file contains the NetworkService implementation
12
13 --*/
14 #include "NetworkService.h"
15 #include "WarningCallback.h"
16 #include <wslutil.h>
17 #include <wslc.h>
18
19 using namespace wsl::shared;
20 using namespace wsl::shared::string;
21 using namespace wsl::windows::common::wslutil;
22
23 namespace wsl::windows::wslc::services {
24
25 void NetworkService::Create(Terminal& terminal, models::Session& session, const models::CreateNetworkOptions& createOptions)
26 {
27 WarningCallback warningCallback(terminal);
28 WSLCNetworkOptions options{};
29 options.Name = createOptions.Name.c_str();
30 if (createOptions.Driver.has_value())
31 {
32 options.Driver = createOptions.Driver->c_str();
33 }
34
35 // Set driver options
36 std::vector<KeyValuePair> driverOpts;
37 for (const auto& option : createOptions.DriverOpts)
38 {
39 driverOpts.push_back({.Key = option.first.c_str(), .Value = option.second.c_str()});
40 }
41
42 // Set labels
43 std::vector<KeyValuePair> labels;
44 for (const auto& label : createOptions.Labels)
45 {
46 labels.push_back({.Key = label.first.c_str(), .Value = label.second.c_str()});
47 }
48
49 options.DriverOpts = driverOpts.data();
50 options.DriverOptsCount = static_cast<ULONG>(driverOpts.size());
51 options.Labels = labels.data();
52 options.LabelsCount = static_cast<ULONG>(labels.size());
53
54 options.Internal = createOptions.Internal ? TRUE : FALSE;
55 if (createOptions.Subnet.has_value())
56 {
57 options.Subnet = createOptions.Subnet->c_str();
58 }
59
60 if (createOptions.Gateway.has_value())
61 {
62 options.Gateway = createOptions.Gateway->c_str();
63 }
64
65 if (createOptions.IpRange.has_value())
66 {
67 options.IpRange = createOptions.IpRange->c_str();
68 }
69
70 THROW_IF_FAILED(session.Get()->CreateNetwork(&options, &warningCallback));
71 }
72
73 void NetworkService::Delete(models::Session& session, const std::string& name)
74 {
75 THROW_IF_FAILED(session.Get()->DeleteNetwork(name.c_str()));
76 }
77
78 std::vector<wsl::windows::common::wslc_schema::NetworkListEntry> NetworkService::List(
79 models::Session& session, const std::vector<std::pair<std::string, std::string>>& filters)
80 {
81 std::vector<WSLCFilter> filterEntries;
82 filterEntries.reserve(filters.size());
83 for (const auto& [key, value] : filters)
84 {
85 filterEntries.push_back({.Key = key.c_str(), .Value = value.c_str()});
86 }
87
88 wil::unique_cotaskmem_ansistring output;
89 THROW_IF_FAILED(session.Get()->ListNetworks(
90 filterEntries.empty() ? nullptr : filterEntries.data(), static_cast<ULONG>(filterEntries.size()), &output));
91
92 return FromJson<std::vector<wsl::windows::common::wslc_schema::NetworkListEntry>>(output.get());
93 }
94
95 wsl::windows::common::wslc_schema::Network NetworkService::Inspect(models::Session& session, const std::string& name)
96 {
97 wil::unique_cotaskmem_ansistring output;
98 THROW_IF_FAILED(session.Get()->InspectNetwork(name.c_str(), &output));
99 return FromJson<wsl::windows::common::wslc_schema::Network>(output.get());
100 }
101
102 models::PruneNetworksResult NetworkService::Prune(models::Session& session, const std::vector<std::pair<std::string, std::string>>& filters)
103 {
104 std::vector<WSLCFilter> filterEntries;
105 filterEntries.reserve(filters.size());
106 for (const auto& [key, value] : filters)
107 {
108 filterEntries.push_back({.Key = key.c_str(), .Value = value.c_str()});
109 }
110
111 wil::unique_cotaskmem_array_ptr<WSLCNetworkName> networks;
112 THROW_IF_FAILED(session.Get()->PruneNetworks(
113 filterEntries.empty() ? nullptr : filterEntries.data(), static_cast<ULONG>(filterEntries.size()), &networks, networks.size_address<ULONG>()));
114
115 models::PruneNetworksResult result;
116 result.PrunedNetworks.reserve(networks.size());
117 for (auto ptr = networks.get(), end = networks.get() + networks.size(); ptr != end; ++ptr)
118 {
119 result.PrunedNetworks.emplace_back(*ptr);
120 }
121
122 return result;
123 }
124
125 void NetworkService::Connect(models::Session& session, const models::ConnectNetworkOptions& connectOptions)
126 {
127 wil::com_ptr<IWSLCContainer> container;
128 THROW_IF_FAILED(session.Get()->OpenContainer(connectOptions.ContainerId.c_str(), &container));
129
130 // Build KVPs so the pointers remain valid for the duration of the ConnectToNetwork call.
131 std::vector<KeyValuePair> settings;
132 settings.reserve(
133 connectOptions.Aliases.size() + connectOptions.Links.size() + connectOptions.LinkLocalIps.size() +
134 connectOptions.DriverOpts.size() + (connectOptions.IpAddress.has_value() ? 1 : 0));
135
136 for (const auto& alias : connectOptions.Aliases)
137 {
138 settings.push_back({.Key = "Aliases", .Value = alias.c_str()});
139 }
140
141 if (connectOptions.IpAddress.has_value())
142 {
143 settings.push_back({.Key = "IPAddress", .Value = connectOptions.IpAddress->c_str()});
144 }
145
146 for (const auto& link : connectOptions.Links)
147 {
148 settings.push_back({.Key = "Links", .Value = link.c_str()});
149 }
150
151 for (const auto& linkLocalIp : connectOptions.LinkLocalIps)
152 {
153 settings.push_back({.Key = "LinkLocalIPs", .Value = linkLocalIp.c_str()});
154 }
155
156 for (const auto& entry : connectOptions.DriverOpts)
157 {
158 settings.push_back({.Key = "DriverOpts", .Value = entry.c_str()});
159 }
160
161 WSLCNetworkConnectionOptions options{};
162 options.NetworkName = connectOptions.NetworkName.c_str();
163 options.Settings = settings.empty() ? nullptr : settings.data();
164 options.SettingsCount = static_cast<ULONG>(settings.size());
165 THROW_IF_FAILED(container->ConnectToNetwork(&options));
166 }
167
168 void NetworkService::Disconnect(models::Session& session, const std::string& networkName, const std::string& containerId)
169 {
170 wil::com_ptr<IWSLCContainer> container;
171 THROW_IF_FAILED(session.Get()->OpenContainer(containerId.c_str(), &container));
172 THROW_IF_FAILED(container->DisconnectFromNetwork(networkName.c_str()));
173 }
174 } // namespace wsl::windows::wslc::services