improved IPv6 handling (Patch 19a39b42c4bb6256363b1624520c200835a9b93e from G10H4ck)

git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.6-IPv6@8198 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2015-05-01 13:14:25 +00:00
parent 09d601aac0
commit d40a9002fa
7 changed files with 124 additions and 87 deletions

View file

@ -219,29 +219,23 @@ int p3BitDht::addBadPeer(const struct sockaddr_storage &addr, uint32_t /*reason*
int p3BitDht::addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &addr, uint32_t flags) int p3BitDht::addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &addr, uint32_t flags)
{ {
struct sockaddr_in addrv4; struct sockaddr_in addrv4;
sockaddr_storage tmpAddr = addr;
if (addr.ss_family != AF_INET) if (!sockaddr_storage_ipv6_to_ipv4(tmpAddr))
{ {
std::cerr << "p3BitDht::addKnownPeer() Warning! Non IPv4 Address - Cannot handle IPV6 Yet. addr.ss_family=" << addr.ss_family; #ifdef DEBUG_BITDHT
std::cerr << std::endl; std::cerr << "p3BitDht::addKnownPeer() Warning! Cannot add non IPv4 Address" << std::endl;
sockaddr_clear(&addrv4); sockaddr_storage_dump(addr);
#endif
return 0; // TODO:IPV6
if (flags & NETASSIST_KNOWN_PEER_ONLINE)
{
std::cerr << "p3BitDht::addKnownPeer() Non IPv4 Address & ONLINE. Abort()ing.";
std::cerr << std::endl;
return 0; // TODO:IPV6
}
} }
else else
{ {
// convert. // convert.
struct sockaddr_in *ap = (struct sockaddr_in *) &addr; struct sockaddr_in *ap = (struct sockaddr_in *) &tmpAddr;
sockaddr_clear(&addrv4);
addrv4.sin_family = ap->sin_family; addrv4.sin_family = ap->sin_family;
addrv4.sin_addr = ap->sin_addr; addrv4.sin_addr = ap->sin_addr;
addrv4.sin_port = ap->sin_port; addrv4.sin_port = ap->sin_port;

View file

@ -975,31 +975,34 @@ bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, c
std::cerr << ")" << std::endl; std::cerr << ")" << std::endl;
#endif #endif
std::list<struct sockaddr_storage> lAddrs;
getLocalAddresses(lAddrs); // Better to have this outside mutex
{ {
/****** STACK LOCK MUTEX *******/ /****** STACK LOCK MUTEX *******/
RsStackMutex stack(mPeerMtx); (void)stack; RS_STACK_MUTEX(mPeerMtx);
mOwnState.localaddr = localAddr;
// update ip address list // update ip address list
uint16_t port = 0;
if(!sockaddr_storage_isnull(localAddr))
{
lAddrs.push_front(localAddr);
port = sockaddr_storage_port(localAddr);
}
if (!lAddrs.empty())
mOwnState.localaddr = lAddrs.front();
std::list<struct sockaddr_storage>::iterator it; std::list<struct sockaddr_storage>::iterator it;
std::list<struct sockaddr_storage> lAddrs;
getLocalAddresses(lAddrs);
lAddrs.push_front(localAddr);
for ( it = lAddrs.begin(); it != lAddrs.end(); ++it) for ( it = lAddrs.begin(); it != lAddrs.end(); ++it)
{ {
pqiIpAddress ipAddressTimed; pqiIpAddress ipAddressTimed;
ipAddressTimed.mAddr = *it; ipAddressTimed.mAddr = *it;
sockaddr_storage_setport(ipAddressTimed.mAddr, sockaddr_storage_port(localAddr)); sockaddr_storage_setport(ipAddressTimed.mAddr, port);
ipAddressTimed.mSeenTime = time(NULL); ipAddressTimed.mSeenTime = time(NULL);
ipAddressTimed.mSrc = 0 ; ipAddressTimed.mSrc = 0;
mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed); mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed);
} }
}
{
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
//update ip address list //update ip address list
pqiIpAddress ipAddressTimed; pqiIpAddress ipAddressTimed;
@ -1015,7 +1018,7 @@ bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, c
* This should keep people happy, and allow for misconfiguration! * This should keep people happy, and allow for misconfiguration!
*/ */
if (mOwnState.netMode & RS_NET_MODE_TRY_EXT) if (mOwnState.netMode & RS_NET_MODE_TRY_EXT)
{ {
/**** THIS CASE SHOULD NOT BE TRIGGERED ****/ /**** THIS CASE SHOULD NOT BE TRIGGERED ****/
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port "; std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port ";
@ -1025,10 +1028,10 @@ bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, c
std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr); std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr);
std::cerr << std::endl; std::cerr << std::endl;
} }
else if (mOwnState.netMode & RS_NET_MODE_EXT) else if (mOwnState.netMode & RS_NET_MODE_EXT)
{ {
sockaddr_storage_copyip(mOwnState.serveraddr,extAddr); sockaddr_storage_copyip(mOwnState.serveraddr, extAddr);
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port "; std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port ";
std::cerr << " as MANUAL FORWARD Mode"; std::cerr << " as MANUAL FORWARD Mode";
std::cerr << std::endl; std::cerr << std::endl;
@ -1037,10 +1040,9 @@ bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, c
std::cerr << std::endl; std::cerr << std::endl;
} }
else else
{
mOwnState.serveraddr = extAddr; mOwnState.serveraddr = extAddr;
}
} } // end RS_STACK_MUTEX(mPeerMtx);
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
mLinkMgr->setLocalAddress(localAddr); mLinkMgr->setLocalAddress(localAddr);

View file

@ -371,21 +371,25 @@ in_addr_t inet_network(const char *inet_name)
bool getLocalAddresses(std::list<struct sockaddr_storage> & addrs) bool getLocalAddresses(std::list<struct sockaddr_storage> & addrs)
{ {
struct ifaddrs *ifsaddrs, *ifa; struct ifaddrs *ifsaddrs, *ifa;
if(getifaddrs(&ifsaddrs) != 0) exit(1); if(getifaddrs(&ifsaddrs) != 0)
{
freeifaddrs(ifsaddrs);
return false;
}
addrs.clear(); addrs.clear();
for ( ifa = ifsaddrs; ifa; ifa = ifa->ifa_next ) for ( ifa = ifsaddrs; ifa; ifa = ifa->ifa_next )
if ( (ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_LOOPBACK) ) if ( (ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_LOOPBACK) )
{ {
sockaddr_storage * tmp = new sockaddr_storage; const sockaddr_storage & ifaaddr = * (const struct sockaddr_storage *) ifa->ifa_addr;
if (sockaddr_storage_copyip(* tmp, * (const struct sockaddr_storage *) ifa->ifa_addr)) if (sockaddr_storage_isLinkLocal(ifaaddr)) continue;
addrs.push_back(*tmp); sockaddr_storage tmp;
else delete tmp; if (sockaddr_storage_copyip(tmp, ifaaddr)) addrs.push_back(tmp);
} }
freeifaddrs(ifsaddrs);
return (!addrs.empty()); freeifaddrs(ifsaddrs);
return !addrs.empty();
} }

View file

@ -604,12 +604,12 @@ int pqissl::Delay_Connection()
} }
rslog(RSL_WARNING, pqisslzone, rslog(RSL_WARNING, pqisslzone,
"pqissl::Initiate_Connection() Already Attempt in Progress!"); "pqissl::Delay_Connection() Already Attempt in Progress!");
return -1; return -1;
} }
int pqissl::Initiate_Connection() int pqissl::Initiate_Connection()
{ {
int err; int err;
struct sockaddr_storage addr = remote_addr; struct sockaddr_storage addr = remote_addr;
@ -750,6 +750,7 @@ int pqissl::Initiate_Connection()
{ {
std::string out; std::string out;
rs_sprintf(out, "pqissl::Initiate_Connection() connect returns:%d -> errno: %d error: %s\n", err, errno, socket_errorType(errno).c_str()); rs_sprintf(out, "pqissl::Initiate_Connection() connect returns:%d -> errno: %d error: %s\n", err, errno, socket_errorType(errno).c_str());
sockaddr_storage_dump(addr, &out);
if (errno == EINPROGRESS) if (errno == EINPROGRESS)
{ {

View file

@ -894,7 +894,9 @@ bool p3Peers::setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht)
bool p3Peers::getProxyServer(std::string &addr, uint16_t &port, uint32_t &status) bool p3Peers::getProxyServer(std::string &addr, uint16_t &port, uint32_t &status)
{ {
std::cerr << "p3Peers::getProxyServer()" << std::endl; #ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::getProxyServer()" << std::endl;
#endif
struct sockaddr_storage proxy_addr; struct sockaddr_storage proxy_addr;
mPeerMgr->getProxyServerAddress(proxy_addr); mPeerMgr->getProxyServerAddress(proxy_addr);

View file

@ -110,7 +110,7 @@ std::string sockaddr_storage_tostring(const struct sockaddr_storage &addr);
std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr); std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr);
std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr); std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr);
std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr); std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr);
void sockaddr_storage_dump(const sockaddr_storage & addr); void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString = NULL);
// output // output
//void sockaddr_storage_output(const struct sockaddr_storage &addr, std::ostream &out); //void sockaddr_storage_output(const struct sockaddr_storage &addr, std::ostream &out);
@ -118,6 +118,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr);
// net checks. // net checks.
bool sockaddr_storage_isnull(const struct sockaddr_storage &addr); bool sockaddr_storage_isnull(const struct sockaddr_storage &addr);
bool sockaddr_storage_isLinkLocal(const struct sockaddr_storage &addr);
bool sockaddr_storage_isIPv4Mapped(const struct sockaddr_storage &addr);
bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr); bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr);
bool sockaddr_storage_isLoopbackNet(const struct sockaddr_storage &addr); bool sockaddr_storage_isLoopbackNet(const struct sockaddr_storage &addr);
bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr); bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr);

View file

@ -27,6 +27,7 @@
#include "util/rsnet.h" #include "util/rsnet.h"
#include "util/rsstring.h" #include "util/rsstring.h"
#include "util/stacktrace.h"
#include "pqi/pqinetwork.h" #include "pqi/pqinetwork.h"
/***************************** Internal Helper Fns ******************************/ /***************************** Internal Helper Fns ******************************/
@ -180,8 +181,7 @@ bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr
uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr) uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr)
{ {
#ifdef SS_DEBUG #ifdef SS_DEBUG
std::cerr << "sockaddr_storage_port()"; std::cerr << "sockaddr_storage_port()" << std::endl;
std::cerr << std::endl;
#endif #endif
switch(addr.ss_family) switch(addr.ss_family)
{ {
@ -192,8 +192,9 @@ uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr)
return sockaddr_storage_ipv6_port(addr); return sockaddr_storage_ipv6_port(addr);
break; break;
default: default:
std::cerr << "sockaddr_storage_port() invalid addr.ss_family" << std::endl; std::cerr << "sockaddr_storage_port() invalid addr.ss_family ";
sockaddr_storage_dump(addr); sockaddr_storage_dump(addr);
//print_stacktrace();
break; break;
} }
return 0; return 0;
@ -310,27 +311,20 @@ bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr)
if ( addr.ss_family == AF_INET ) return true; if ( addr.ss_family == AF_INET ) return true;
if ( addr.ss_family == AF_INET6 ) if(sockaddr_storage_isIPv4Mapped(addr))
{ {
sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr; sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr;
bool ipv4m = addr_ipv6.sin6_addr.s6_addr16[5] == (u_int16_t) 0xffff; u_int32_t ip = addr_ipv6.sin6_addr.s6_addr32[3];
for ( int i = 0; ipv4m && i < 5 ; ++i ) u_int16_t port = addr_ipv6.sin6_port;
ipv4m &= addr_ipv6.sin6_addr.s6_addr16[i] == (u_int16_t) 0x0000;
if(ipv4m) sockaddr_in & addr_ipv4 = (sockaddr_in &) addr;
{
u_int32_t ip = addr_ipv6.sin6_addr.s6_addr32[3];
u_int16_t port = addr_ipv6.sin6_port;
sockaddr_in & addr_ipv4 = (sockaddr_in &) addr; sockaddr_storage_clear(addr);
addr_ipv4.sin_family = AF_INET;
addr_ipv4.sin_port = port;
addr_ipv4.sin_addr.s_addr = ip;
sockaddr_storage_clear(addr); return true;
addr_ipv4.sin_family = AF_INET;
addr_ipv4.sin_port = port;
addr_ipv4.sin_addr.s_addr = ip;
return true;
}
} }
return false; return false;
@ -478,26 +472,54 @@ std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr)
bool sockaddr_storage_isnull(const struct sockaddr_storage &addr) bool sockaddr_storage_isnull(const struct sockaddr_storage &addr)
{ {
#ifdef SS_DEBUG #ifdef SS_DEBUG
std::cerr << "sockaddr_storage_isnull()"; std::cerr << "sockaddr_storage_isnull()" << std::endl;
std::cerr << std::endl;
#endif #endif
if (addr.ss_family == 0)
return true;
switch(addr.ss_family) switch(addr.ss_family)
{ {
case AF_INET: case AF_INET:
return sockaddr_storage_ipv4_isnull(addr); return sockaddr_storage_ipv4_isnull(addr);
break;
case AF_INET6: case AF_INET6:
return sockaddr_storage_ipv6_isnull(addr); return sockaddr_storage_ipv6_isnull(addr);
break;
default: default:
return true; return true;
break;
} }
return true; }
bool sockaddr_storage_isLinkLocal(const struct sockaddr_storage &addr)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_isLinkLocal()" << std::endl;
#endif
switch(addr.ss_family)
{
case AF_INET:
return false; // TODO:IPv4
case AF_INET6:
{
const sockaddr_in6 * addr6 = (const sockaddr_in6 *) &addr;
u_int16_t mask = 0xc0ff; // Mask end prefix inverted because of IPv6 is big endian
return ((addr6->sin6_addr.s6_addr16[0] & mask ) == 0x80fe);
}
default:
return false;
}
}
bool sockaddr_storage_isIPv4Mapped(const struct sockaddr_storage &addr)
{
if (addr.ss_family == AF_INET6)
{
sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr;
bool ipv4m = addr_ipv6.sin6_addr.s6_addr16[5] == (u_int16_t) 0xffff;
for ( int i = 0; ipv4m && i < 5 ; ++i )
ipv4m &= addr_ipv6.sin6_addr.s6_addr16[i] == (u_int16_t) 0x0000;
return ipv4m;
}
return false;
} }
bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr) bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr)
@ -587,8 +609,7 @@ bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr)
return sockaddr_storage_ipv6_isExternalNet(addr); return sockaddr_storage_ipv6_isExternalNet(addr);
break; break;
default: default:
std::cerr << "sockaddr_storage_isExternalNet() INVALID Family - error"; std::cerr << "sockaddr_storage_isExternalNet() INVALID Family - error" << std::endl;
std::cerr << std::endl;
break; break;
} }
return false; return false;
@ -703,14 +724,14 @@ bool sockaddr_storage_ipv6_copyip(struct sockaddr_storage &dst, const struct soc
dst_ptr->sin6_family = AF_INET6; dst_ptr->sin6_family = AF_INET6;
memcpy(&(dst_ptr->sin6_addr), &(src_ptr->sin6_addr), sizeof(src_ptr->sin6_addr)); memcpy(&(dst_ptr->sin6_addr), &(src_ptr->sin6_addr), sizeof(src_ptr->sin6_addr));
dst_ptr->sin6_scope_id = src_ptr->sin6_scope_id;
return true; return true;
} }
uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr) uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr)
{ {
#ifdef SS_DEBUG #ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_port()"; std::cerr << "sockaddr_storage_ipv6_port()" << std::endl;
std::cerr << std::endl;
#endif #endif
const struct sockaddr_in6 *ipv6_ptr = to_const_ipv6_ptr(addr); const struct sockaddr_in6 *ipv6_ptr = to_const_ipv6_ptr(addr);
uint16_t port = ntohs(ipv6_ptr->sin6_port); uint16_t port = ntohs(ipv6_ptr->sin6_port);
@ -719,8 +740,9 @@ uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr)
bool sockaddr_storage_ipv6_setport(struct sockaddr_storage &addr, uint16_t port) bool sockaddr_storage_ipv6_setport(struct sockaddr_storage &addr, uint16_t port)
{ {
std::cerr << "sockaddr_storage_ipv6_setport()"; #ifdef SS_DEBUG
std::cerr << std::endl; std::cerr << "sockaddr_storage_ipv6_setport()" << std::endl;
#endif
struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr);
ipv6_ptr->sin6_port = htons(port); ipv6_ptr->sin6_port = htons(port);
@ -866,7 +888,7 @@ std::string sockaddr_storage_iptostring(const struct sockaddr_storage & addr)
return output; return output;
} }
void sockaddr_storage_dump(const sockaddr_storage & addr) void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString)
{ {
// This function must not rely on others sockaddr_storage_* // This function must not rely on others sockaddr_storage_*
@ -892,6 +914,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr)
output << "addr.ss_family = AF_INET6"; output << "addr.ss_family = AF_INET6";
output << " in6->sin6_addr = "; output << " in6->sin6_addr = ";
output << addrStr; output << addrStr;
output << " in6->sin6_scope_id = ";
output << in6->sin6_scope_id;
output << " in6->sin6_port = "; output << " in6->sin6_port = ";
output << in6->sin6_port; output << in6->sin6_port;
break; break;
@ -906,7 +930,15 @@ void sockaddr_storage_dump(const sockaddr_storage & addr)
output << addr.__ss_padding; output << addr.__ss_padding;
}} }}
std::cerr << output.str() << std::endl; if(outputString)
{
outputString->append(output.str() + "\n");
#ifdef SS_DEBUG
std::cerr << output.str() << std::endl;
#endif
}
else
std::cerr << output.str() << std::endl;
} }
/********************************* Net Checks ***********************************/ /********************************* Net Checks ***********************************/
@ -1013,9 +1045,9 @@ bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage & )
bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage & addr ) bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage & addr )
{ {
sockaddr_in6 & addr6 = (sockaddr_in6 &) addr; sockaddr_in6 & addr6 = (sockaddr_in6 &) addr;
bool isLp = (addr6.sin6_addr.s6_addr32[3] == 0x1); bool isLp = (addr6.sin6_addr.s6_addr32[3] == 0x10000000); // IPv6 is big endian
for (int i=0; isLp && i<3; ++i) for (int i=0; isLp && i<3; ++i)
isLp &= (addr6.sin6_addr.s6_addr32[i] == 0x0); isLp &= (addr6.sin6_addr.s6_addr32[i] == 0x00000000);
#ifdef SS_DEBUG #ifdef SS_DEBUG
sockaddr_storage_dump(addr); sockaddr_storage_dump(addr);
@ -1034,13 +1066,13 @@ bool sockaddr_storage_ipv6_isPrivateNet(const struct sockaddr_storage &)
return false; return false;
} }
bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &) bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage & addr)
{ {
#ifdef SS_DEBUG #ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_isExternalNet() TODO" << std::endl; std::cerr << "sockaddr_storage_ipv6_isExternalNet() TODO" << std::endl;
#endif #endif
return true; return !sockaddr_storage_isLinkLocal(addr);
} }