Loading getaddrinfo.cpp +28 −13 Original line number Diff line number Diff line Loading @@ -147,7 +147,8 @@ static struct addrinfo* _gethtent(FILE**, const char*, const struct addrinfo*); static struct addrinfo* getCustomHosts(const size_t netid, const char*, const struct addrinfo*); static bool files_getaddrinfo(const size_t netid, const char* name, const addrinfo* pai, addrinfo** res); static int _find_src_addr(const struct sockaddr*, struct sockaddr*, unsigned, uid_t); static int _find_src_addr(const struct sockaddr*, struct sockaddr*, unsigned, uid_t, bool allow_v6_linklocal); static int res_queryN(const char* name, res_target* target, ResState* res, int* herrno); static int res_searchN(const char* name, res_target* target, ResState* res, int* herrno); Loading Loading @@ -220,13 +221,14 @@ void freeaddrinfo(struct addrinfo* ai) { * on the local system". However, bionic doesn't currently support getifaddrs, * so checking for connectivity is the next best thing. */ static int have_ipv6(unsigned mark, uid_t uid) { static int have_ipv6(unsigned mark, uid_t uid, bool mdns) { static const struct sockaddr_in6 sin6_test = { .sin6_family = AF_INET6, .sin6_addr.s6_addr = {// 2000:: 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; sockaddr_union addr = {.sin6 = sin6_test}; return _find_src_addr(&addr.sa, NULL, mark, uid) == 1; sockaddr sa; return _find_src_addr(&addr.sa, &sa, mark, uid, /*allow_v6_linklocal=*/mdns) == 1; } static int have_ipv4(unsigned mark, uid_t uid) { Loading @@ -235,7 +237,8 @@ static int have_ipv4(unsigned mark, uid_t uid) { .sin_addr.s_addr = __constant_htonl(0x08080808L) // 8.8.8.8 }; sockaddr_union addr = {.sin = sin_test}; return _find_src_addr(&addr.sa, NULL, mark, uid) == 1; sockaddr sa; return _find_src_addr(&addr.sa, &sa, mark, uid, /*(don't care) allow_v6_linklocal=*/false) == 1; } // Internal version of getaddrinfo(), but limited to AI_NUMERICHOST. Loading Loading @@ -1256,7 +1259,8 @@ static int _rfc6724_compare(const void* ptr1, const void* ptr2) { /* * Find the source address that will be used if trying to connect to the given * address. src_addr must be large enough to hold a struct sockaddr_in6. * address. src_addr must be assigned and large enough to hold a struct sockaddr_in6. * allow_v6_linklocal controls whether to accept link-local source addresses. * * Returns 1 if a source address was found, 0 if the address is unreachable, * and -1 if a fatal error occurred. If 0 or -1, the contents of src_addr are Loading @@ -1264,7 +1268,9 @@ static int _rfc6724_compare(const void* ptr1, const void* ptr2) { */ static int _find_src_addr(const struct sockaddr* addr, struct sockaddr* src_addr, unsigned mark, uid_t uid) { uid_t uid, bool allow_v6_linklocal) { if (src_addr == nullptr) return -1; int sock; int ret; socklen_t len; Loading Loading @@ -1306,10 +1312,19 @@ static int _find_src_addr(const struct sockaddr* addr, struct sockaddr* src_addr return 0; } if (src_addr && getsockname(sock, src_addr, &len) == -1) { if (getsockname(sock, src_addr, &len) == -1) { close(sock); return -1; } if (src_addr->sa_family == AF_INET6) { sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(src_addr); if (!allow_v6_linklocal && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { close(sock); return 0; } } close(sock); return 1; } Loading Loading @@ -1347,7 +1362,8 @@ void resolv_rfc6724_sort(struct addrinfo* list_sentinel, unsigned mark, uid_t ui elems[i].ai = cur; elems[i].original_order = i; has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.sa, mark, uid); has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.sa, mark, uid, /*allow_v6_linklocal=*/true); if (has_src_addr == -1) { goto error; } Loading @@ -1372,6 +1388,8 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, NetworkDnsEventReported* event) { res_target q = {}; res_target q2 = {}; ResState res(netcontext, event); setMdnsFlag(name, res.netid, &(res.flags)); switch (pai->ai_family) { case AF_UNSPEC: { Loading @@ -1380,7 +1398,8 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, q.qclass = C_IN; int query_ipv6 = 1, query_ipv4 = 1; if (pai->ai_flags & AI_ADDRCONFIG) { query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid); query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid, isMdnsResolution(res.flags)); query_ipv4 = have_ipv4(netcontext->app_mark, netcontext->uid); } if (query_ipv6) { Loading Loading @@ -1412,10 +1431,6 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, return EAI_FAMILY; } ResState res(netcontext, event); setMdnsFlag(name, res.netid, &(res.flags)); int he; if (res_searchN(name, &q, &res, &he) < 0) { // Return h_errno (he) to catch more detailed errors rather than EAI_NODATA. Loading Loading
getaddrinfo.cpp +28 −13 Original line number Diff line number Diff line Loading @@ -147,7 +147,8 @@ static struct addrinfo* _gethtent(FILE**, const char*, const struct addrinfo*); static struct addrinfo* getCustomHosts(const size_t netid, const char*, const struct addrinfo*); static bool files_getaddrinfo(const size_t netid, const char* name, const addrinfo* pai, addrinfo** res); static int _find_src_addr(const struct sockaddr*, struct sockaddr*, unsigned, uid_t); static int _find_src_addr(const struct sockaddr*, struct sockaddr*, unsigned, uid_t, bool allow_v6_linklocal); static int res_queryN(const char* name, res_target* target, ResState* res, int* herrno); static int res_searchN(const char* name, res_target* target, ResState* res, int* herrno); Loading Loading @@ -220,13 +221,14 @@ void freeaddrinfo(struct addrinfo* ai) { * on the local system". However, bionic doesn't currently support getifaddrs, * so checking for connectivity is the next best thing. */ static int have_ipv6(unsigned mark, uid_t uid) { static int have_ipv6(unsigned mark, uid_t uid, bool mdns) { static const struct sockaddr_in6 sin6_test = { .sin6_family = AF_INET6, .sin6_addr.s6_addr = {// 2000:: 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; sockaddr_union addr = {.sin6 = sin6_test}; return _find_src_addr(&addr.sa, NULL, mark, uid) == 1; sockaddr sa; return _find_src_addr(&addr.sa, &sa, mark, uid, /*allow_v6_linklocal=*/mdns) == 1; } static int have_ipv4(unsigned mark, uid_t uid) { Loading @@ -235,7 +237,8 @@ static int have_ipv4(unsigned mark, uid_t uid) { .sin_addr.s_addr = __constant_htonl(0x08080808L) // 8.8.8.8 }; sockaddr_union addr = {.sin = sin_test}; return _find_src_addr(&addr.sa, NULL, mark, uid) == 1; sockaddr sa; return _find_src_addr(&addr.sa, &sa, mark, uid, /*(don't care) allow_v6_linklocal=*/false) == 1; } // Internal version of getaddrinfo(), but limited to AI_NUMERICHOST. Loading Loading @@ -1256,7 +1259,8 @@ static int _rfc6724_compare(const void* ptr1, const void* ptr2) { /* * Find the source address that will be used if trying to connect to the given * address. src_addr must be large enough to hold a struct sockaddr_in6. * address. src_addr must be assigned and large enough to hold a struct sockaddr_in6. * allow_v6_linklocal controls whether to accept link-local source addresses. * * Returns 1 if a source address was found, 0 if the address is unreachable, * and -1 if a fatal error occurred. If 0 or -1, the contents of src_addr are Loading @@ -1264,7 +1268,9 @@ static int _rfc6724_compare(const void* ptr1, const void* ptr2) { */ static int _find_src_addr(const struct sockaddr* addr, struct sockaddr* src_addr, unsigned mark, uid_t uid) { uid_t uid, bool allow_v6_linklocal) { if (src_addr == nullptr) return -1; int sock; int ret; socklen_t len; Loading Loading @@ -1306,10 +1312,19 @@ static int _find_src_addr(const struct sockaddr* addr, struct sockaddr* src_addr return 0; } if (src_addr && getsockname(sock, src_addr, &len) == -1) { if (getsockname(sock, src_addr, &len) == -1) { close(sock); return -1; } if (src_addr->sa_family == AF_INET6) { sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(src_addr); if (!allow_v6_linklocal && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { close(sock); return 0; } } close(sock); return 1; } Loading Loading @@ -1347,7 +1362,8 @@ void resolv_rfc6724_sort(struct addrinfo* list_sentinel, unsigned mark, uid_t ui elems[i].ai = cur; elems[i].original_order = i; has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.sa, mark, uid); has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.sa, mark, uid, /*allow_v6_linklocal=*/true); if (has_src_addr == -1) { goto error; } Loading @@ -1372,6 +1388,8 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, NetworkDnsEventReported* event) { res_target q = {}; res_target q2 = {}; ResState res(netcontext, event); setMdnsFlag(name, res.netid, &(res.flags)); switch (pai->ai_family) { case AF_UNSPEC: { Loading @@ -1380,7 +1398,8 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, q.qclass = C_IN; int query_ipv6 = 1, query_ipv4 = 1; if (pai->ai_flags & AI_ADDRCONFIG) { query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid); query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid, isMdnsResolution(res.flags)); query_ipv4 = have_ipv4(netcontext->app_mark, netcontext->uid); } if (query_ipv6) { Loading Loading @@ -1412,10 +1431,6 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, return EAI_FAMILY; } ResState res(netcontext, event); setMdnsFlag(name, res.netid, &(res.flags)); int he; if (res_searchN(name, &q, &res, &he) < 0) { // Return h_errno (he) to catch more detailed errors rather than EAI_NODATA. Loading