2009-12-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Store all addresses found by getifaddrs() and getaddrinfo().  In
	bind, try all addresses until success
	* src/SocketCore.cc
	* src/SocketCore.h
pull/1/head
Tatsuhiro Tsujikawa 2009-12-06 08:25:41 +00:00
parent 766ad3baf2
commit 45f681b9dc
3 changed files with 67 additions and 47 deletions

View File

@ -1,3 +1,10 @@
2009-12-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
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 <t-tujikawa@users.sourceforge.net>
Updated po templates.

View File

@ -87,9 +87,8 @@ SocketCore::PollMethod SocketCore::_pollMethod = SocketCore::POLL_METHOD_SELECT;
int SocketCore::_protocolFamily = AF_UNSPEC;
SharedHandle<struct sockaddr_storage> SocketCore::_bindAddr;
socklen_t SocketCore::_bindAddrLen = 0;
std::vector<std::pair<struct sockaddr_storage, socklen_t> >
SocketCore::_bindAddrs;
#ifdef ENABLE_SSL
SharedHandle<TLSContext> 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 {
for(std::vector<std::pair<struct sockaddr_storage, socklen_t> >::
const_iterator i = _bindAddrs.begin(); i != _bindAddrs.end(); ++i) {
sock_t fd = bindInternal
(_bindAddr->ss_family, _sockType, 0,
reinterpret_cast<const struct sockaddr*>(_bindAddr.get()), _bindAddrLen);
((*i).first.ss_family, _sockType, 0,
reinterpret_cast<const struct sockaddr*>
(&(*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<const struct sockaddr*>(_bindAddr.get()),
_bindAddrLen) == -1) {
if(!_bindAddrs.empty()) {
bool bindSuccess = false;
for(std::vector<std::pair<struct sockaddr_storage, socklen_t> >::
const_iterator i = _bindAddrs.begin(); i != _bindAddrs.end(); ++i) {
if(::bind(fd,reinterpret_cast<const struct sockaddr*>(&(*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<struct sockaddr_storage> bindAddr(new struct sockaddr_storage());
socklen_t bindAddrLen = 0;
memset(bindAddr.get(), 0, sizeof(struct sockaddr_storage));
bool found = false;
std::vector<std::pair<struct sockaddr_storage, socklen_t> > 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<struct addrinfo*> 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<const struct sockaddr*>(bindAddr.get()),
bindAddrLen);
(reinterpret_cast<const struct sockaddr*>(&bindAddr), bindAddrLen);
bindAddrs.push_back(std::make_pair(bindAddr, bindAddrLen));
} catch(RecoverableException& e) {
throw DL_ABORT_EX2
continue;
}
}
}
}
if(bindAddrs.empty()) {
throw DL_ABORT_EX
(StringFormat(MSG_INTERFACE_NOT_FOUND,
interface.c_str(), e.what()).str(), e);
}
found = true;
break;
}
}
}
if(found) {
interface.c_str(), "not available").str());
} else {
_bindAddrs = bindAddrs;
for(std::vector<std::pair<struct sockaddr_storage, socklen_t> >::
const_iterator i = _bindAddrs.begin(); i != _bindAddrs.end(); ++i) {
char host[NI_MAXHOST];
int s;
s = getnameinfo(reinterpret_cast<struct sockaddr*>(bindAddr.get()),
bindAddrLen,
s = getnameinfo(reinterpret_cast<const struct sockaddr*>(&(*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;
}
}
}

View File

@ -44,6 +44,7 @@
#include <string>
#include <cstdlib>
#include <utility>
#include <vector>
#ifdef HAVE_LIBSSL
// for SSL
@ -92,9 +93,7 @@ private:
static int _protocolFamily;
static SharedHandle<struct sockaddr_storage> _bindAddr;
static socklen_t _bindAddrLen;
static std::vector<std::pair<struct sockaddr_storage, socklen_t> > _bindAddrs;
bool blocking;
int secure;