From 45f681b9dc6cee8c3ca5ffc4c609ea144896a55c Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 6 Dec 2009 08:25:41 +0000 Subject: [PATCH] 2009-12-06 Tatsuhiro Tsujikawa Store all addresses found by getifaddrs() and getaddrinfo(). In bind, try all addresses until success * src/SocketCore.cc * src/SocketCore.h --- ChangeLog | 7 ++++ src/SocketCore.cc | 102 ++++++++++++++++++++++++++-------------------- src/SocketCore.h | 5 +-- 3 files changed, 67 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 40daa5ee..e25c7b3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-12-06 Tatsuhiro Tsujikawa + + Store all addresses found by getifaddrs() and getaddrinfo(). In + bind, try all addresses until success + * src/SocketCore.cc + * src/SocketCore.h + 2009-12-05 Tatsuhiro Tsujikawa Updated po templates. diff --git a/src/SocketCore.cc b/src/SocketCore.cc index 0d85f72d..8dcece60 100644 --- a/src/SocketCore.cc +++ b/src/SocketCore.cc @@ -87,9 +87,8 @@ SocketCore::PollMethod SocketCore::_pollMethod = SocketCore::POLL_METHOD_SELECT; int SocketCore::_protocolFamily = AF_UNSPEC; -SharedHandle SocketCore::_bindAddr; - -socklen_t SocketCore::_bindAddrLen = 0; +std::vector > +SocketCore::_bindAddrs; #ifdef ENABLE_SSL SharedHandle SocketCore::_tlsContext; @@ -192,7 +191,7 @@ void SocketCore::bind(uint16_t port, int flags) { closeConnection(); - if(flags == 0 || _bindAddr.isNull()) { + if(flags == 0 || _bindAddrs.empty()) { struct addrinfo hints; struct addrinfo* res; memset(&hints, 0, sizeof(hints)); @@ -217,11 +216,16 @@ void SocketCore::bind(uint16_t port, int flags) } freeaddrinfo(res); } else { - sock_t fd = bindInternal - (_bindAddr->ss_family, _sockType, 0, - reinterpret_cast(_bindAddr.get()), _bindAddrLen); - if(fd != (sock_t)-1) { - sockfd = fd; + for(std::vector >:: + const_iterator i = _bindAddrs.begin(); i != _bindAddrs.end(); ++i) { + sock_t fd = bindInternal + ((*i).first.ss_family, _sockType, 0, + reinterpret_cast + (&(*i).first), (*i).second); + if(fd != (sock_t)-1) { + sockfd = fd; + break; + } } } if(sockfd == (sock_t) -1) { @@ -310,11 +314,19 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port) CLOSE(fd); continue; } - - if(!_bindAddr.isNull()) { - if(::bind(fd, reinterpret_cast(_bindAddr.get()), - _bindAddrLen) == -1) { - LogFactory::getInstance()->debug(EX_SOCKET_BIND, strerror(errno)); + if(!_bindAddrs.empty()) { + bool bindSuccess = false; + for(std::vector >:: + const_iterator i = _bindAddrs.begin(); i != _bindAddrs.end(); ++i) { + if(::bind(fd,reinterpret_cast(&(*i).first), + (*i).second) == -1) { + LogFactory::getInstance()->debug(EX_SOCKET_BIND, strerror(errno)); + } else { + bindSuccess = true; + break; + } + } + if(!bindSuccess) { CLOSE(fd); continue; } @@ -1127,10 +1139,7 @@ void SocketCore::useSelect() void SocketCore::bindAddress(const std::string& interface) { - SharedHandle bindAddr(new struct sockaddr_storage()); - socklen_t bindAddrLen = 0; - memset(bindAddr.get(), 0, sizeof(struct sockaddr_storage)); - bool found = false; + std::vector > bindAddrs; LogFactory::getInstance()->debug("Finding interface %s", interface.c_str()); #ifdef HAVE_GETIFADDRS // First find interface in interface addresses @@ -1162,22 +1171,23 @@ void SocketCore::bindAddress(const std::string& interface) continue; } if(std::string(ifa->ifa_name) == interface) { - bindAddrLen = + socklen_t bindAddrLen = family == AF_INET?sizeof(struct sockaddr_in): sizeof(struct sockaddr_in6); - memcpy(bindAddr.get(), ifa->ifa_addr, bindAddrLen); - found = true; - break; + struct sockaddr_storage bindAddr; + memset(&bindAddr, 0, sizeof(bindAddr)); + memcpy(&bindAddr, ifa->ifa_addr, bindAddrLen); + bindAddrs.push_back(std::make_pair(bindAddr, bindAddrLen)); } } } #endif // HAVE_GETIFADDRS - if(!found) { + if(bindAddrs.empty()) { struct addrinfo hints; struct addrinfo* res = 0; memset(&hints, 0, sizeof(hints)); hints.ai_family = _protocolFamily; - hints.ai_socktype = 0; + hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; hints.ai_protocol = 0; int s; @@ -1190,37 +1200,41 @@ void SocketCore::bindAddress(const std::string& interface) auto_delete resDeleter(res, freeaddrinfo); struct addrinfo* rp; for(rp = res; rp; rp = rp->ai_next) { - bindAddrLen = rp->ai_addrlen; - memcpy(bindAddr.get(), rp->ai_addr, rp->ai_addrlen); + socklen_t bindAddrLen = rp->ai_addrlen; + struct sockaddr_storage bindAddr; + memset(&bindAddr, 0, sizeof(bindAddr)); + memcpy(&bindAddr, rp->ai_addr, rp->ai_addrlen); // Try to bind socket with this address. If it fails, the // address is not for this machine. try { SocketCore socket; socket.bind - (reinterpret_cast(bindAddr.get()), - bindAddrLen); + (reinterpret_cast(&bindAddr), bindAddrLen); + bindAddrs.push_back(std::make_pair(bindAddr, bindAddrLen)); } catch(RecoverableException& e) { - throw DL_ABORT_EX2 - (StringFormat(MSG_INTERFACE_NOT_FOUND, - interface.c_str(), e.what()).str(), e); + continue; } - found = true; - break; } } } - if(found) { - char host[NI_MAXHOST]; - int s; - s = getnameinfo(reinterpret_cast(bindAddr.get()), - bindAddrLen, - host, NI_MAXHOST, 0, NI_MAXSERV, - NI_NUMERICHOST); - if(s == 0) { - LogFactory::getInstance()->debug("Sockets will bind to %s", host); + if(bindAddrs.empty()) { + throw DL_ABORT_EX + (StringFormat(MSG_INTERFACE_NOT_FOUND, + interface.c_str(), "not available").str()); + } else { + _bindAddrs = bindAddrs; + for(std::vector >:: + const_iterator i = _bindAddrs.begin(); i != _bindAddrs.end(); ++i) { + char host[NI_MAXHOST]; + int s; + s = getnameinfo(reinterpret_cast(&(*i).first), + (*i).second, + host, NI_MAXHOST, 0, NI_MAXSERV, + NI_NUMERICHOST); + if(s == 0) { + LogFactory::getInstance()->debug("Sockets will bind to %s", host); + } } - _bindAddr = bindAddr; - _bindAddrLen = bindAddrLen; } } diff --git a/src/SocketCore.h b/src/SocketCore.h index 9d06fbeb..866a45e0 100644 --- a/src/SocketCore.h +++ b/src/SocketCore.h @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef HAVE_LIBSSL // for SSL @@ -92,9 +93,7 @@ private: static int _protocolFamily; - static SharedHandle _bindAddr; - - static socklen_t _bindAddrLen; + static std::vector > _bindAddrs; bool blocking; int secure;