Check non-loopback (and non-linklocak for IPv6) address is configured

Issue A record query only when non-loopback IPv4 address is
configured.  Likewise, issue AAA record query only when non-loopback
and non-linklocak IPv6 address is configured.
pull/60/head
Tatsuhiro Tsujikawa 2013-03-31 00:57:33 +09:00
parent 56fac58b4d
commit f4a0987544
5 changed files with 108 additions and 7 deletions

View File

@ -107,7 +107,11 @@ AbstractCommand::AbstractCommand
requestGroup_->increaseStreamCommand();
requestGroup_->increaseNumCommand();
#ifdef ENABLE_ASYNC_DNS
if(e_->getOption()->getAsBool(PREF_DISABLE_IPV6)) {
if(!net::getIPv4AddrConfigured()) {
asyncNameResolverMan_->setIPv4(false);
}
if(!net::getIPv6AddrConfigured() ||
e_->getOption()->getAsBool(PREF_DISABLE_IPV6)) {
asyncNameResolverMan_->setIPv6(false);
}
#endif // ENABLE_ASYNC_DNS

View File

@ -69,14 +69,16 @@ void AsyncNameResolverMan::startAsync(const std::string& hostname,
Command* command)
{
numResolver_ = 0;
if(ipv4_) {
startAsyncFamily(hostname, AF_INET, e, command);
++numResolver_;
}
// Set IPv6 resolver first, so that we can push IPv6 address in
// front of IPv6 address in getResolvedAddress().
if(ipv6_) {
startAsyncFamily(hostname, AF_INET6, e, command);
++numResolver_;
}
if(ipv4_) {
startAsyncFamily(hostname, AF_INET, e, command);
++numResolver_;
}
A2_LOG_INFO(fmt(MSG_RESOLVING_HOSTNAME, command->getCuid(),
hostname.c_str()));
}
@ -150,11 +152,13 @@ void AsyncNameResolverMan::disableNameResolverCheck(size_t index,
int AsyncNameResolverMan::getStatus() const
{
size_t success = 0;
size_t error = 0;
for(size_t i = 0; i < numResolver_; ++i) {
switch(asyncNameResolver_[i]->getStatus()) {
case AsyncNameResolver::STATUS_SUCCESS:
return 1;
++success;
break;
case AsyncNameResolver::STATUS_ERROR:
++error;
break;
@ -162,7 +166,13 @@ int AsyncNameResolverMan::getStatus() const
break;
}
}
return error == numResolver_ ? -1 : 0;
if(success == numResolver_) {
return 1;
} else if(error == numResolver_) {
return -1;
} else {
return 0;
}
}
const std::string& AsyncNameResolverMan::getLastError() const

View File

@ -1546,6 +1546,86 @@ bool verifyHostname(const std::string& hostname,
return false;
}
namespace {
bool ipv4AddrConfigured = true;
bool ipv6AddrConfigured = true;
} // namespace
void checkAddrconfig()
{
// TODO Use GetAdaptersAddresses() for Mingw
#ifdef HAVE_GETIFADDRS
A2_LOG_INFO("Checking configured addresses");
ipv4AddrConfigured = false;
ipv6AddrConfigured = false;
ifaddrs* ifaddr = 0;
int rv;
rv = getifaddrs(&ifaddr);
if(rv == -1) {
int errNum = SOCKET_ERRNO;
A2_LOG_INFO(fmt("getifaddrs failed. Cause: %s", errorMsg(errNum).c_str()));
return;
}
auto_delete<ifaddrs*> ifaddrDeleter(ifaddr, freeifaddrs);
char host[NI_MAXHOST];
sockaddr_union ad;
for(ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if(!ifa->ifa_addr) {
continue;
}
bool found = false;
size_t addrlen = 0;
switch(ifa->ifa_addr->sa_family) {
case AF_INET: {
addrlen = sizeof(sockaddr_in);
memcpy(&ad.storage, ifa->ifa_addr, addrlen);
if(ad.in.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
ipv4AddrConfigured = true;
found = true;
}
break;
}
case AF_INET6: {
addrlen = sizeof(sockaddr_in6);
memcpy(&ad.storage, ifa->ifa_addr, addrlen);
if(!IN6_IS_ADDR_LOOPBACK(&ad.in6.sin6_addr) &&
!IN6_IS_ADDR_LINKLOCAL(&ad.in6.sin6_addr)) {
ipv6AddrConfigured = true;
found = true;
}
break;
}
default:
continue;
}
rv = getnameinfo(ifa->ifa_addr, addrlen, host, NI_MAXHOST, 0, 0,
NI_NUMERICHOST);
if(rv == 0) {
if(found) {
A2_LOG_INFO(fmt("Found configured address: %s", host));
} else {
A2_LOG_INFO(fmt("Not considered: %s", host));
}
}
}
A2_LOG_INFO(fmt("IPv4 configured=%d, IPv6 configured=%d",
ipv4AddrConfigured, ipv6AddrConfigured));
#else // !HAVE_GETIFADDRS
A2_LOG_INFO("getifaddrs is not available. Assume IPv4 and IPv6 addresses"
" are configured.");
#endif // !HAVE_GETIFADDRS
}
bool getIPv4AddrConfigured()
{
return ipv4AddrConfigured;
}
bool getIPv6AddrConfigured()
{
return ipv6AddrConfigured;
}
} // namespace net
} // namespace aria2

View File

@ -401,6 +401,12 @@ bool verifyHostname(const std::string& hostname,
const std::vector<std::string>& dnsNames,
const std::vector<std::string>& ipAddrs,
const std::string& commonName);
// Checks public IP address are configured for each family: IPv4 and
// IPv6. The result can be obtained using getIpv4AddrConfigured() and
// getIpv6AddrConfigured() respectively.
void checkAddrconfig();
bool getIPv4AddrConfigured();
bool getIPv6AddrConfigured();
} // namespace net

View File

@ -208,6 +208,7 @@ error_code::Value main(int argc, char* argv[])
// when none of network interface has IPv4 address.
setDefaultAIFlags(0);
}
net::checkAddrconfig();
// Bind interface
if(!op->get(PREF_INTERFACE).empty()) {
std::string iface = op->get(PREF_INTERFACE);