Switch from inet_pton to getaddrinfo
This is intended to fix DNS-over-TLS server address parsing in cases
where the address is an IPv6 link-local address that is marked with
a scopeid.
Bug: 70320049
Bug: 63731765
Test: Integration tests pass. (No IPv6 scope-id test coverage!)
Change-Id: If19ffb988d8c9ee7f42b2a2eafffe1bf408b005b
diff --git a/server/ResolverController.cpp b/server/ResolverController.cpp
index 5488d96..e0dc9f1 100644
--- a/server/ResolverController.cpp
+++ b/server/ResolverController.cpp
@@ -63,25 +63,22 @@
return std::string(out);
}
-bool parseServer(const char* server, in_port_t port, sockaddr_storage* parsed) {
- sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(parsed);
- if (inet_pton(AF_INET, server, &(sin->sin_addr)) == 1) {
- // IPv4 parse succeeded, so it's IPv4
- sin->sin_family = AF_INET;
- sin->sin_port = htons(port);
- return true;
+bool parseServer(const char* server, sockaddr_storage* parsed) {
+ addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV
+ };
+ addrinfo* res;
+
+ int err = getaddrinfo(server, "853", &hints, &res);
+ if (err != 0) {
+ ALOGW("Failed to parse server address (%s): %s", server, gai_strerror(err));
+ return false;
}
- sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(parsed);
- if (inet_pton(AF_INET6, server, &(sin6->sin6_addr)) == 1){
- // IPv6 parse succeeded, so it's IPv6.
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = htons(port);
- return true;
- }
- if (DBG) {
- ALOGW("Failed to parse server address: %s", server);
- }
- return false;
+
+ memcpy(parsed, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ return true;
}
// Structure for tracking the validation status of servers on a specific netId.
@@ -158,7 +155,7 @@
std::set<DnsTlsServer> set;
for (size_t i = 0; i < servers.size(); ++i) {
sockaddr_storage parsed;
- if (!parseServer(servers[i].c_str(), 853, &parsed)) {
+ if (!parseServer(servers[i].c_str(), &parsed)) {
return -EINVAL;
}
DnsTlsServer server(parsed);