2010-02-22 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Put the portion of code to get interface addresses in
	SocketCore::bindAddress() into newly added getInterfaceAddress().
	* src/SocketCore.cc
	* src/SocketCore.h
pull/1/head
Tatsuhiro Tsujikawa 2010-02-21 15:21:21 +00:00
parent 8f9af67b99
commit 6f0fff2a5f
3 changed files with 59 additions and 34 deletions

View File

@ -1,3 +1,10 @@
2010-02-22 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Put the portion of code to get interface addresses in
SocketCore::bindAddress() into newly added getInterfaceAddress().
* src/SocketCore.cc
* src/SocketCore.h
2010-02-22 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2010-02-22 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Rewritten util::parseInt() and parseUInt() Rewritten util::parseInt() and parseUInt()

View File

@ -1175,6 +1175,34 @@ void SocketCore::useSelect()
void SocketCore::bindAddress(const std::string& iface) void SocketCore::bindAddress(const std::string& iface)
{ {
std::vector<std::pair<struct sockaddr_storage, socklen_t> > bindAddrs; std::vector<std::pair<struct sockaddr_storage, socklen_t> > bindAddrs;
getInterfaceAddress(bindAddrs, iface, _protocolFamily);
if(bindAddrs.empty()) {
throw DL_ABORT_EX
(StringFormat(MSG_INTERFACE_NOT_FOUND,
iface.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<const struct sockaddr*>(&(*i).first),
(*i).second,
host, NI_MAXHOST, 0, NI_MAXSERV,
NI_NUMERICHOST);
if(s == 0) {
if(LogFactory::getInstance()->debug()) {
LogFactory::getInstance()->debug("Sockets will bind to %s", host);
}
}
}
}
}
void getInterfaceAddress
(std::vector<std::pair<struct sockaddr_storage, socklen_t> >& ifAddrs,
const std::string& iface, int family)
{
if(LogFactory::getInstance()->debug()) { if(LogFactory::getInstance()->debug()) {
LogFactory::getInstance()->debug("Finding interface %s", iface.c_str()); LogFactory::getInstance()->debug("Finding interface %s", iface.c_str());
} }
@ -1191,38 +1219,37 @@ void SocketCore::bindAddress(const std::string& iface)
if(!ifa->ifa_addr) { if(!ifa->ifa_addr) {
continue; continue;
} }
int family = ifa->ifa_addr->sa_family; int iffamily = ifa->ifa_addr->sa_family;
if(_protocolFamily == AF_UNSPEC) { if(family == AF_UNSPEC) {
if(family != AF_INET && family != AF_INET6) { if(iffamily != AF_INET && iffamily != AF_INET6) {
continue; continue;
} }
} else if(_protocolFamily == AF_INET) { } else if(family == AF_INET) {
if(family != AF_INET) { if(iffamily != AF_INET) {
continue; continue;
} }
} else if(_protocolFamily == AF_INET6) { } else if(family == AF_INET6) {
if(family != AF_INET6) { if(iffamily != AF_INET6) {
continue; continue;
} }
} else { } else {
continue; continue;
} }
if(std::string(ifa->ifa_name) == iface) { if(std::string(ifa->ifa_name) == iface) {
socklen_t bindAddrLen = socklen_t bindAddrLen = iffamily == AF_INET?sizeof(struct sockaddr_in):
family == AF_INET?sizeof(struct sockaddr_in):
sizeof(struct sockaddr_in6); sizeof(struct sockaddr_in6);
struct sockaddr_storage bindAddr; struct sockaddr_storage bindAddr;
memset(&bindAddr, 0, sizeof(bindAddr)); memset(&bindAddr, 0, sizeof(bindAddr));
memcpy(&bindAddr, ifa->ifa_addr, bindAddrLen); memcpy(&bindAddr, ifa->ifa_addr, bindAddrLen);
bindAddrs.push_back(std::make_pair(bindAddr, bindAddrLen)); ifAddrs.push_back(std::make_pair(bindAddr, bindAddrLen));
} }
} }
} }
#endif // HAVE_GETIFADDRS #endif // HAVE_GETIFADDRS
if(bindAddrs.empty()) { if(ifAddrs.empty()) {
struct addrinfo* res; struct addrinfo* res;
int s; int s;
s = callGetaddrinfo(&res, iface.c_str(), 0, _protocolFamily, s = callGetaddrinfo(&res, iface.c_str(), 0, family,
SOCK_STREAM, 0, 0); SOCK_STREAM, 0, 0);
if(s) { if(s) {
throw DL_ABORT_EX throw DL_ABORT_EX
@ -1242,34 +1269,13 @@ void SocketCore::bindAddress(const std::string& iface)
SocketCore socket; SocketCore socket;
socket.bind socket.bind
(reinterpret_cast<const struct sockaddr*>(&bindAddr), bindAddrLen); (reinterpret_cast<const struct sockaddr*>(&bindAddr), bindAddrLen);
bindAddrs.push_back(std::make_pair(bindAddr, bindAddrLen)); ifAddrs.push_back(std::make_pair(bindAddr, bindAddrLen));
} catch(RecoverableException& e) { } catch(RecoverableException& e) {
continue; continue;
} }
} }
} }
} }
if(bindAddrs.empty()) {
throw DL_ABORT_EX
(StringFormat(MSG_INTERFACE_NOT_FOUND,
iface.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<const struct sockaddr*>(&(*i).first),
(*i).second,
host, NI_MAXHOST, 0, NI_MAXSERV,
NI_NUMERICHOST);
if(s == 0) {
if(LogFactory::getInstance()->debug()) {
LogFactory::getInstance()->debug("Sockets will bind to %s", host);
}
}
}
}
} }
namespace { namespace {

View File

@ -368,6 +368,10 @@ public:
// We cannot use interface as an argument because it is a reserved // We cannot use interface as an argument because it is a reserved
// keyword in MSVC. // keyword in MSVC.
static void bindAddress(const std::string& iface); static void bindAddress(const std::string& iface);
friend void getInterfaceAddress
(std::vector<std::pair<struct sockaddr_storage, socklen_t> >& ifAddrs,
const std::string& iface, int family);
}; };
// Set default ai_flags. hints.ai_flags is initialized with this // Set default ai_flags. hints.ai_flags is initialized with this
@ -382,6 +386,14 @@ int callGetaddrinfo
(struct addrinfo** resPtr, const char* host, const char* service, int family, (struct addrinfo** resPtr, const char* host, const char* service, int family,
int sockType, int flags, int protocol); int sockType, int flags, int protocol);
// Collects IP addresses of given inteface iface and stores in
// ifAddres. iface may be specified as a hostname, IP address or
// interface name like eth0. You can limit the family of IP addresses
// to collect using family argument.
void getInterfaceAddress
(std::vector<std::pair<struct sockaddr_storage, socklen_t> >& ifAddrs,
const std::string& iface, int family = AF_UNSPEC);
} // namespace aria2 } // namespace aria2
#endif // _D_SOCKET_CORE_H_ #endif // _D_SOCKET_CORE_H_