Use link local address only if necessary

This should solve APIPA address being always selected as preferred local
address on Windows which was causing problems connecting to machines on
the same local network.
Now the link local address is used as fallback only if there is non link
local private address available.
This commit is contained in:
Gioacchino Mazzurco 2018-02-19 23:23:15 +01:00
parent afc43d0ff7
commit 0c99975800
No known key found for this signature in database
GPG Key ID: A1FBCA3872E87051
4 changed files with 80 additions and 33 deletions

View File

@ -3,7 +3,8 @@
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2007-2011 by Robert Fernie.
* Copyright (C) 2007-2011 Robert Fernie
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -37,8 +38,7 @@
#include "util/extaddrfinder.h"
#include "util/dnsresolver.h"
//#include "util/rsprint.h"
//#include "util/rsdebug.h"
struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"};
#define p3netmgrzone &p3netmgrzoneInfo
@ -165,11 +165,6 @@ void p3NetMgrIMPL::setManagers(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr)
mLinkMgr = linkMgr;
}
//void p3NetMgrIMPL::setDhtMgr(p3DhtMgr *dhtMgr)
//{
// mDhtMgr = dhtMgr;
//}
#ifdef RS_USE_DHT_STUNNER
void p3NetMgrIMPL::setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun)
{
@ -1020,19 +1015,39 @@ bool p3NetMgrIMPL::checkNetAddress()
}
else
{
// TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just one local address is a flawed assumption, this should be redesigned soon.
/* TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just one local
* address is a flawed assumption, this should be redesigned as soon as
* possible. It will require complete reenginering of the network layer
* code.
*/
std::list<sockaddr_storage> addrs;
std::list<sockaddr_storage>::iterator it;
if (getLocalAddresses(addrs))
for(it = addrs.begin(); (it != addrs.end() && !validAddr); ++it)
if(sockaddr_storage_isValidNet(*it) && !sockaddr_storage_isLoopbackNet(*it))
{
for (auto&& addr : addrs)
{
if( sockaddr_storage_isValidNet(addr) &&
!sockaddr_storage_isLoopbackNet(addr) &&
!sockaddr_storage_isLinkLocalNet(addr))
{
prefAddr = *it;
prefAddr = addr;
validAddr = true;
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
std::cout << "p3NetMgrIMPL::checkNetAddress() prefAddr: " << sockaddr_storage_iptostring(prefAddr) << std::endl;
#endif
break;
}
}
// If no satisfactory local address has been found yet relax and
// accept also link local addresses
if(!validAddr) for (auto&& addr : addrs)
{
if( sockaddr_storage_isValidNet(addr) &&
!sockaddr_storage_isLoopbackNet(addr) )
{
prefAddr = addr;
validAddr = true;
break;
}
}
}
}

View File

@ -4,6 +4,7 @@
* Universal Networking Header for RetroShare.
*
* Copyright 2007-2008 by Robert Fernie.
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -147,25 +148,25 @@ bool isLoopbackNet(const struct in_addr *addr)
return (taddr == (127 << 24 | 1));
}
bool isPrivateNet(const struct in_addr *addr)
bool isPrivateNet(const struct in_addr *addr)
{
in_addr_t taddr = ntohl(addr->s_addr);
// 10.0.0.0/8
// 172.16.0.0/12
// 192.168.0.0/16
// 169.254.0.0/16
if ((taddr>>24 == 10) ||
(taddr>>20 == (172<<4 | 16>>4)) ||
(taddr>>16 == (192<<8 | 168)) ||
(taddr>>16 == (169<<8 | 254)))
{
if ( (taddr>>24 == 10) || // 10.0.0.0/8
(taddr>>20 == (172<<4 | 16>>4)) || // 172.16.0.0/12
(taddr>>16 == (192<<8 | 168)) || // 192.168.0.0/16
(taddr>>16 == (169<<8 | 254)) ) // 169.254.0.0/16
return true;
}
else
{
return false;
}
return false;
}
bool isLinkLocalNet(const struct in_addr *addr)
{
in_addr_t taddr = ntohl(addr->s_addr);
if ( taddr>>16 == (169<<8 | 254) ) return true; // 169.254.0.0/16
return false;
}
bool isExternalNet(const struct in_addr *addr)

View File

@ -4,6 +4,7 @@
* Universal Networking Header for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -72,6 +73,7 @@ void sockaddr_clear(struct sockaddr_in *addr);
bool isValidNet(const struct in_addr *addr);
bool isLoopbackNet(const struct in_addr *addr);
bool isPrivateNet(const struct in_addr *addr);
bool isLinkLocalNet(const struct in_addr *addr);
bool isExternalNet(const struct in_addr *addr);
// uses a re-entrant version of gethostbyname
@ -128,6 +130,7 @@ bool sockaddr_storage_isnull(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_isPrivateNet(const struct sockaddr_storage &addr);
bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr);
bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr);
bool rs_inet_ntop(const sockaddr_storage &addr, std::string &dst);

View File

@ -4,6 +4,7 @@
* sockaddr_storage functions for RetroShare.
*
* Copyright 2013-2013 by Robert Fernie.
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -389,7 +390,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputSt
std::stringstream output;
output << "sockaddr_storage_dump(addr) ";
switch (addr.ss_family){
switch (addr.ss_family)
{
case AF_INET:
{
const sockaddr_in * in = (const sockaddr_in *) & addr;
@ -421,7 +423,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputSt
for( uint32_t i = 0; i < sizeof(addr); ++i )
output << std::setw(2) << std::setfill('0') << std::hex << +buf[i];
// The unary +buf[i] operation forces a no-op type conversion to an int with the correct sign
}}
}
}
if(outputString)
{
@ -578,6 +581,31 @@ bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr)
return false;
}
bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr)
{
#ifdef SS_DEBUG
std::cerr << __PRETTY_FUNCTION__ << std::endl;
#endif
switch(addr.ss_family)
{
case AF_INET:
return isLinkLocalNet(&(to_const_ipv4_ptr(addr)->sin_addr));
case AF_INET6:
std::cerr << __PRETTY_FUNCTION__ << " for AF_INET6 not implemented"
<< std::endl;
break;
default:
#ifdef SS_DEBUG
std::cerr << __PRETTY_FUNCTION__ <<" INVALID Family:" << std::endl;
sockaddr_storage_dump(addr);
#endif
break;
}
return false;
}
bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr)
{