diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 2d593e42f..7dad79bb2 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -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 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,6 +25,7 @@ */ #include +#include #include "pqi/p3netmgr.h" @@ -37,8 +39,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 +166,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 +1016,41 @@ 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. - std::list addrs; - std::list::iterator it; + /* 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::vector addrs; if (getLocalAddresses(addrs)) - for(it = addrs.begin(); (it != addrs.end() && !validAddr); ++it) - if(sockaddr_storage_isValidNet(*it) && !sockaddr_storage_isLoopbackNet(*it)) + { + for (auto it = addrs.begin(); it!=addrs.end(); ++it) + { + sockaddr_storage& addr(*it); + 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 it = addrs.begin(); it!=addrs.end(); ++it) + { + sockaddr_storage& addr(*it); + if( sockaddr_storage_isValidNet(addr) && + !sockaddr_storage_isLoopbackNet(addr) ) + { + prefAddr = addr; + validAddr = true; + break; + } + } + } } diff --git a/libretroshare/src/pqi/pqiipset.h b/libretroshare/src/pqi/pqiipset.h index 29c8aaddd..6da862b08 100644 --- a/libretroshare/src/pqi/pqiipset.h +++ b/libretroshare/src/pqi/pqiipset.h @@ -29,7 +29,7 @@ #include "util/rsnet.h" #include "serialiser/rstlvaddrs.h" -#define MAX_ADDRESS_LIST_SIZE 4 +#define MAX_ADDRESS_LIST_SIZE 10 class pqiIpAddress { diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index f15692e06..c302123a4 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -3,7 +3,8 @@ * * 3P/PQI network interface for RetroShare. * - * Copyright 2004-2006 by Robert Fernie. + * Copyright (C) 2004-2006 Robert Fernie. + * Copyright (C) 2015-2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -284,7 +285,7 @@ int inet_aton(const char *name, struct in_addr *addr) # include #endif // WINDOWS_SYS -bool getLocalAddresses(std::list & addrs) +bool getLocalAddresses(std::vector& addrs) { addrs.clear(); diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h index 7cb7f93cf..21d8ee81c 100644 --- a/libretroshare/src/pqi/pqinetwork.h +++ b/libretroshare/src/pqi/pqinetwork.h @@ -3,7 +3,8 @@ * * 3P/PQI network interface for RetroShare. * - * Copyright 2004-2006 by Robert Fernie. + * Copyright (C) 2004-2006 Robert Fernie. + * Copyright (C) 2015-2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,10 +25,10 @@ */ - #ifndef MRK_PQI_NETWORKING_HEADER #define MRK_PQI_NETWORKING_HEADER +#include /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS @@ -95,7 +96,7 @@ void showSocketError(std::string &out); std::string socket_errorType(int err); -bool getLocalAddresses(std::list & addrs); +bool getLocalAddresses(std::vector & addrs); /* universal socket interface */ diff --git a/libretroshare/src/services/p3discovery2.cc b/libretroshare/src/services/p3discovery2.cc index 4728a0d77..286848a6f 100644 --- a/libretroshare/src/services/p3discovery2.cc +++ b/libretroshare/src/services/p3discovery2.cc @@ -3,7 +3,8 @@ * * Services for RetroShare. * - * Copyright 2004-2013 by Robert Fernie. + * Copyright (C) 2004-2013 Robert Fernie. + * Copyright (C) 2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,11 +26,15 @@ #include "services/p3discovery2.h" #include "pqi/p3peermgr.h" +#include "pqi/pqinetwork.h" // for getLocalAddresses #include "util/rsversioninfo.h" #include "retroshare/rsiface.h" #include "rsserver/p3face.h" +#include // for std::vector +#include // for std::random_shuffle + // Interface pointer. RsDisc *rsDisc = NULL; @@ -38,7 +43,9 @@ RsDisc *rsDisc = NULL; * #define P3DISC_DEBUG 1 ****/ -static bool populateContactInfo(const peerState &detail, RsDiscContactItem *pkt,bool include_ip_information) +static bool populateContactInfo( const peerState &detail, + RsDiscContactItem *pkt, + bool include_ip_information ) { pkt->clear(); @@ -341,10 +348,56 @@ void p3discovery2::sendOwnContactInfo(const SSLID &sslid) std::cerr << std::endl; #endif peerState detail; - if (mPeerMgr->getOwnNetStatus(detail)) + if (mPeerMgr->getOwnNetStatus(detail)) { + /* Workaround to spread multiple local ip addresses when presents. This + * is needed because RS wrongly assumes that there is just one active + * local ip address at time. */ + std::vector addrs; + if(!detail.hiddenNode && getLocalAddresses(addrs)) + { + /* To work around MAX_ADDRESS_LIST_SIZE addresses limitation, + * let's shuffle the list of + * local addresses in the hope that with enough time every local + * address is advertised to trusted nodes so they may try to + * connect to all of them including the most convenient if a local + * connection exists.*/ + std::random_shuffle(addrs.begin(), addrs.end()); + + for (auto it = addrs.begin(); it!=addrs.end(); ++it) + { + sockaddr_storage& addr(*it); + if( sockaddr_storage_isValidNet(addr) && + !sockaddr_storage_isLoopbackNet(addr) && + !sockaddr_storage_sameip(addr, detail.localaddr) ) + { + pqiIpAddress pqiIp; + sockaddr_storage_clear(pqiIp.mAddr); + pqiIp.mAddr.ss_family = addr.ss_family; + sockaddr_storage_copyip(pqiIp.mAddr, addr); + sockaddr_storage_setport( + pqiIp.mAddr, + sockaddr_storage_port(detail.localaddr) ); + pqiIp.mSeenTime = time(nullptr); + pqiIp.mSrc = 0; + detail.ipAddrs.updateLocalAddrs(pqiIp); + } + } + } + RsDiscContactItem *pkt = new RsDiscContactItem(); - populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid)); // we dont send our own IP to an hidden node. It will not use it anyway. + /* Cyril: we dont send our own IP to an hidden node. It will not use it + * anyway. */ + populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid)); + /* G10h4ck: sending IP information also to hidden nodes has proven very + * helpful in the usecase of non hidden nodes, that share a common + * hidden trusted node, to discover each other IP. + * Advanced/corner case non hidden node users that want to hide their + * IP to a specific hidden ~trusted~ node can do it through the + * permission matrix. Disabling this instead will make life more + * difficult for average user, that moreover whould have no way to + * revert an hardcoded policy. */ + //populateContactInfo(detail, pkt, true); pkt->version = RsUtil::retroshareVersion(); pkt->PeerId(sslid); @@ -433,10 +486,11 @@ void p3discovery2::recvOwnContactInfo(const SSLID &fromId, const RsDiscContactIt void p3discovery2::updatePeerAddresses(const RsDiscContactItem *item) { if (item->isHidden) - mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr, item->hiddenPort); + mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr, + item->hiddenPort); else { - mPeerMgr->setDynDNS(item->sslId, item->dyndns); + mPeerMgr->setDynDNS(item->sslId, item->dyndns); updatePeerAddressList(item); } } @@ -447,8 +501,19 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) if (item->isHidden) { } - else if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId())) // we don't store IP addresses if we're a hidden node. Normally they should not be sent to us, except for old peers. + else if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId())) { + /* Cyril: we don't store IP addresses if we're a hidden node. + * Normally they should not be sent to us, except for old peers. */ + /* G10h4ck: sending IP information also to hidden nodes has proven very + * helpful in the usecase of non hidden nodes, that share a common + * hidden trusted node, to discover each other IP. + * Advanced/corner case non hidden node users that want to hide their + * IP to a specific hidden ~trusted~ node can do it through the + * permission matrix. Disabling this instead will make life more + * difficult for average user, that moreover whould have no way to + * revert an hardcoded policy. */ + pqiIpAddrSet addrsFromPeer; addrsFromPeer.mLocal.extractFromTlv(item->localAddrList); addrsFromPeer.mExt.extractFromTlv(item->extAddrList); @@ -471,13 +536,12 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) void p3discovery2::sendPGPList(const SSLID &toId) { updatePgpFriendList(); - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + RS_STACK_MUTEX(mDiscMtx); #ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendPGPList() to " << toId; - std::cerr << std::endl; + std::cerr << "p3discovery2::sendPGPList() to " << toId << std::endl; #endif RsDiscPgpListItem *pkt = new RsDiscPgpListItem(); @@ -508,7 +572,7 @@ void p3discovery2::updatePgpFriendList() std::cerr << std::endl; #endif - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mDiscMtx); #define PGP_MAX_UPDATE_PERIOD 300 @@ -863,26 +927,20 @@ void p3discovery2::sendContactInfo_locked(const PGPID &aboutId, const SSLID &toI void p3discovery2::processContactInfo(const SSLID &fromId, const RsDiscContactItem *item) { - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + (void) fromId; // remove unused parameter warnings, debug only + + RS_STACK_MUTEX(mDiscMtx); if (item->sslId == rsPeers->getOwnId()) - { - if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr)) - mPeerMgr->addCandidateForOwnExternalAddress(item->PeerId(), item->currentConnectAddress.addr) ; -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processContactInfo(" << fromId << ") PGPID: "; - std::cerr << item->pgpId << " Ignoring Info on self"; - std::cerr << std::endl; -#else - /* remove unused parameter warnings */ - (void) fromId; -#endif - delete item; + { + if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr)) + mPeerMgr->addCandidateForOwnExternalAddress( + item->PeerId(), item->currentConnectAddress.addr); + + delete item; return; } - - /* */ std::map::iterator it; it = mFriendList.find(item->pgpId); if (it == mFriendList.end()) @@ -895,7 +953,8 @@ void p3discovery2::processContactInfo(const SSLID &fromId, const RsDiscContactIt std::cerr << std::endl; #endif - /* THESE ARE OUR FRIEND OF FRIENDS ... pass this information along to NetMgr & DHT... + /* THESE ARE OUR FRIEND OF FRIENDS ... pass this information along to + * NetMgr & DHT... * as we can track FOF and use them as potential Proxies / Relays */ @@ -941,7 +1000,10 @@ void p3discovery2::processContactInfo(const SSLID &fromId, const RsDiscContactIt // set last seen to RS_PEER_OFFLINE_NO_DISC minus 1 so that it won't be shared with other friends // until a first connection is established - mPeerMgr->addFriend(item->sslId, item->pgpId, item->netMode, RS_VS_DISC_OFF, RS_VS_DHT_FULL, time(NULL) - RS_PEER_OFFLINE_NO_DISC - 1, RS_NODE_PERM_ALL); + mPeerMgr->addFriend( item->sslId, item->pgpId, item->netMode, + RS_VS_DISC_OFF, RS_VS_DHT_FULL, + time(NULL) - RS_PEER_OFFLINE_NO_DISC - 1, + RS_NODE_PERM_ALL ); updatePeerAddresses(item); } } diff --git a/libretroshare/src/util/rsnet.cc b/libretroshare/src/util/rsnet.cc index 8b8c9ef82..565185edc 100644 --- a/libretroshare/src/util/rsnet.cc +++ b/libretroshare/src/util/rsnet.cc @@ -4,6 +4,7 @@ * Universal Networking Header for RetroShare. * * Copyright 2007-2008 by Robert Fernie. + * Copyright (C) 2015-2018 Gioacchino Mazzurco * * 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) diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index 0dd3b6741..ffd34ffb7 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -4,6 +4,7 @@ * Universal Networking Header for RetroShare. * * Copyright 2004-2006 by Robert Fernie. + * Copyright (C) 2015-2018 Gioacchino Mazzurco * * 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); diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc index c11b698da..1d94aa882 100644 --- a/libretroshare/src/util/rsnet_ss.cc +++ b/libretroshare/src/util/rsnet_ss.cc @@ -4,6 +4,7 @@ * sockaddr_storage functions for RetroShare. * * Copyright 2013-2013 by Robert Fernie. + * Copyright (C) 2015-2018 Gioacchino Mazzurco * * 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) {