22
22
#include " source/common/common/utility.h"
23
23
#include " source/common/network/address_impl.h"
24
24
#include " source/common/network/io_socket_error_impl.h"
25
+ #include " source/common/network/ip_address_parsing.h"
25
26
#include " source/common/network/socket_option_impl.h"
26
27
#include " source/common/protobuf/protobuf.h"
27
28
#include " source/common/protobuf/utility.h"
@@ -106,75 +107,18 @@ Api::IoCallUint64Result receiveMessage(uint64_t max_rx_datagram_size, Buffer::In
106
107
return result;
107
108
}
108
109
109
- StatusOr<sockaddr_in> parseV4Address (const std::string& ip_address, uint16_t port) {
110
- sockaddr_in sa4;
111
- memset (&sa4, 0 , sizeof (sa4));
112
- if (inet_pton (AF_INET, ip_address.c_str (), &sa4.sin_addr ) != 1 ) {
113
- return absl::FailedPreconditionError (" failed parsing ipv4" );
114
- }
115
- sa4.sin_family = AF_INET;
116
- sa4.sin_port = htons (port);
117
- return sa4;
118
- }
119
-
120
- StatusOr<sockaddr_in6> parseV6Address (const std::string& ip_address, uint16_t port) {
121
- // Parse IPv6 with optional scope using getaddrinfo().
122
- // While inet_pton() would be faster and simpler, it does not support IPv6
123
- // addresses that specify a scope, e.g. `::%eth0` to listen on only one interface.
124
- struct addrinfo hints;
125
- memset (&hints, 0 , sizeof (hints));
126
- struct addrinfo * res = nullptr ;
127
- // Suppresses any potentially lengthy network host address lookups and inhibit the invocation of
128
- // a name resolution service.
129
- hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
130
- hints.ai_family = AF_INET6;
131
- // Given that we don't specify a service but we use getaddrinfo() to only parse the node
132
- // address, specifying the socket type allows to hint the getaddrinfo() to return only an
133
- // element with the below socket type. The behavior though remains platform dependent and anyway
134
- // we consume only the first element (if the call succeeds).
135
- hints.ai_socktype = SOCK_DGRAM;
136
- hints.ai_protocol = IPPROTO_UDP;
137
-
138
- // We want to use the interface of OsSysCalls for this for the
139
- // platform-independence, but we don't want to use the common
140
- // OsSysCallsSingleton.
141
- //
142
- // The problem with using OsSysCallsSingleton is that we likely
143
- // want to override getaddrinfo() for DNS lookups in tests, but
144
- // typically that override would resolve a name to e.g.
145
- // the address from resolveUrl("tcp://[::1]:80") - but resolveUrl
146
- // calls parseV6Address, which calls getaddrinfo(), so if we use
147
- // the mock *here* then mocking DNS causes infinite recursion.
148
- //
149
- // We don't ever need to mock *this* getaddrinfo() call, because
150
- // it's only used to parse numeric IP addresses, per `ai_flags`,
151
- // so it should be deterministic resolution; there's no need to
152
- // mock it to test failure cases.
153
- static Api::OsSysCallsImpl os_sys_calls;
154
-
155
- const Api::SysCallIntResult rc =
156
- os_sys_calls.getaddrinfo (ip_address.c_str (), /* service=*/ nullptr , &hints, &res);
157
- if (rc.return_value_ != 0 ) {
158
- return absl::FailedPreconditionError (fmt::format (" getaddrinfo error: {}" , rc.return_value_ ));
159
- }
160
- sockaddr_in6 sa6 = *reinterpret_cast <sockaddr_in6*>(res->ai_addr );
161
- os_sys_calls.freeaddrinfo (res);
162
- sa6.sin6_port = htons (port);
163
- return sa6;
164
- }
165
-
166
110
} // namespace
167
111
168
112
Address::InstanceConstSharedPtr
169
113
Utility::parseInternetAddressNoThrow (const std::string& ip_address, uint16_t port, bool v6only,
170
114
absl::optional<std::string> network_namespace) {
171
- StatusOr<sockaddr_in> sa4 = parseV4Address (ip_address, port);
115
+ StatusOr<sockaddr_in> sa4 = IpAddressParsing::parseIPv4 (ip_address, port);
172
116
if (sa4.ok ()) {
173
117
return instanceOrNull (Address::InstanceFactory::createInstancePtr<Address::Ipv4Instance>(
174
118
&sa4.value (), nullptr , network_namespace));
175
119
}
176
120
177
- StatusOr<sockaddr_in6> sa6 = parseV6Address (ip_address, port);
121
+ StatusOr<sockaddr_in6> sa6 = IpAddressParsing::parseIPv6 (ip_address, port);
178
122
if (sa6.ok ()) {
179
123
return instanceOrNull (Address::InstanceFactory::createInstancePtr<Address::Ipv6Instance>(
180
124
*sa6, v6only, nullptr , network_namespace));
@@ -200,7 +144,7 @@ Utility::parseInternetAddressAndPortNoThrow(const std::string& ip_address, bool
200
144
if (port_str.empty () || !absl::SimpleAtoi (port_str, &port64) || port64 > 65535 ) {
201
145
return nullptr ;
202
146
}
203
- StatusOr<sockaddr_in6> sa6 = parseV6Address (ip_str, port64);
147
+ StatusOr<sockaddr_in6> sa6 = IpAddressParsing::parseIPv6 (ip_str, static_cast < uint16_t >( port64) );
204
148
if (sa6.ok ()) {
205
149
return instanceOrNull (Address::InstanceFactory::createInstancePtr<Address::Ipv6Instance>(
206
150
*sa6, v6only, nullptr , network_namespace));
@@ -218,7 +162,7 @@ Utility::parseInternetAddressAndPortNoThrow(const std::string& ip_address, bool
218
162
if (port_str.empty () || !absl::SimpleAtoi (port_str, &port64) || port64 > 65535 ) {
219
163
return nullptr ;
220
164
}
221
- StatusOr<sockaddr_in> sa4 = parseV4Address (ip_str, port64);
165
+ StatusOr<sockaddr_in> sa4 = IpAddressParsing::parseIPv4 (ip_str, static_cast < uint16_t >( port64) );
222
166
if (sa4.ok ()) {
223
167
return instanceOrNull (Address::InstanceFactory::createInstancePtr<Address::Ipv4Instance>(
224
168
&sa4.value (), nullptr , network_namespace));
0 commit comments