diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c index b9439f7..91b4d30 100644 --- a/src/network/getaddrinfo.c +++ b/src/network/getaddrinfo.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include "lookup.h" int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res) @@ -43,6 +46,35 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru } } + if (flags & AI_ADDRCONFIG) { + static const struct sockaddr_in lo4 = { + .sin_family = AF_INET, .sin_port = 65535, + .sin_addr.s_addr = __BYTE_ORDER == __BIG_ENDIAN + ? 0x7f000001 : 0x0100007f + }; + static const struct sockaddr_in6 lo6 = { + .sin6_family = AF_INET6, .sin6_port = 65535, + .sin6_addr = IN6ADDR_LOOPBACK_INIT + }; + int tf[2] = { AF_INET, AF_INET6 }; + const void *ta[2] = { &lo4, &lo6 }; + socklen_t tl[2] = { sizeof lo4, sizeof lo6 }; + int cs; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + for (i=0; i<2; i++) { + if (family==tf[1-i]) continue; + int s = socket(tf[i], SOCK_CLOEXEC|SOCK_DGRAM, + IPPROTO_UDP); + if (s<0) continue; + int r = connect(s, ta[i], tl[i]); + close(s); + if (!r) continue; + if (family == tf[i]) return EAI_NONAME; + family = tf[1-i]; + } + pthread_setcancelstate(cs, 0); + } + nservs = __lookup_serv(ports, serv, proto, socktype, flags); if (nservs < 0) return nservs;