master
cpp 138 lines 5.57 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 #include "precomp.h"
4 #include "hns_schema.h"
5 #include "WslCoreNetworkEndpointSettings.h"
6 #include "WslCoreHostDnsInfo.h"
7
8 using namespace wsl::shared;
9
10 std::shared_ptr<wsl::core::networking::NetworkSettings> wsl::core::networking::GetEndpointSettings(const hns::HNSEndpoint& properties)
11 {
12 EndpointIpAddress address{};
13 address.Address = windows::common::string::StringToSockAddrInet(properties.IPAddress);
14 address.AddressString = properties.IPAddress;
15 address.PrefixLength = properties.PrefixLength;
16
17 EndpointRoute route{};
18 route.DestinationPrefix.PrefixLength = 0;
19 IN4ADDR_SETANY(&route.DestinationPrefix.Prefix.Ipv4);
20 route.DestinationPrefixString = LX_INIT_UNSPECIFIED_ADDRESS;
21 route.NextHop = windows::common::string::StringToSockAddrInet(properties.GatewayAddress);
22 route.NextHopString = properties.GatewayAddress;
23
24 return std::make_shared<wsl::core::networking::NetworkSettings>(
25 properties.InterfaceConstraint.InterfaceGuid,
26 address,
27 EndpointIpAddress{},
28 route,
29 EndpointRoute{},
30 properties.MacAddress,
31 properties.InterfaceConstraint.InterfaceIndex,
32 properties.InterfaceConstraint.InterfaceMediaType);
33 }
34
35 std::shared_ptr<wsl::core::networking::NetworkSettings> wsl::core::networking::GetHostEndpointSettings()
36 {
37 auto addresses = AdapterAddresses::GetCurrent();
38 auto bestIndex = GetBestInterface();
39 auto bestInterfacePtr =
40 std::find_if(addresses.cbegin(), addresses.cend(), [&](const auto& address) { return address->IfIndex == bestIndex; });
41 if (bestInterfacePtr == addresses.end())
42 {
43 return std::make_shared<NetworkSettings>();
44 }
45
46 const auto& bestInterface = *bestInterfacePtr;
47
48 std::wstring macAddress = wsl::shared::string::FormatMacAddress(
49 wsl::shared::string::MacAddress{
50 bestInterface->PhysicalAddress[0],
51 bestInterface->PhysicalAddress[1],
52 bestInterface->PhysicalAddress[2],
53 bestInterface->PhysicalAddress[3],
54 bestInterface->PhysicalAddress[4],
55 bestInterface->PhysicalAddress[5]},
56 L'-');
57
58 EndpointIpAddress address{};
59 auto firstIpv4Address = bestInterface->FirstUnicastAddress;
60 while (firstIpv4Address && firstIpv4Address->Address.lpSockaddr->sa_family != AF_INET)
61 {
62 firstIpv4Address = firstIpv4Address->Next;
63 }
64 if (firstIpv4Address)
65 {
66 address.Address.Ipv4 = *reinterpret_cast<SOCKADDR_IN*>(firstIpv4Address->Address.lpSockaddr);
67 address.AddressString = windows::common::string::SockAddrInetToWstring(address.Address);
68 address.PrefixLength = firstIpv4Address->OnLinkPrefixLength;
69 }
70
71 // Find the first global-scope (non-link-local) IPv6 unicast address.
72 EndpointIpAddress ipv6Address{};
73 auto nextUnicastAddress = bestInterface->FirstUnicastAddress;
74 while (nextUnicastAddress)
75 {
76 if (nextUnicastAddress->Address.lpSockaddr->sa_family == AF_INET6)
77 {
78 const auto& sin6 = *reinterpret_cast<SOCKADDR_IN6*>(nextUnicastAddress->Address.lpSockaddr);
79 if (!IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) && !IN6_IS_ADDR_LOOPBACK(&sin6.sin6_addr))
80 {
81 ipv6Address.Address.Ipv6 = sin6;
82 ipv6Address.AddressString = windows::common::string::SockAddrInetToWstring(ipv6Address.Address);
83 ipv6Address.PrefixLength = nextUnicastAddress->OnLinkPrefixLength;
84 break;
85 }
86 }
87 nextUnicastAddress = nextUnicastAddress->Next;
88 }
89
90 // Helper to find the first gateway address of a given family.
91 auto findGatewayAddress = [](PIP_ADAPTER_GATEWAY_ADDRESS list, ADDRESS_FAMILY family) -> PIP_ADAPTER_GATEWAY_ADDRESS {
92 while (list && list->Address.lpSockaddr->sa_family != family)
93 {
94 list = list->Next;
95 }
96 return list;
97 };
98
99 // Build IPv4 default route.
100 EndpointRoute route{};
101 const auto v4Gateway = findGatewayAddress(bestInterface->FirstGatewayAddress, AF_INET);
102 if (v4Gateway)
103 {
104 SOCKADDR_INET v4NextHop{};
105 v4NextHop.Ipv4 = *reinterpret_cast<SOCKADDR_IN*>(v4Gateway->Address.lpSockaddr);
106 route = EndpointRoute::DefaultRoute(AF_INET, v4NextHop);
107 }
108 else if (address.Address.si_family == AF_INET)
109 {
110 // Synthesize a gateway from the first host address in the subnet.
111 SOCKADDR_INET gatewayAddr{};
112 gatewayAddr.si_family = AF_INET;
113 const uint32_t hostAddr = ntohl(address.Address.Ipv4.sin_addr.s_addr);
114 const uint32_t mask = (address.PrefixLength == 0) ? 0u : ~((1u << (32u - address.PrefixLength)) - 1u);
115 gatewayAddr.Ipv4.sin_addr.s_addr = htonl((hostAddr & mask) | 1u);
116 route = EndpointRoute::DefaultRoute(AF_INET, gatewayAddr);
117 }
118
119 // Build IPv6 default route.
120 EndpointRoute v6Route{};
121 const auto v6Gateway = findGatewayAddress(bestInterface->FirstGatewayAddress, AF_INET6);
122 if (v6Gateway)
123 {
124 SOCKADDR_INET v6NextHop{};
125 v6NextHop.Ipv6 = *reinterpret_cast<SOCKADDR_IN6*>(v6Gateway->Address.lpSockaddr);
126 v6Route = EndpointRoute::DefaultRoute(AF_INET6, v6NextHop);
127 }
128
129 return std::make_shared<NetworkSettings>(
130 bestInterface->NetworkGuid,
131 std::move(address),
132 std::move(ipv6Address),
133 std::move(route),
134 std::move(v6Route),
135 std::move(macAddress),
136 bestInterface->IfIndex,
137 bestInterface->IfType);
138 }