From 2170313e421d9b35add8263360832c16dcd2edae Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Wed, 21 Feb 2018 17:38:31 +0100 Subject: [PATCH 01/10] Improve discovery Workaround RS single local address flawed assumption by spreading all viables local addrresses via discovery Spread addresses also through hidden node as they are the only hope to help direct connection happening for common trusted nodes behind nasty firewalls --- libretroshare/src/services/p3discovery2.cc | 48 ++-------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/libretroshare/src/services/p3discovery2.cc b/libretroshare/src/services/p3discovery2.cc index 286848a6f..a1ee778a4 100644 --- a/libretroshare/src/services/p3discovery2.cc +++ b/libretroshare/src/services/p3discovery2.cc @@ -26,15 +26,11 @@ #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; @@ -43,9 +39,7 @@ 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(); @@ -348,43 +342,8 @@ 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(); /* Cyril: we dont send our own IP to an hidden node. It will not use it * anyway. */ @@ -502,7 +461,6 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) { } 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 @@ -513,7 +471,7 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) * 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); From b3c7d195c874d761a62e02cd051c08f30300fa31 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Thu, 22 Feb 2018 12:18:51 +0100 Subject: [PATCH 02/10] Port pqissl to dual stack IPv6+IPv4 Changed unix_connect signature to be more comfortable for dual stack usage Remove dead code in pqissl::pqissl(...) Adapt p3I2pBob::connectI2P() to new unix_connect Adapt extaddrfinder to new unix_connect Add sockaddr_storage_ipv4_to_ipv6 to convert from flat IPv4 to IPv4 mapped as IPv6 --- libretroshare/src/pqi/p3linkmgr.cc | 3 +- libretroshare/src/pqi/pqinetwork.cc | 34 +-------- libretroshare/src/pqi/pqinetwork.h | 2 +- libretroshare/src/pqi/pqissl.cc | 74 ++++++++----------- libretroshare/src/pqi/pqissl.h | 3 +- .../src/services/autoproxy/p3i2pbob.cc | 4 +- libretroshare/src/util/extaddrfinder.cc | 5 +- libretroshare/src/util/rsnet.h | 1 + libretroshare/src/util/rsnet_ss.cc | 27 +++++++ 9 files changed, 72 insertions(+), 81 deletions(-) diff --git a/libretroshare/src/pqi/p3linkmgr.cc b/libretroshare/src/pqi/p3linkmgr.cc index c84b8ea4f..d3e2b50d0 100644 --- a/libretroshare/src/pqi/p3linkmgr.cc +++ b/libretroshare/src/pqi/p3linkmgr.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 diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index c302123a4..058e1cd07 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -438,43 +438,17 @@ int unix_fcntl_nonblock(int fd) } -int unix_connect(int fd, const struct sockaddr *serv_addr, socklen_t socklen) +int unix_connect(int fd, const sockaddr_storage &serv_addr) { #ifdef NET_DEBUG - std::cerr << "unix_connect()"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << std::endl; #endif - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) serv_addr; - socklen_t len = socklen; - - switch (ss_addr->ss_family) - { - case AF_INET: - len = sizeof(struct sockaddr_in); - break; - case AF_INET6: - len = sizeof(struct sockaddr_in6); - break; - } - - if (len > socklen) - { - std::cerr << "unix_connect() ERROR len > socklen"; - std::cerr << std::endl; - - len = socklen; - //return EINVAL; - } - - int ret = connect(fd, serv_addr, len); + int ret = connect( fd, (const struct sockaddr *) &serv_addr, + sizeof(struct sockaddr_in6) ); /******************* WINDOWS SPECIFIC PART ******************/ #ifdef WINDOWS_SYS // WINDOWS - -#ifdef NET_DEBUG - std::cerr << "unix_connect()" << std::endl; -#endif if (ret != 0) { errno = WinToUnixError(WSAGetLastError()); diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h index 21d8ee81c..e974f68cf 100644 --- a/libretroshare/src/pqi/pqinetwork.h +++ b/libretroshare/src/pqi/pqinetwork.h @@ -103,7 +103,7 @@ bool getLocalAddresses(std::vector & addrs); int unix_close(int sockfd); int unix_socket(int domain, int type, int protocol); int unix_fcntl_nonblock(int sockfd); -int unix_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); +int unix_connect(int sockfd, const sockaddr_storage& serv_addr); int unix_getsockopt_error(int sockfd, int *err); #ifdef WINDOWS_SYS // WINDOWS diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index 898080262..74bf6f8d2 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -4,6 +4,7 @@ * 3P/PQI network interface 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 @@ -96,44 +97,14 @@ static const int PQISSL_SSL_CONNECT_TIMEOUT = 30; * */ -pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) - :NetBinInterface(parent, parent->PeerId()), - mLinkMgr(lm), pqil(l), - mSslMtx("pqissl"), - active(false), certvalid(false), waiting(WAITING_NOT), - sslmode(PQISSL_ACTIVE), ssl_connection(NULL), sockfd(-1), - readpkt(NULL), pktlen(0), total_len(0), - attempt_ts(0), - n_read_zero(0), mReadZeroTS(0), ssl_connect_timeout(0), - mConnectDelay(0), mConnectTS(0), - mConnectTimeout(0), mTimeoutTS(0) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - /* set address to zero */ - sockaddr_storage_clear(remote_addr); - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "pqissl for PeerId: " + PeerId()); -#endif - -#if 0 - if (!(AuthSSL::getAuthSSL()->isAuthenticated(PeerId()))) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::Warning Certificate Not Approved!"); - - rslog(RSL_ALERT, pqisslzone, - "\t pqissl will not initialise...."); - - } -#else - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Warning SSL Certificate Approval Not CHECKED??"); -#endif - - return; -} +pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) : + NetBinInterface(parent, parent->PeerId()), + mLinkMgr(lm), pqil(l), mSslMtx("pqissl"), active(false), certvalid(false), + waiting(WAITING_NOT), sslmode(PQISSL_ACTIVE), ssl_connection(NULL), + sockfd(-1), readpkt(NULL), pktlen(0), total_len(0), attempt_ts(0), + n_read_zero(0), mReadZeroTS(0), ssl_connect_timeout(0), mConnectDelay(0), + mConnectTS(0), mConnectTimeout(0), mTimeoutTS(0) +{ sockaddr_storage_clear(remote_addr); } pqissl::~pqissl() { @@ -151,11 +122,8 @@ pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) int pqissl::connect(const struct sockaddr_storage &raddr) { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - // reset failures + RS_STACK_MUTEX(mSslMtx); remote_addr = raddr; - return ConnectAttempt(); } @@ -613,7 +581,7 @@ int pqissl::Delay_Connection() } -int pqissl::Initiate_Connection() +int pqissl::Initiate_Connection() { int err; struct sockaddr_storage addr = remote_addr; @@ -636,7 +604,7 @@ int pqissl::Initiate_Connection() #endif // open socket connection to addr. - int osock = unix_socket(PF_INET, SOCK_STREAM, 0); + int osock = unix_socket(PF_INET6, SOCK_STREAM, 0); #ifdef PQISSL_LOG_DEBUG { @@ -736,10 +704,26 @@ int pqissl::Initiate_Connection() #endif #endif // WINDOWS_SYS + /* Systems that supports dual stack sockets defines IPV6_V6ONLY and some set + * it to 1 by default. This enable dual stack socket on such systems. + * Systems which don't support dual stack (only Windows older then XP SP3) + * will support IPv6 only and not IPv4 */ +#ifdef IPV6_V6ONLY + int no = 0; + err = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&no, sizeof(no)); +#ifdef PQISSL_DEBUG + if (err) std::cerr << __PRETTY_FUNCTION__ + << " Error setting IPv6 socket dual stack" << std::endl; + else std::cerr << __PRETTY_FUNCTION__ + << " Setting IPv6 socket dual stack" << std::endl; +#endif // PQISSL_DEBUG +#endif // IPV6_V6ONLY + mTimeoutTS = time(NULL) + mConnectTimeout; //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; - if (0 != (err = unix_connect(osock, (struct sockaddr *) &addr, sizeof(addr)))) + sockaddr_storage_ipv4_to_ipv6(addr); + if (0 != (err = unix_connect(osock, addr))) { std::string out; rs_sprintf(out, "pqissl::Initiate_Connection() connect returns:%d -> errno: %d error: %s\n", err, errno, socket_errorType(errno).c_str()); diff --git a/libretroshare/src/pqi/pqissl.h b/libretroshare/src/pqi/pqissl.h index b4cd267d6..5748f5a9c 100644 --- a/libretroshare/src/pqi/pqissl.h +++ b/libretroshare/src/pqi/pqissl.h @@ -4,6 +4,7 @@ * 3P/PQI network interface 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 @@ -114,7 +115,7 @@ virtual bool cansend(uint32_t usec); virtual int close(); /* BinInterface version of reset() */ virtual RsFileHash gethash(); /* not used here */ -virtual bool bandwidthLimited() { return true ; } // replace by !sameLAN to avoid bandwidth limiting on LAN +virtual bool bandwidthLimited() { return true ; } public: diff --git a/libretroshare/src/services/autoproxy/p3i2pbob.cc b/libretroshare/src/services/autoproxy/p3i2pbob.cc index 917b8a8a7..36e5604c7 100644 --- a/libretroshare/src/services/autoproxy/p3i2pbob.cc +++ b/libretroshare/src/services/autoproxy/p3i2pbob.cc @@ -890,7 +890,7 @@ bool p3I2pBob::connectI2P() } // create socket - mSocket = unix_socket(AF_INET, SOCK_STREAM, 0); + mSocket = unix_socket(PF_INET, SOCK_STREAM, 0); if (mSocket < 0) { rslog(RsLog::Warning, &i2pBobLogInfo, "connectI2P_locked Failed to open socket! Socket Error: " + socket_errorType(errno)); @@ -898,7 +898,7 @@ bool p3I2pBob::connectI2P() } // connect - int err = unix_connect(mSocket, (struct sockaddr *)&mI2PProxyAddr, sizeof(mI2PProxyAddr)); + int err = unix_connect(mSocket, mI2PProxyAddr); if (err != 0) { rslog(RsLog::Warning, &i2pBobLogInfo, "connectI2P_locked Failed to connect to BOB! Socket Error: " + socket_errorType(errno)); return false; diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc index e01e37211..308a8ea48 100644 --- a/libretroshare/src/util/extaddrfinder.cc +++ b/libretroshare/src/util/extaddrfinder.cc @@ -94,7 +94,10 @@ static void getPage(const std::string& server_name,std::string& page) #endif std::cerr << "ExtAddrFinder: resolved hostname " << server_name << " to " << rs_inet_ntoa(in) << std::endl; - if(unix_connect(sockfd,(struct sockaddr *)&serveur, sizeof(serveur)) == -1) + sockaddr_storage server; + sockaddr_storage_setipv4(server, &serveur); + sockaddr_storage_setport(server, 80); + if(unix_connect(sockfd, server) == -1) { std::cerr << "ExtAddrFinder: Connection error to " << server_name << std::endl ; unix_close(sockfd); diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index ffd34ffb7..903ee0a65 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -106,6 +106,7 @@ bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name); bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, const uint16_t port); +bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr); // comparisons. bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b); diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc index 1d94aa882..ad4db25ac 100644 --- a/libretroshare/src/util/rsnet_ss.cc +++ b/libretroshare/src/util/rsnet_ss.cc @@ -265,6 +265,33 @@ bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name) return (1 == inet_aton(name, &(ipv4_ptr->sin_addr))); } +bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr) +{ +#ifdef SS_DEBUG + std::cerr << __PRETTY_FUNCTION__ << std::endl; +#endif + + if ( addr.ss_family == AF_INET6 ) return true; + + if ( addr.ss_family == AF_INET ) + { + sockaddr_in & addr_ipv4 = (sockaddr_in &) addr; + sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr; + + u_int32_t ip = addr_ipv4.sin_addr.s_addr; + u_int16_t port = addr_ipv4.sin_port; + + sockaddr_storage_clear(addr); + addr_ipv6.sin6_family = AF_INET6; + addr_ipv6.sin6_port = port; + addr_ipv6.sin6_addr.s6_addr32[3] = ip; + addr_ipv6.sin6_addr.s6_addr16[5] = (u_int16_t) 0xffff; + + return true; + } + + return false; +} /******************************** Comparisions **********************************/ From 4a138e07b990d8c0d95f7da70629ec8e1cac601e Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sat, 24 Feb 2018 14:07:25 +0100 Subject: [PATCH 03/10] Implement IPv6 listening With this commit IPv6-v3 surpass v0.6-IPv6-2 in term of features obsoleting it. p3BitDht handle gracefully unwanted non IPv4 addresses rsUdpStack handle gracefully unwanted non IPv4 addresses pqissludp handle gracefully unwanted non IPv4 addresses Move single address limitation workaround from p3discovery2::sendOwnContactInfo to better place p3PeerMgrIMPL::UpdateOwnAddress this way local address list is queried less often and only id there is some suggestion that it may have changed (probably ir will not be called all the times there is a changes in local network interfaces but is good enough) Implement crossplatform rs_setsockopt to avoid too much ifdef around Implement sockaddr_storage_copy to safely copy sockaddr_storage objects --- libretroshare/src/dht/p3bitdht_peers.cc | 70 +++-- libretroshare/src/pqi/p3netmgr.cc | 7 +- libretroshare/src/pqi/p3peermgr.cc | 98 +++++-- libretroshare/src/pqi/pqinetwork.cc | 9 +- libretroshare/src/pqi/pqissl.cc | 249 ++++++++-------- libretroshare/src/pqi/pqissl.h | 12 +- libretroshare/src/pqi/pqissllistener.cc | 35 ++- libretroshare/src/pqi/pqissludp.cc | 38 ++- libretroshare/src/rsserver/p3peers.cc | 68 ++--- libretroshare/src/services/p3discovery2.cc | 13 +- libretroshare/src/tcponudp/rsudpstack.h | 33 ++- libretroshare/src/util/rsnet.h | 28 +- libretroshare/src/util/rsnet_ss.cc | 323 ++++++++++++++++----- libretroshare/src/util/rsthreads.cc | 13 +- 14 files changed, 618 insertions(+), 378 deletions(-) diff --git a/libretroshare/src/dht/p3bitdht_peers.cc b/libretroshare/src/dht/p3bitdht_peers.cc index 0543b91b2..cf2d2af97 100644 --- a/libretroshare/src/dht/p3bitdht_peers.cc +++ b/libretroshare/src/dht/p3bitdht_peers.cc @@ -4,6 +4,7 @@ * BitDht interface for RetroShare. * * Copyright 2009-2010 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 @@ -184,18 +185,24 @@ bool p3BitDht::dropPeer(const RsPeerId& pid) ********************************* Basic Peer Details ************************************* ******************************************************************************************/ -int p3BitDht::addBadPeer(const struct sockaddr_storage &addr, uint32_t /*reason*/, uint32_t /*flags*/, uint32_t /*age*/) +int p3BitDht::addBadPeer( const sockaddr_storage &addr, uint32_t /*reason*/, + uint32_t /*flags*/, uint32_t /*age*/ ) { //mUdpBitDht->updateKnownPeer(&id, 0, bdflags); - struct sockaddr_in addrv4; - if (addr.ss_family != AF_INET) + sockaddr_in addrv4; + sockaddr_storage tmpaddr; + sockaddr_storage_copy(addr, tmpaddr); + if(!sockaddr_storage_ipv6_to_ipv4(tmpaddr)) { - std::cerr << "p3BitDht::addBadPeer() cannot handle IPV6 Yet, aborting"; - std::cerr << std::endl; - abort(); + std::cerr << __PRETTY_FUNCTION__ << " Error: got non IPv4 address!" + << std::endl; + sockaddr_storage_dump(addr); + print_stacktrace(); + return -EINVAL; } - struct sockaddr_in *ap = (struct sockaddr_in *) &addr; + + struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr; // convert. addrv4.sin_family = ap->sin_family; @@ -216,39 +223,30 @@ 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 sockaddr_storage &addr, uint32_t flags ) { - struct sockaddr_in addrv4; - sockaddr_clear(&addrv4); + sockaddr_in addrv4; + sockaddr_clear(&addrv4); - if (addr.ss_family != AF_INET) - { - if(addr.ss_family != AF_UNSPEC) - { - std::cerr << "p3BitDht::addKnownPeer() Warning! Non IPv4 Address - Cannot handle IPV6 Yet. addr.ss_family=" << addr.ss_family; - std::cerr << std::endl; - } - - if (flags & NETASSIST_KNOWN_PEER_ONLINE) - { - std::cerr << "p3BitDht::addKnownPeer() Non IPv4 Address & ONLINE. Abort()ing."; - std::cerr << std::endl; - abort(); - } - } - else + sockaddr_storage tmpaddr; + sockaddr_storage_copy(addr, tmpaddr); + if( !sockaddr_storage_isnull(addr) && + !sockaddr_storage_ipv6_to_ipv4(tmpaddr) ) { - - // convert. - struct sockaddr_in *ap = (struct sockaddr_in *) &addr; - - addrv4.sin_family = ap->sin_family; - addrv4.sin_addr = ap->sin_addr; - addrv4.sin_port = ap->sin_port; + std::cerr << __PRETTY_FUNCTION__ << " Error: got non IPv4 address!" + << std::endl; + sockaddr_storage_dump(addr); + print_stacktrace(); + return -EINVAL; } - - + // convert. + struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr; + addrv4.sin_family = ap->sin_family; + addrv4.sin_addr = ap->sin_addr; + addrv4.sin_port = ap->sin_port; + int p3type = 0; int bdflags = 0; bdId id; @@ -295,7 +293,7 @@ int p3BitDht::addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &a if (!isOwnId) { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ + RS_STACK_MUTEX(dhtMtx); DhtPeerDetails *dpd = addInternalPeer_locked(pid, p3type); diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 7dad79bb2..54b6415cd 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -1038,12 +1038,15 @@ bool p3NetMgrIMPL::checkNetAddress() } /* If no satisfactory local address has been found yet relax and - * accept also link local addresses */ + * accept also IPv4 link local addresses, IPv6 link local is not + * accepted because of sin6_scope_id that depends on the host using + * it as an outgoing connection endpoint */ if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it) { sockaddr_storage& addr(*it); if( sockaddr_storage_isValidNet(addr) && - !sockaddr_storage_isLoopbackNet(addr) ) + !sockaddr_storage_isLoopbackNet(addr) && + !sockaddr_storage_ipv6_isLinkLocalNet(addr) ) { prefAddr = addr; validAddr = true; diff --git a/libretroshare/src/pqi/p3peermgr.cc b/libretroshare/src/pqi/p3peermgr.cc index 9862838aa..f275170d6 100644 --- a/libretroshare/src/pqi/p3peermgr.cc +++ b/libretroshare/src/pqi/p3peermgr.cc @@ -4,6 +4,7 @@ * 3P/PQI network interface for RetroShare. * * Copyright 2007-2011 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 @@ -23,6 +24,9 @@ * */ +#include // for std::vector +#include // for std::random_shuffle + #include "rsserver/p3face.h" #include "util/rsnet.h" #include "pqi/authgpg.h" @@ -32,6 +36,7 @@ #include "pqi/p3linkmgr.h" #include "pqi/p3netmgr.h" #include "pqi/p3historymgr.h" +#include "pqi/pqinetwork.h" // for getLocalAddresses //#include "pqi/p3dhtmgr.h" // Only need it for constants. //#include "tcponudp/tou.h" @@ -1227,38 +1232,85 @@ void p3PeerMgrIMPL::printPeerLists(std::ostream &out) * as it doesn't call back to there. */ -bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, const struct sockaddr_storage &extAddr) +bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& localAddr, + const sockaddr_storage& extAddr ) { #ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress("; - std::cerr << sockaddr_storage_tostring(localAddr); - std::cerr << ", "; - std::cerr << sockaddr_storage_tostring(extAddr); - std::cerr << ")" << std::endl; + std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress(" + << sockaddr_storage_tostring(localAddr) << ", " + << sockaddr_storage_tostring(extAddr) << ")" << std::endl; #endif - if((rsBanList != NULL) && !rsBanList->isAddressAccepted(localAddr, RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - std::cerr << "(SS) Trying to set own IP to a banned IP " << sockaddr_storage_iptostring(localAddr) << ". This probably means that a friend in under traffic re-routing attack." << std::endl; - return false ; - } + if( rsBanList && + !rsBanList->isAddressAccepted(localAddr, + RSBANLIST_CHECKING_FLAGS_BLACKLIST) ) + { + std::cerr << "(SS) Trying to set own IP to a banned IP " + << sockaddr_storage_iptostring(localAddr) << ". This probably" + << "means that a friend in under traffic re-routing attack." + << std::endl; + return false; + } - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ + { + RS_STACK_MUTEX(mPeerMtx); - //update ip address list - pqiIpAddress ipAddressTimed; - ipAddressTimed.mAddr = localAddr; - ipAddressTimed.mSeenTime = time(NULL); - ipAddressTimed.mSrc = 0 ; - mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed); + //update ip address list + pqiIpAddress ipAddressTimed; + ipAddressTimed.mAddr = localAddr; + ipAddressTimed.mSeenTime = time(NULL); + ipAddressTimed.mSrc = 0; + mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed); - mOwnState.localaddr = localAddr; - } + if(!mOwnState.hiddenNode) + { + /* 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(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) && + /* Avoid IPv6 link local addresses as we don't have + * implemented the logic needed to handle sin6_scope_id. + * To properly handle sin6_scope_id it would probably + * require deep reenginering of the RetroShare + * networking stack */ + !sockaddr_storage_ipv6_isLinkLocalNet(addr) ) + { + 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(localAddr) ); + pqiIp.mSeenTime = time(nullptr); + pqiIp.mSrc = 0; + mOwnState.ipAddrs.updateLocalAddrs(pqiIp); + } + } + } + } + + mOwnState.localaddr = localAddr; + } - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ + { + RS_STACK_MUTEX(mPeerMtx); //update ip address list pqiIpAddress ipAddressTimed; diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index 058e1cd07..8f843cfeb 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -41,6 +41,7 @@ #include "util/rsdebug.h" #include "util/rsstring.h" #include "util/rsnet.h" +#include "util/stacktrace.h" static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"}; #define pqinetzone &pqinetzoneInfo @@ -335,15 +336,17 @@ bool getLocalAddresses(std::vector& addrs) struct ifaddrs *ifsaddrs, *ifa; if(getifaddrs(&ifsaddrs) != 0) { - std::cerr << "FATAL ERROR: getLocalAddresses failed!" << std::endl; - return false ; + std::cerr << __PRETTY_FUNCTION__ << " FATAL ERROR: " << errno << " " + << strerror(errno) << std::endl; + print_stacktrace(); + return false; } for ( ifa = ifsaddrs; ifa; ifa = ifa->ifa_next ) if ( ifa->ifa_addr && (ifa->ifa_flags & IFF_UP) ) { sockaddr_storage tmp; sockaddr_storage_clear(tmp); - if (sockaddr_storage_copyip(tmp, * reinterpret_cast(ifa->ifa_addr))) + if (sockaddr_storage_copyip(tmp, *reinterpret_cast(ifa->ifa_addr))) addrs.push_back(tmp); } freeifaddrs(ifsaddrs); diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index 74bf6f8d2..d549e9542 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -60,14 +60,15 @@ static struct RsLog::logInfo pqisslzoneInfo = {RsLog::Default, "pqisslzone"}; #define PQISSL_PASSIVE 0x00 #define PQISSL_ACTIVE 0x01 -#define PQISSL_DEBUG 1 -#define PQISSL_LOG_DEBUG 1 - const int PQISSL_LOCAL_FLAG = 0x01; const int PQISSL_REMOTE_FLAG = 0x02; const int PQISSL_UDP_FLAG = 0x02; ***********/ +//#define PQISSL_DEBUG 1 +//#define PQISSL_LOG_DEBUG 1 + + static const int PQISSL_MAX_READ_ZERO_COUNT = 20; static const time_t PQISSL_MAX_READ_ZERO_TIME = 15; // 15 seconds of no data => reset. (atm HeartBeat pkt sent 5 secs) @@ -123,6 +124,7 @@ pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) : int pqissl::connect(const struct sockaddr_storage &raddr) { RS_STACK_MUTEX(mSslMtx); + remote_addr = raddr; return ConnectAttempt(); } @@ -171,12 +173,11 @@ int pqissl::close() // put back on the listening queue. int pqissl::reset() { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - + RS_STACK_MUTEX(mSslMtx); return reset_locked(); } -int pqissl::reset_locked() +int pqissl::reset_locked() { std::string outLog; bool neededReset = false; @@ -355,7 +356,7 @@ int pqissl::status() out += " active: \n"; // print out connection. - out += "Connected TO : " + PeerId() + "\n"; + out += "Connected TO : " + PeerId().toStdString() + "\n"; // print out cipher. rs_sprintf_append(out, "\t\tSSL Cipher:%s", SSL_get_cipher(ssl_connection)); rs_sprintf_append(out, " (%d:%d)", SSL_get_cipher_bits(ssl_connection, &alg), alg); @@ -551,7 +552,7 @@ int pqissl::Delay_Connection() #ifdef PQISSL_LOG_DEBUG { std::string out; - rs_sprintf(out, "pqissl::Delay_Connection() Delaying Connection to %s for %lu seconds", PeerId().c_str(), mConnectDelay); + rs_sprintf(out, "pqissl::Delay_Connection() Delaying Connection to %s for %lu seconds", PeerId().toStdString(), mConnectDelay); rslog(RSL_DEBUG_BASIC, pqisslzone, out); } #endif @@ -564,7 +565,7 @@ int pqissl::Delay_Connection() #ifdef PQISSL_LOG_DEBUG { std::string out; - rs_sprintf(out, "pqissl::Delay_Connection() Connection to %s starting in %ld seconds", PeerId().c_str(), mConnectTS - time(NULL)); + rs_sprintf(out, "pqissl::Delay_Connection() Connection to %s starting in %ld seconds", PeerId().toStdString(), mConnectTS - time(NULL)); rslog(RSL_DEBUG_BASIC, pqisslzone, out); } #endif @@ -710,10 +711,12 @@ int pqissl::Initiate_Connection() * will support IPv6 only and not IPv4 */ #ifdef IPV6_V6ONLY int no = 0; - err = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&no, sizeof(no)); + err = rs_setsockopt( osock, IPPROTO_IPV6, IPV6_V6ONLY, + reinterpret_cast(&no), sizeof(no) ); #ifdef PQISSL_DEBUG if (err) std::cerr << __PRETTY_FUNCTION__ - << " Error setting IPv6 socket dual stack" << std::endl; + << " Error setting IPv6 socket dual stack: " + << errno << " " << strerror(errno) << std::endl; else std::cerr << __PRETTY_FUNCTION__ << " Setting IPv6 socket dual stack" << std::endl; #endif // PQISSL_DEBUG @@ -1089,7 +1092,7 @@ int pqissl::Initiate_SSL_Connection() return 1; } -int pqissl::SSL_Connection_Complete() +int pqissl::SSL_Connection_Complete() { #ifdef PQISSL_LOG_DEBUG rslog(RSL_DEBUG_BASIC, pqisslzone, @@ -1231,27 +1234,21 @@ int pqissl::Extract_Failed_SSL_Certificate() -int pqissl::Authorise_SSL_Connection() +int pqissl::Authorise_SSL_Connection() { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Authorise_SSL_Connection()"); +#ifdef PQISSL_DEBUG + std::cerr << __PRETTY_FUNCTION__ << std::endl; #endif - if (time(NULL) > ssl_connect_timeout) - { - rslog(RSL_WARNING, pqisslzone, - "pqissl::Authorise_SSL_Connection() Connection Timed Out!"); - /* as sockfd is valid, this should close it all up */ - rslog(RSL_ALERT, pqisslzone, "pqissl::Authorise_Connection_Complete() -> calling reset()"); - reset_locked(); + if (time(NULL) > ssl_connect_timeout) + { + std::cerr << __PRETTY_FUNCTION__ << " Connection timed out reset!" + << std::endl; + reset_locked(); } int err; - if (0 >= (err = SSL_Connection_Complete())) - { - return err; - } + if (0 >= (err = SSL_Connection_Complete())) return err; #ifdef PQISSL_LOG_DEBUG rslog(RSL_DEBUG_BASIC, pqisslzone, @@ -1336,36 +1333,54 @@ int pqissl::Authorise_SSL_Connection() /* This function is public, and callable from pqilistener - so must be mutex protected */ -int pqissl::accept(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr) // initiate incoming connection. +int pqissl::accept( SSL *ssl, int fd, + const sockaddr_storage &foreign_addr) { #ifdef PQISSL_DEBUG - std::cerr << "pqissl::accept()"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << std::endl; #endif - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - + RS_STACK_MUTEX(mSslMtx); return accept_locked(ssl, fd, foreign_addr); } -int pqissl::accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr) // initiate incoming connection. +int pqissl::accept_locked( SSL *ssl, int fd, + const sockaddr_storage &foreign_addr ) { - uint32_t check_result; - uint32_t checking_flags = RSBANLIST_CHECKING_FLAGS_BLACKLIST; - if (rsPeers->servicePermissionFlags(PeerId()) & RS_NODE_PERM_REQUIRE_WL) - checking_flags |= RSBANLIST_CHECKING_FLAGS_WHITELIST; +#ifdef PQISSL_DEBUG + std::cerr << __PRETTY_FUNCTION__ << std::endl; +#endif - if(rsBanList!=NULL && !rsBanList->isAddressAccepted(foreign_addr,checking_flags,&check_result)) - { - std::cerr << "(SS) refusing incoming SSL connection from blacklisted foreign address " << sockaddr_storage_iptostring(foreign_addr) - << ". Reason: " << check_result << "." << std::endl; - RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_IP_BLACKLISTED, PeerId().toStdString(), sockaddr_storage_iptostring(foreign_addr), "", "", check_result); + uint32_t check_result; + uint32_t checking_flags = RSBANLIST_CHECKING_FLAGS_BLACKLIST; + + if (rsPeers->servicePermissionFlags(PeerId()) & RS_NODE_PERM_REQUIRE_WL) + checking_flags |= RSBANLIST_CHECKING_FLAGS_WHITELIST; + + if( rsBanList && !rsBanList->isAddressAccepted( foreign_addr, + checking_flags, + &check_result ) ) + { + std::cerr << __PRETTY_FUNCTION__ + << " (SS) refusing incoming SSL connection from blacklisted " + << "foreign address " + << sockaddr_storage_iptostring(foreign_addr) + << ". Reason: " << check_result << "." << std::endl; + + RsServer::notify()->AddFeedItem( + RS_FEED_ITEM_SEC_IP_BLACKLISTED, + PeerId().toStdString(), + sockaddr_storage_iptostring(foreign_addr), "", "", + check_result); reset_locked(); - return -1; - } + return -1; + } + if (waiting != WAITING_NOT) { - rslog(RSL_WARNING, pqisslzone, "pqissl::accept() Peer: " + PeerId().toStdString() + " - Two connections in progress - Shut 1 down!"); + std::cerr << __PRETTY_FUNCTION__ << " Peer: " << PeerId().toStdString() + << " - Two connections in progress - Shut 1 down!" + << std::endl; // outgoing connection in progress. // shut this baby down. @@ -1376,70 +1391,51 @@ int pqissl::accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &forei switch(waiting) { - case WAITING_SOCK_CONNECT: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::accept() STATE = Waiting Sock Connect - close the socket"); +#ifdef PQISSL_DEBUG + std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting Sock Connect " + << "- close the socket" << std::endl; #endif - break; - case WAITING_SSL_CONNECTION: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::accept() STATE = Waiting SSL Connection - close sockfd + ssl_conn"); +#ifdef PQISSL_DEBUG + std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting SSL " + << "Connection - close sockfd + ssl_conn" << std::endl; #endif - break; - case WAITING_SSL_AUTHORISE: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::accept() STATE = Waiting SSL Authorise - close sockfd + ssl_conn"); +#ifdef PQISSL_DEBUG + std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting SSL Authorise" + << " - close sockfd + ssl_conn" << std::endl; #endif - break; - case WAITING_FAIL_INTERFACE: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::accept() STATE = Failed, ignore?"); +#ifdef PQISSL_DEBUG + std::cerr << __PRETTY_FUNCTION__ << " STATE = Failed, ignore?" + << std::endl; #endif - break; - - default: - rslog(RSL_ALERT, pqisslzone, - "pqissl::accept() STATE = Unknown - ignore?"); - - rslog(RSL_ALERT, pqisslzone, "pqissl::accept() -> calling reset()"); + std::cerr << __PRETTY_FUNCTION__ << " STATE = Unknown - resetting!" + << std::endl; reset_locked(); break; } - - //waiting = WAITING_FAIL_INTERFACE; - //return -1; } /* shutdown existing - in all cases use the new one */ if ((ssl_connection) && (ssl_connection != ssl)) { - rslog(RSL_ALERT, pqisslzone, - "pqissl::accept() closing Previous/Existing ssl_connection"); + std::cerr << __PRETTY_FUNCTION__ + << " closing Previous/Existing ssl_connection" << std::endl; SSL_shutdown(ssl_connection); SSL_free (ssl_connection); } if ((sockfd > -1) && (sockfd != fd)) { - rslog(RSL_ALERT, pqisslzone, - "pqissl::accept() closing Previous/Existing sockfd"); + std::cerr << __PRETTY_FUNCTION__ << " closing Previous/Existing sockfd" + << std::endl; net_internal_close(sockfd); } @@ -1452,54 +1448,39 @@ int pqissl::accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &forei /* if we connected - then just writing the same over, * but if from ssllistener then we need to save the address. */ - remote_addr = foreign_addr; + sockaddr_storage_copy(foreign_addr, remote_addr); - /* check whether it is on the same LAN */ - - struct sockaddr_storage localaddr; - mLinkMgr->getLocalAddress(localaddr); + std::cerr << __PRETTY_FUNCTION__ << " SUCCESSFUL connection to: " + << PeerId().toStdString() << " remoteaddr: " + << sockaddr_storage_iptostring(remote_addr) << std::endl; +#ifdef PQISSL_DEBUG { - std::string out = "pqissl::accept() SUCCESSFUL connection to: " + PeerId().toStdString(); - out += " localaddr: " + sockaddr_storage_iptostring(localaddr); - out += " remoteaddr: " + sockaddr_storage_iptostring(remote_addr); - - rslog(RSL_WARNING, pqisslzone, out); - } - - // establish the ssl details. - // cipher name. - int err; - -#ifdef PQISSL_LOG_DEBUG - { - int alg; - std::string out; - rs_sprintf(out, "SSL Cipher:%s\n", SSL_get_cipher(ssl)); - rs_sprintf_append(out, "SSL Cipher Bits:%d - %d\n", SSL_get_cipher_bits(ssl, &alg), alg); - rs_sprintf_append(out, "SSL Cipher Version:%s\n", SSL_get_cipher_version(ssl)); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); + int alg; + std::cerr << __PRETTY_FUNCTION__ << "SSL Cipher: " + << SSL_get_cipher(ssl) << std::endl << "SSL Cipher Bits: " + << SSL_get_cipher_bits(ssl, &alg) << " - " << alg + << std::endl; } #endif // make non-blocking / or check..... - if ((err = net_internal_fcntl_nonblock(sockfd)) < 0) + int err; + if ((err = net_internal_fcntl_nonblock(sockfd)) < 0) { - rslog(RSL_ALERT, pqisslzone, "Error: Cannot make socket NON-Blocking: "); + std::cerr << __PRETTY_FUNCTION__ << "Cannot make socket NON-Blocking " + << "reset!" << std::endl; active = false; - waiting = WAITING_FAIL_INTERFACE; - // failed completely. - rslog(RSL_ALERT, pqisslzone, "pqissl::accept() -> calling reset()"); + waiting = WAITING_FAIL_INTERFACE; // failed completely. + reset_locked(); return -1; } - else - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "pqissl::accept() Socket Made Non-Blocking!"); +#ifdef PQISSL_DEBUG + else std::cerr << __PRETTY_FUNCTION__ << " Socket made non-nlocking!" + << std::endl; #endif - } // we want to continue listening - incase this socket is crap, and they try again. //stoplistening(); @@ -1508,15 +1489,16 @@ int pqissl::accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &forei waiting = WAITING_NOT; #ifdef PQISSL_DEBUG - std::cerr << "pqissl::accept_locked() connection complete - notifying parent"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << "connection complete - notifying parent" + << std::endl; #endif // Notify the pqiperson.... (Both Connect/Receive) if (parent()) { - struct sockaddr_storage addr = remote_addr; - parent() -> notifyEvent(this, NET_CONNECT_SUCCESS, addr); + // Is the copy necessary? + sockaddr_storage addr; sockaddr_storage_copy(remote_addr, addr); + parent()->notifyEvent(this, NET_CONNECT_SUCCESS, addr); } return 1; } @@ -1610,31 +1592,35 @@ int pqissl::senddata(void *data, int len) return tmppktlen; } -int pqissl::readdata(void *data, int len) +int pqissl::readdata(void *data, int len) { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ + RS_STACK_MUTEX(mSslMtx); #ifdef PQISSL_DEBUG - std::cout << "Reading data thread=" << pthread_self() << ", ssl=" << (void*)this << std::endl ; + std::cout << "Reading data thread=" << pthread_self() << ", ssl=" + << (void*)this << std::endl; #endif + // Safety check. Apparently this avoids some SIGSEGV. - // - if (ssl_connection == NULL) - return -1 ; + if (ssl_connection == NULL) return -1; // There is a do, because packets can be splitted into multiple ssl buffers // when they are larger than 16384 bytes. Such packets have to be read in // multiple slices. do { - int tmppktlen ; + int tmppktlen; #ifdef PQISSL_DEBUG - std::cerr << "calling SSL_read. len=" << len << ", total_len=" << total_len << std::endl ; + std::cerr << "calling SSL_read. len=" << len << ", total_len=" + << total_len << std::endl; #endif - ERR_clear_error() ; - - tmppktlen = SSL_read(ssl_connection, (void*)( &(((uint8_t*)data)[total_len])), len-total_len) ; + ERR_clear_error(); + + tmppktlen = SSL_read(ssl_connection, + (void*)( &(((uint8_t*)data)[total_len])), + len-total_len); + #ifdef PQISSL_DEBUG std::cerr << "have read " << tmppktlen << " bytes" << std::endl ; std::cerr << "data[0] = " @@ -1649,7 +1635,6 @@ int pqissl::readdata(void *data, int len) #endif // Need to catch errors..... - // if (tmppktlen <= 0) // probably needs a reset. { std::string out; diff --git a/libretroshare/src/pqi/pqissl.h b/libretroshare/src/pqi/pqissl.h index 5748f5a9c..e14e3928d 100644 --- a/libretroshare/src/pqi/pqissl.h +++ b/libretroshare/src/pqi/pqissl.h @@ -119,12 +119,9 @@ virtual bool bandwidthLimited() { return true ; } public: -/* Completion of the SSL connection, - * this is public, so it can be called by - * the listener (should make friends??) - */ +/// initiate incoming connection. +int accept(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr); -int accept(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr); void getCryptoParams(RsPeerCryptoParams& params) ; bool actAsServer(); @@ -140,7 +137,10 @@ protected: RsMutex mSslMtx; /**** MUTEX protects data and fn below ****/ virtual int reset_locked(); -int accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr); + + /// initiate incoming connection. + int accept_locked( SSL *ssl, int fd, + const sockaddr_storage& foreign_addr ); // A little bit of information to describe // the SSL state, this is needed diff --git a/libretroshare/src/pqi/pqissllistener.cc b/libretroshare/src/pqi/pqissllistener.cc index 975791eec..15c754888 100644 --- a/libretroshare/src/pqi/pqissllistener.cc +++ b/libretroshare/src/pqi/pqissllistener.cc @@ -4,6 +4,7 @@ * 3P/PQI network interface 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 @@ -103,17 +104,27 @@ int pqissllistenbase::status() return 1; } -int pqissllistenbase::setuplisten() +int pqissllistenbase::setuplisten() { - int err; - if (active) - return -1; + int err; + if (active) return -1; + + lsock = socket(PF_INET6, SOCK_STREAM, 0); + +#ifdef IPV6_V6ONLY + int no = 0; + err = rs_setsockopt(lsock, IPPROTO_IPV6, IPV6_V6ONLY, + reinterpret_cast(&no), sizeof(no)); + if (err) std::cerr << __PRETTY_FUNCTION__ + << ": Error setting IPv6 socket dual stack" << std::endl; + else std::cerr << __PRETTY_FUNCTION__ + << ": Success setting IPv6 socket dual stack" << std::endl; +#endif // IPV6_V6ONLY - lsock = socket(PF_INET, SOCK_STREAM, 0); /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS // ie UNIX - if (lsock < 0) - { + if (lsock < 0) + { pqioutput(PQL_ALERT, pqissllistenzone, "pqissllistenbase::setuplisten() Cannot Open Socket!"); @@ -199,10 +210,14 @@ int pqissllistenbase::setuplisten() #ifdef OPEN_UNIVERSAL_PORT struct sockaddr_storage tmpaddr = laddr; - if (!mPeerMgr->isHidden()) sockaddr_storage_zeroip(tmpaddr); - if (0 != (err = universal_bind(lsock, (struct sockaddr *) &tmpaddr, sizeof(tmpaddr)))) + if (!mPeerMgr->isHidden()) + { + tmpaddr.ss_family = PF_INET6; + sockaddr_storage_zeroip(tmpaddr); + } + if (0 != (err = rs_bind(lsock, tmpaddr))) #else - if (0 != (err = universal_bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr)))) + if (0 != (err = universal_bind(lsock, laddr))) #endif { std::string out = "pqissllistenbase::setuplisten() Cannot Bind to Local Address!\n"; diff --git a/libretroshare/src/pqi/pqissludp.cc b/libretroshare/src/pqi/pqissludp.cc index f14fb82e5..8d7e45fd1 100644 --- a/libretroshare/src/pqi/pqissludp.cc +++ b/libretroshare/src/pqi/pqissludp.cc @@ -250,22 +250,38 @@ int pqissludp::Initiate_Connection() { - std::cerr << "CONVERTING ALL ADDRESSES TO IPV4: TODO make IPV6"; - std::cerr << std::endl; - struct sockaddr_in srcaddr; struct sockaddr_in proxyaddr; struct sockaddr_in remoteaddr; - - if ((mConnectSrcAddr.ss_family != AF_INET) || - (mConnectProxyAddr.ss_family != AF_INET) || - (remote_addr.ss_family != AF_INET)) + + bool nonIpV4 = false; + if(!sockaddr_storage_ipv6_to_ipv4(remote_addr)) { - std::cerr << "Error One Address is not IPv4. aborting"; - std::cerr << std::endl; - abort(); + nonIpV4 = true; + std::cerr << __PRETTY_FUNCTION__ << "Error: remote_addr is not " + << "valid IPv4!" << std::endl; + sockaddr_storage_dump(remote_addr); } - + if(!sockaddr_storage_ipv6_to_ipv4(mConnectSrcAddr)) + { + nonIpV4 = true; + std::cerr << __PRETTY_FUNCTION__ << "Error: mConnectSrcAddr is " + << "not valid IPv4!" << std::endl; + sockaddr_storage_dump(mConnectSrcAddr); + } + if(!sockaddr_storage_ipv6_to_ipv4(mConnectProxyAddr)) + { + nonIpV4 = true; + std::cerr << __PRETTY_FUNCTION__ << "Error: mConnectProxyAddr " + << "is not valid IPv4!" << std::endl; + sockaddr_storage_dump(mConnectProxyAddr); + } + if(!nonIpV4) + { + print_stacktrace(); + return -EINVAL; + } + struct sockaddr_in *rap = (struct sockaddr_in *) &remote_addr; struct sockaddr_in *pap = (struct sockaddr_in *) &mConnectProxyAddr; struct sockaddr_in *sap = (struct sockaddr_in *) &mConnectSrcAddr; diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index 9292e1562..245a074df 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -4,6 +4,7 @@ * RetroShare C++ Interface. * * Copyright 2004-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 @@ -900,68 +901,33 @@ bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &address, uin return true; } -bool p3Peers::setLocalAddress(const RsPeerId &id, const std::string &addr_str, uint16_t port) +bool p3Peers::setLocalAddress(const RsPeerId &id, + const std::string &addr_str, uint16_t port) { #ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setLocalAddress() " << id << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " " + << port << std::endl; #endif - if(port < 1024) - { - std::cerr << "(EE) attempt to use a port that is reserved to the system: " << port << std::endl; - return false ; - } - - struct sockaddr_storage addr; - struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr; - addrv4p->sin_family = AF_INET; - addrv4p->sin_port = htons(port); - - int ret = 1; -/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ -#ifndef WINDOWS_SYS - if (ret && (0 != inet_aton(addr_str.c_str(), &(addrv4p->sin_addr)))) -#else - addrv4p->sin_addr.s_addr = inet_addr(addr_str.c_str()); - if (ret) -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ - { - return mPeerMgr->setLocalAddress(id, addr); - } + sockaddr_storage addr; + if (sockaddr_storage_inet_pton(addr, addr_str)) + if (sockaddr_storage_setport(addr, port)) + return mPeerMgr->setLocalAddress(id, addr); return false; } -bool p3Peers::setExtAddress(const RsPeerId &id, const std::string &addr_str, uint16_t port) +bool p3Peers::setExtAddress(const RsPeerId &id, + const std::string &addr_str, uint16_t port) { #ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setExtAddress() " << id << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " " + << port << std::endl; #endif - if(port < 1024) - { - std::cerr << "(EE) attempt to use a port that is reserved to the system: " << port << std::endl; - return false ; - } - - // NOTE THIS IS IPV4 FOR NOW. - struct sockaddr_storage addr; - struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr; - addrv4p->sin_family = AF_INET; - addrv4p->sin_port = htons(port); - - int ret = 1; -/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ -#ifndef WINDOWS_SYS - if (ret && (0 != inet_aton(addr_str.c_str(), &(addrv4p->sin_addr)))) -#else - addrv4p->sin_addr.s_addr = inet_addr(addr_str.c_str()); - if (ret) -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ - { - return mPeerMgr->setExtAddress(id, addr); - } + sockaddr_storage addr; + if (sockaddr_storage_inet_pton(addr, addr_str)) + if (sockaddr_storage_setport(addr, port)) + return mPeerMgr->setExtAddress(id, addr); return false; } diff --git a/libretroshare/src/services/p3discovery2.cc b/libretroshare/src/services/p3discovery2.cc index a1ee778a4..3eacf2548 100644 --- a/libretroshare/src/services/p3discovery2.cc +++ b/libretroshare/src/services/p3discovery2.cc @@ -39,7 +39,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(); @@ -342,7 +344,7 @@ void p3discovery2::sendOwnContactInfo(const SSLID &sslid) std::cerr << std::endl; #endif peerState detail; - if (mPeerMgr->getOwnNetStatus(detail)) + if (mPeerMgr->getOwnNetStatus(detail)) { RsDiscContactItem *pkt = new RsDiscContactItem(); /* Cyril: we dont send our own IP to an hidden node. It will not use it @@ -461,6 +463,7 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) { } 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 @@ -471,13 +474,13 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) * 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; + pqiIpAddrSet addrsFromPeer; addrsFromPeer.mLocal.extractFromTlv(item->localAddrList); addrsFromPeer.mExt.extractFromTlv(item->extAddrList); #ifdef P3DISC_DEBUG - std::cerr << "Setting address list to peer " << item->sslId << ", to be:" << std::endl ; + std::cerr << "Setting address list to peer " << item->sslId + << ", to be:" << std::endl ; std::string addrstr; addrsFromPeer.printAddrs(addrstr); diff --git a/libretroshare/src/tcponudp/rsudpstack.h b/libretroshare/src/tcponudp/rsudpstack.h index e2dec61b0..ac1408a05 100644 --- a/libretroshare/src/tcponudp/rsudpstack.h +++ b/libretroshare/src/tcponudp/rsudpstack.h @@ -50,34 +50,37 @@ virtual bool resetAddress(struct sockaddr_in &local) { return false; } /*******************************************************/ #include "pqi/pqimonitor.h" +#include "util/rsnet.h" +#include "util/stacktrace.h" + #include class rsUdpStack: public UdpStack, public pqiNetListener { - public: - rsUdpStack(struct sockaddr_in &local) - :UdpStack(local) { return; } +public: + rsUdpStack(struct sockaddr_in &local) : UdpStack(local) {} - rsUdpStack(int testmode, struct sockaddr_in &local) - :UdpStack(testmode, local) { return; } + rsUdpStack(int testmode, struct sockaddr_in &local) : + UdpStack(testmode, local) {} - /* from pqiNetListener */ -virtual bool resetListener(const struct sockaddr_storage &local) + /// @see pqiNetListener + virtual bool resetListener(const sockaddr_storage& local) { - //std::cerr << "rsUdpStack::resetListener(" << sockaddr_storage_tostring(local) << ")"; - //std::cerr << std::endl; + sockaddr_storage temp; + sockaddr_storage_copy(local, temp); - if (local.ss_family != AF_INET) + if (!sockaddr_storage_ipv6_to_ipv4(temp)) { - std::cerr << "rsUdpStack::resetListener() NOT IPv4 ERROR"; - std::cerr << std::endl; - abort(); + std::cerr << __PRETTY_FUNCTION__ << " Got non IPv4 address ERROR" + << std::endl; + sockaddr_storage_dump(local); + print_stacktrace(); + return -EINVAL; } - struct sockaddr_in *addr = (struct sockaddr_in *) &local; + sockaddr_in *addr = reinterpret_cast(&temp); return resetAddress(*addr); } - }; class rsFixedUdpStack: public UdpStack, public pqiNetListener diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index 903ee0a65..1d028e991 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -88,14 +88,26 @@ std::string rs_inet_ntoa(struct in_addr in); /***************************/ // sockaddr_storage fns. -// Standard bind, on OSX anyway will not accept a longer socklen for IPv4. -// so hidding details behind function. -int universal_bind(int fd, const struct sockaddr *addr, socklen_t socklen); +int rs_bind(int fd, const sockaddr_storage& addr); void sockaddr_storage_clear(struct sockaddr_storage &addr); // mods. bool sockaddr_storage_zeroip(struct sockaddr_storage &addr); + +/** + * @brief Use this function to copy sockaddr_storage. + * + * POSIX does not require that objects of type sockaddr_storage can be copied + * as aggregates thus it is unsafe to aggregate copy ( operator = ) + * sockaddr_storage and unexpected behaviors may happens due to padding + * and alignment. + * + * @see https://sourceware.org/bugzilla/show_bug.cgi?id=20111 + * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71120 + */ +bool sockaddr_storage_copy(const sockaddr_storage& src, sockaddr_storage& dst); + bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src); uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr); bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port); @@ -103,10 +115,14 @@ bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port); bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in *addr_ipv4); bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 *addr_ipv6); +bool sockaddr_storage_inet_pton( sockaddr_storage &addr, + const std::string& ipStr ); bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name); + bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, const uint16_t port); bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr); +bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr); // comparisons. bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b); @@ -132,8 +148,12 @@ 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_ipv6_isLinkLocalNet(const sockaddr_storage &addr); bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr); -bool rs_inet_ntop(const sockaddr_storage &addr, std::string &dst); +bool sockaddr_storage_inet_ntop(const sockaddr_storage &addr, std::string &dst); + +int rs_setsockopt( int sockfd, int level, int optname, + const uint8_t *optval, uint32_t optlen ); #endif /* RS_UNIVERSAL_NETWORK_HEADER */ diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc index ad4db25ac..da9ab2dfb 100644 --- a/libretroshare/src/util/rsnet_ss.cc +++ b/libretroshare/src/util/rsnet_ss.cc @@ -26,6 +26,24 @@ #include #include +#include + +#ifdef WINDOWS_SYS +# include +/** Provides Linux like accessor for in6_addr.s6_addr16 for Windows. + * Yet Windows doesn't provide 32 bits accessors so there is no way to use + * in6_addr.s6_addr32 crossplatform. + */ +# define s6_addr16 u.Word +#else +# include +# include +# include +# ifdef __APPLE__ +/// Provides Linux like accessor for in6_addr.s6_addr16 for Mac. +# define s6_addr16 __u6_addr.__u6_addr16 +#endif // __APPLE__ +#endif // WINDOWS_SYS #include "util/rsnet.h" #include "util/rsstring.h" @@ -90,17 +108,14 @@ bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &addr); /******************************** Socket Fns ***********************************/ // Standard bind, on OSX anyway will not accept a longer socklen for IPv4. // so hidding details behind function. -int universal_bind(int fd, const struct sockaddr *addr, socklen_t socklen) +int rs_bind(int fd, const sockaddr_storage& addr) { #ifdef SS_DEBUG - std::cerr << "universal_bind()"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << std::endl; #endif - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) addr; - socklen_t len = socklen; - - switch (ss_addr->ss_family) + socklen_t len = 0; + switch (addr.ss_family) { case AF_INET: len = sizeof(struct sockaddr_in); @@ -110,13 +125,7 @@ int universal_bind(int fd, const struct sockaddr *addr, socklen_t socklen) break; } - if (len > socklen) - { - std::cerr << "universal_bind() ERROR len > socklen" << std::endl; - len = socklen; - } - - return bind(fd, addr, len); + return bind(fd, reinterpret_cast(&addr), len); } @@ -252,6 +261,58 @@ bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 return true; } +#ifdef WINDOWS_SYS +int inet_pton(int af, const char *src, void *dst) +{ + sockaddr_storage ss; + int size = sizeof(ss); + char src_copy[INET6_ADDRSTRLEN+1]; + + ZeroMemory(&ss, sizeof(ss)); + /* stupid non-const API */ + strncpy (src_copy, src, INET6_ADDRSTRLEN+1); + src_copy[INET6_ADDRSTRLEN] = 0; + + if (WSAStringToAddressA(src_copy, af, NULL, (sockaddr *)&ss, &size) == 0) + { + switch(af) + { + case AF_INET: + *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr; + return 1; + case AF_INET6: + *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr; + return 1; + } + } + return 0; +} +#endif + +bool sockaddr_storage_inet_pton( sockaddr_storage &addr, + const std::string& ipStr ) +{ +#ifdef SS_DEBUG + std::cerr << __PRETTY_FUNCTION__ << std::endl; +#endif + + struct sockaddr_in6 * addrv6p = (struct sockaddr_in6 *) &addr; + struct sockaddr_in * addrv4p = (struct sockaddr_in *) &addr; + + if ( 1 == inet_pton(AF_INET6, ipStr.c_str(), &(addrv6p->sin6_addr)) ) + { + addr.ss_family = AF_INET6; + return true; + } + else if ( 1 == inet_pton(AF_INET, ipStr.c_str(), &(addrv4p->sin_addr)) ) + { + addr.ss_family = AF_INET; + return sockaddr_storage_ipv4_to_ipv6(addr); + } + + return false; +} + bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name) { @@ -278,21 +339,59 @@ bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr) sockaddr_in & addr_ipv4 = (sockaddr_in &) addr; sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr; - u_int32_t ip = addr_ipv4.sin_addr.s_addr; - u_int16_t port = addr_ipv4.sin_port; + uint32_t ip = addr_ipv4.sin_addr.s_addr; + uint16_t port = addr_ipv4.sin_port; sockaddr_storage_clear(addr); addr_ipv6.sin6_family = AF_INET6; addr_ipv6.sin6_port = port; - addr_ipv6.sin6_addr.s6_addr32[3] = ip; - addr_ipv6.sin6_addr.s6_addr16[5] = (u_int16_t) 0xffff; - + addr_ipv6.sin6_addr.s6_addr16[5] = htons(0xffff); + memmove( reinterpret_cast(&(addr_ipv6.sin6_addr.s6_addr16[6])), + reinterpret_cast(&ip), 4 ); return true; } return false; } +bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr) +{ +#ifdef SS_DEBUG + std::cerr << __PRETTY_FUNCTION__ << std::endl; +#endif + + if ( addr.ss_family == AF_INET ) return true; + + if ( addr.ss_family == AF_INET6 ) + { + sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr; + bool ipv4m = addr_ipv6.sin6_addr.s6_addr16[5] == htons(0xffff); + for ( int i = 0; ipv4m && i < 5 ; ++i ) + ipv4m &= addr_ipv6.sin6_addr.s6_addr16[i] == htons(0x0000); + + if(ipv4m) + { + uint32_t ip; + memmove( reinterpret_cast(&ip), + reinterpret_cast(&(addr_ipv6.sin6_addr.s6_addr16[6])), + 4 ); + uint16_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; + + return true; + } + } + + return false; +} + + /******************************** Comparisions **********************************/ bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b) @@ -397,15 +496,20 @@ std::string sockaddr_storage_tostring(const struct sockaddr_storage &addr) switch(addr.ss_family) { - case AF_INET: - case AF_INET6: - output += "="; - output += sockaddr_storage_iptostring(addr); - output += ":"; - output += sockaddr_storage_porttostring(addr); - break; - default: - break; + case AF_INET: + output += "="; + output += sockaddr_storage_iptostring(addr); + output += ":"; + output += sockaddr_storage_porttostring(addr); + break; + case AF_INET6: + output += "=["; + output += sockaddr_storage_iptostring(addr); + output += "]:"; + output += sockaddr_storage_porttostring(addr); + break; + default: + break; } return output; } @@ -433,7 +537,7 @@ void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputSt { const sockaddr_in6 * in6 = (const sockaddr_in6 *) & addr; std::string addrStr = "INVALID_IPV6"; - rs_inet_ntop(addr, addrStr); + sockaddr_storage_inet_ntop(addr, addrStr); output << "addr.ss_family = AF_INET6"; output << " in6->sin6_addr = "; output << addrStr; @@ -449,7 +553,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputSt const uint8_t * buf = reinterpret_cast(&addr); 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 + /* The unary +buf[i] operation forces a no-op type conversion to an int + * with the correct sign */ } } @@ -477,6 +582,10 @@ std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr) break; default: output = "AF_INVALID"; + std::cerr << __PRETTY_FUNCTION__ << " Got invalid address!" + << std::endl; + sockaddr_storage_dump(addr); + print_stacktrace(); break; } return output; @@ -487,15 +596,18 @@ std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr) std::string output; switch(addr.ss_family) { - case AF_INET: - output = sockaddr_storage_ipv4_iptostring(addr); - break; - case AF_INET6: - output = sockaddr_storage_ipv6_iptostring(addr); - break; - default: - output = "INVALID_IP"; - break; + case AF_INET: + output = sockaddr_storage_ipv4_iptostring(addr); + break; + case AF_INET6: + output = sockaddr_storage_ipv6_iptostring(addr); + break; + default: + output = "INVALID_IP"; + std::cerr << __PRETTY_FUNCTION__ << " Got invalid IP:" << std::endl; + sockaddr_storage_dump(addr); + print_stacktrace(); + break; } return output; } @@ -619,9 +731,7 @@ bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr) 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; + return sockaddr_storage_ipv6_isLinkLocalNet(addr); default: #ifdef SS_DEBUG std::cerr << __PRETTY_FUNCTION__ <<" INVALID Family:" << std::endl; @@ -633,6 +743,16 @@ bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr) return false; } +bool sockaddr_storage_ipv6_isLinkLocalNet(const sockaddr_storage &addr) +{ + if(addr.ss_family != AF_INET6) return false; + + const sockaddr_in6 * addr6 = (const sockaddr_in6 *) &addr; + uint16_t mask = htons(0xffc0); + uint16_t llPrefix = htons(0xfe80); + return ((addr6->sin6_addr.s6_addr16[0] & mask ) == llPrefix); +} + bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr) { @@ -695,6 +815,51 @@ const struct sockaddr_in6 *to_const_ipv6_ptr(const struct sockaddr_storage &addr /******************************** Set / Clear ***********************************/ +bool sockaddr_storage_copy(const sockaddr_storage& src, sockaddr_storage& dst) +{ + if(&src == &dst) return true; + + switch(src.ss_family) + { + case AF_INET: + { + sockaddr_storage_clear(dst); + const sockaddr_in& ins(reinterpret_cast(src)); + sockaddr_in& ind(reinterpret_cast(dst)); + + ind.sin_family = AF_INET; + ind.sin_addr.s_addr = ins.sin_addr.s_addr; + ind.sin_port = ins.sin_port; + + return true; + } + case AF_INET6: + { + sockaddr_storage_clear(dst); + const sockaddr_in6& ins6(reinterpret_cast(src)); + sockaddr_in6& ind6(reinterpret_cast(dst)); + + ind6.sin6_family = AF_INET6; + for(int i=0; i<8; ++i) + ind6.sin6_addr.s6_addr16[i] = ins6.sin6_addr.s6_addr16[i]; + ind6.sin6_flowinfo = ins6.sin6_flowinfo; + ind6.sin6_port = ins6.sin6_port; + ind6.sin6_scope_id = ins6.sin6_scope_id; + + return true; + } + default: +#ifdef SS_DEBUG + std::cerr << __PRETTY_FUNCTION__ << " Attempt to copy unknown family! " + << src.ss_family << " defaulting to memmove!" << std::endl; + sockaddr_storage_dump(src); + print_stacktrace(); +#endif // SS_DEBUG + memmove(&dst, &src, sizeof(sockaddr_storage)); + return true; + } +} + bool sockaddr_storage_ipv4_zeroip(struct sockaddr_storage &addr) { #ifdef SS_DEBUG @@ -917,7 +1082,7 @@ std::string sockaddr_storage_ipv4_iptostring(const struct sockaddr_storage &addr std::string sockaddr_storage_ipv6_iptostring(const struct sockaddr_storage & addr) { std::string addrStr; - rs_inet_ntop(addr, addrStr); + sockaddr_storage_inet_ntop(addr, addrStr); return addrStr; } @@ -1006,62 +1171,58 @@ bool sockaddr_storage_ipv4_isExternalNet(const struct sockaddr_storage &addr) } -bool sockaddr_storage_ipv6_isnull(const struct sockaddr_storage &/*addr*/) +bool sockaddr_storage_ipv6_isnull(const struct sockaddr_storage& addr) { -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_isnull() TODO"; - std::cerr << std::endl; -#endif + const sockaddr_in6& addr6 = reinterpret_cast(addr); - return false; + uint16_t nZero = htons(0); // anyway 0 should be the same in host and net + bool isZero = (addr6.sin6_addr.s6_addr16[7] == nZero); + for (int i=0; isZero && i<7; ++i) + isZero &= (addr6.sin6_addr.s6_addr16[i] == nZero); + + return nZero; } -bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage &/*addr*/) +bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage& addr) { -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_isValidNet() TODO"; - std::cerr << std::endl; -#endif - - return false; + return !sockaddr_storage_ipv6_isnull(addr); } -bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage &/*addr*/) +bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage& addr) { + const sockaddr_in6& addr6 = reinterpret_cast(addr); + bool isLoopBack = (addr6.sin6_addr.s6_addr16[7] == htons(0x0001)); + uint16_t nZero = htons(0); // anyway 0 should be the same in host and net + for (int i=0; isLoopBack && i<7; ++i) + isLoopBack &= (addr6.sin6_addr.s6_addr16[i] == nZero); + #ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_isLoopbackNet() TODO"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " " << sockaddr_storage_tostring(addr) + << " " << isLoopBack << std::endl; #endif - return false; + return isLoopBack; } bool sockaddr_storage_ipv6_isPrivateNet(const struct sockaddr_storage &/*addr*/) { -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_isPrivateNet() TODO"; - std::cerr << std::endl; -#endif + /* It is unlikely that we end up connecting to an IPv6 address behind NAT + * W.R.T. RS it is probably better to consider all IPv6 as internal/local + * addresses as direct connection should be always possible. */ - return false; + return true; } bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &/*addr*/) { -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_isExternalNet() TODO"; - std::cerr << std::endl; -#endif + /* It is unlikely that we end up connecting to an IPv6 address behind NAT + * W.R.T. RS it is probably better to consider all IPv6 as internal/local + * addresses as direct connection should be always possible. */ return false; } -#ifdef WINDOWS_SYS -#include -#include -#endif - -bool rs_inet_ntop (const sockaddr_storage &addr, std::string &dst) +bool sockaddr_storage_inet_ntop (const sockaddr_storage &addr, std::string &dst) { bool success = false; char ipStr[255]; @@ -1098,3 +1259,15 @@ bool rs_inet_ntop (const sockaddr_storage &addr, std::string &dst) dst = ipStr; return success; } + +int rs_setsockopt( int sockfd, int level, int optname, + const uint8_t *optval, uint32_t optlen ) +{ +#ifdef WINDOWS_SYS + return setsockopt( sockfd, level, optname, + reinterpret_cast(optval), optlen ); +#else + return setsockopt( sockfd, level, optname, + reinterpret_cast(optval), optlen ); +#endif // WINDOWS_SYS +} diff --git a/libretroshare/src/util/rsthreads.cc b/libretroshare/src/util/rsthreads.cc index 39eca594a..65fcad4b7 100644 --- a/libretroshare/src/util/rsthreads.cc +++ b/libretroshare/src/util/rsthreads.cc @@ -169,11 +169,14 @@ void RsTickingThread::fullstop() void RsThread::start(const std::string &threadName) { - if(isRunning()) - { - std::cerr << "(EE) RsThread \"" << threadName << "\" is already running. Will not start twice!" << std::endl; - return ; - } + if(isRunning()) + { + std::cerr << "(EE) RsThread \"" << threadName + << "\" is already running. Will not start twice!" + << std::endl; + print_stacktrace(); + return; + } pthread_t tid; void *data = (void *)this ; From 9281a5966bd0b0c5177a528f72e71ca06bf6f17e Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sun, 25 Feb 2018 12:48:55 +0100 Subject: [PATCH 04/10] p3Peers::getPeerDetails retrocompatible IPv4 format --- libretroshare/src/pgp/rscertificate.cc | 14 ++++---- libretroshare/src/rsserver/p3peers.cc | 44 +++++++++++++------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/libretroshare/src/pgp/rscertificate.cc b/libretroshare/src/pgp/rscertificate.cc index 839f646a7..2088f020f 100644 --- a/libretroshare/src/pgp/rscertificate.cc +++ b/libretroshare/src/pgp/rscertificate.cc @@ -174,24 +174,24 @@ RsCertificate::RsCertificate(const RsPeerDetails& Detail, const unsigned char *b try { - scan_ip(Detail.localAddr,Detail.localPort,ipv4_internal_ip_and_port) ; + scan_ip(Detail.localAddr,Detail.localPort,ipv4_internal_ip_and_port); } catch(...) { - std::cerr << "RsCertificate::Invalid LocalAddress"; - std::cerr << std::endl; - memset(ipv4_internal_ip_and_port,0,6) ; + std::cerr << "RsCertificate::Invalid LocalAddress: " + << Detail.localAddr << std::endl; + memset(ipv4_internal_ip_and_port,0,6); } try { - scan_ip(Detail.extAddr,Detail.extPort,ipv4_external_ip_and_port) ; + scan_ip(Detail.extAddr,Detail.extPort,ipv4_external_ip_and_port); } catch(...) { - std::cerr << "RsCertificate::Invalid ExternalAddress"; - std::cerr << std::endl; + std::cerr << "RsCertificate::Invalid ExternalAddress: " + << Detail.extAddr << std::endl; memset(ipv4_external_ip_and_port,0,6) ; } diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index 245a074df..c27943f62 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -333,27 +333,27 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) d.hiddenNodePort = 0; d.hiddenType = RS_HIDDEN_TYPE_NONE; - if (sockaddr_storage_isnull(ps.localaddr)) - { - d.localAddr = "INVALID_IP"; - d.localPort = 0; - } - else + if (sockaddr_storage_ipv6_to_ipv4(ps.localaddr)) { d.localAddr = sockaddr_storage_iptostring(ps.localaddr); d.localPort = sockaddr_storage_port(ps.localaddr); } - - if (sockaddr_storage_isnull(ps.serveraddr)) - { - d.extAddr = "INVALID_IP"; - d.extPort = 0; - } else + { + d.localAddr = "INVALID_IP"; + d.localPort = 0; + } + + if (sockaddr_storage_ipv6_to_ipv4(ps.serveraddr)) { d.extAddr = sockaddr_storage_iptostring(ps.serveraddr); d.extPort = sockaddr_storage_port(ps.serveraddr); } + else + { + d.extAddr = "INVALID_IP"; + d.extPort = 0; + } d.dyndns = ps.dyndns; @@ -1051,22 +1051,22 @@ std::string p3Peers::getPGPKey(const RsPgpId& pgp_id,bool include_signatures) unsigned char *mem_block = NULL; size_t mem_block_size = 0; - if(!AuthGPG::getAuthGPG()->exportPublicKey(RsPgpId(pgp_id),mem_block,mem_block_size,false,include_signatures)) + if( !AuthGPG::getAuthGPG()->exportPublicKey( + RsPgpId(pgp_id), mem_block, mem_block_size, + false, include_signatures ) ) { - std::cerr << "Cannot output certificate for id \"" << pgp_id << "\". Sorry." << std::endl; + std::cerr << "Cannot output certificate for id \"" << pgp_id + << "\". Sorry." << std::endl; return "" ; } - RsPeerDetails Detail ; + RsPeerDetails Detail; + if(!getGPGDetails(pgp_id,Detail)) return ""; - if(!getGPGDetails(pgp_id,Detail) ) - return "" ; + RsCertificate cert( Detail,mem_block,mem_block_size ); + delete[] mem_block ; - RsCertificate cert( Detail,mem_block,mem_block_size ) ; - - delete[] mem_block ; - - return cert.armouredPGPKey() ; + return cert.armouredPGPKey(); } From f5160338ed481713cf5a9877101bfaebd3adde7d Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sun, 25 Feb 2018 13:18:34 +0100 Subject: [PATCH 05/10] sockaddr_storage_familytostring be quite if not debugging --- libretroshare/src/pqi/p3linkmgr.cc | 6 ++++-- libretroshare/src/util/rsnet_ss.cc | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libretroshare/src/pqi/p3linkmgr.cc b/libretroshare/src/pqi/p3linkmgr.cc index d3e2b50d0..94f09f6b9 100644 --- a/libretroshare/src/pqi/p3linkmgr.cc +++ b/libretroshare/src/pqi/p3linkmgr.cc @@ -1345,8 +1345,10 @@ void p3LinkMgrIMPL::peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, } /* This has become very unwieldy - as extra arguments are required for UDP connections */ -void p3LinkMgrIMPL::peerConnectRequest(const RsPeerId& id, const struct sockaddr_storage &raddr, const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) +void p3LinkMgrIMPL::peerConnectRequest( + const RsPeerId& id, const sockaddr_storage &raddr, + const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr, + uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth ) { #ifdef LINKMGR_DEBUG std::cerr << "p3LinkMgrIMPL::peerConnectRequest() id: " << id; diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc index da9ab2dfb..581fd06e9 100644 --- a/libretroshare/src/util/rsnet_ss.cc +++ b/libretroshare/src/util/rsnet_ss.cc @@ -582,10 +582,12 @@ std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr) break; default: output = "AF_INVALID"; +#ifdef SS_DEBUG std::cerr << __PRETTY_FUNCTION__ << " Got invalid address!" << std::endl; sockaddr_storage_dump(addr); print_stacktrace(); +#endif break; } return output; From ac8b56951ccb6a4398c102010141521d983759c7 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 26 Feb 2018 08:49:06 +0100 Subject: [PATCH 06/10] Enforce main IPv4 usage for better retrocompatibility --- libretroshare/src/pqi/p3netmgr.cc | 131 ++++++++++++++---------------- libretroshare/src/pqi/p3peermgr.h | 21 +++-- 2 files changed, 72 insertions(+), 80 deletions(-) diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 54b6415cd..7ca1713f7 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -692,11 +692,11 @@ void p3NetMgrIMPL::netExtCheck() bool netSetupDone = false; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); bool isStable = false; - struct sockaddr_storage tmpip ; + sockaddr_storage tmpip; - std::map address_votes ; + std::map address_votes; /* check for External Address */ /* in order of importance */ @@ -705,38 +705,30 @@ void p3NetMgrIMPL::netExtCheck() #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok" << std::endl; #endif - /* net Assist */ - if (netAssistExtAddress(tmpip)) + if ( netAssistExtAddress(tmpip) && + sockaddr_storage_isValidNet(tmpip) && + sockaddr_storage_ipv6_to_ipv4(tmpip) ) { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied from netAssistExternalAddress()" << std::endl; -#endif - if(sockaddr_storage_isValidNet(tmpip)) + if( !rsBanList || + rsBanList->isAddressAccepted( + tmpip, RSBANLIST_CHECKING_FLAGS_BLACKLIST ) ) { - if( (rsBanList==NULL) || rsBanList->isAddressAccepted(tmpip,RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - // must be stable??? - isStable = true; - //mNetFlags.mExtAddr = tmpip; - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = isStable; - - address_votes[tmpip].n++ ; - - std::cerr << "NetAssistAddress reported external address " << sockaddr_storage_iptostring(tmpip) << std::endl; - } - else - std::cerr << "(SS) netAssisExternalAddress returned banned own IP " << sockaddr_storage_iptostring(tmpip) << " (banned). Rejecting." << std::endl; + // must be stable??? + isStable = true; + mNetFlags.mExtAddrOk = true; + mNetFlags.mExtAddrStableOk = isStable; + address_votes[tmpip].n++ ; + std::cerr << __PRETTY_FUNCTION__ << " NetAssistAddress " + << " reported external address " + << sockaddr_storage_iptostring(tmpip) + << std::endl; } -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) else - { - std::cerr << "p3NetMgrIMPL::netExtCheck() Bad Address supplied from netAssistExternalAddress()" << std::endl; - } -#endif + std::cerr << "(SS) netAssisExternalAddress returned banned " + << "own IP " << sockaddr_storage_iptostring(tmpip) + << " (banned). Rejecting." << std::endl; } - } #ifdef ALLOW_DHT_STUNNER @@ -780,7 +772,7 @@ void p3NetMgrIMPL::netExtCheck() } #endif - /* otherwise ask ExtAddrFinder */ + /* ask ExtAddrFinder */ { /* ExtAddrFinder */ if (mUseExtAddrFinder) @@ -789,7 +781,7 @@ void p3NetMgrIMPL::netExtCheck() std::cerr << "p3NetMgrIMPL::netExtCheck() checking ExtAddrFinder" << std::endl; #endif bool extFinderOk = mExtAddrFinder->hasValidIP(tmpip); - if (extFinderOk) + if (extFinderOk && sockaddr_storage_ipv6_to_ipv4(tmpip)) { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; @@ -803,38 +795,41 @@ void p3NetMgrIMPL::netExtCheck() std::cerr << std::endl; #endif - //mNetFlags.mExtAddr = tmpip; mNetFlags.mExtAddrOk = true; address_votes[tmpip].n++ ; - /* XXX HACK TO FIX */ -#warning drbob: ALLOWING ExtAddrFinder -> ExtAddrStableOk = true (which it is not normally) + /* XXX HACK TO FIX drbob: ALLOWING + * ExtAddrFinder -> ExtAddrStableOk = true + * (which it is not normally) */ mNetFlags.mExtAddrStableOk = true; - - std::cerr << "ExtAddrFinder reported external address " << sockaddr_storage_iptostring(tmpip) << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " ExtAddrFinder " + << " reported external address " + << sockaddr_storage_iptostring(tmpip) + << std::endl; } } } - - /* also ask peer mgr. */ - + + /* also ask peer mgr. */ if (mPeerMgr) { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) std::cerr << "p3NetMgrIMPL::netExtCheck() checking mPeerMgr" << std::endl; #endif - uint8_t isstable ; // unused - sockaddr_storage tmpaddr ; + uint8_t isstable; // unused + sockaddr_storage tmpaddr; - if (mPeerMgr->getExtAddressReportedByFriends(tmpaddr, isstable)) + if ( mPeerMgr->getExtAddressReportedByFriends(tmpaddr, isstable) && + sockaddr_storage_ipv6_to_ipv4(tmpaddr) ) { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; #endif /* best guess at port */ - sockaddr_storage_setport(tmpaddr, sockaddr_storage_port(mLocalAddr)); + sockaddr_storage_setport( tmpaddr, + sockaddr_storage_port(mLocalAddr) ); #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) std::cerr << "p3NetMgrIMPL::netExtCheck() "; @@ -842,20 +837,21 @@ void p3NetMgrIMPL::netExtCheck() std::cerr << std::endl; #endif - //mNetFlags.mExtAddr = tmpaddr; mNetFlags.mExtAddrOk = true; mNetFlags.mExtAddrStableOk = isstable; - address_votes[tmpaddr].n++ ; - - std::cerr << "PeerMgr reported external address " << sockaddr_storage_iptostring(tmpaddr) << std::endl; + address_votes[tmpaddr].n++; + + std::cerr << __PRETTY_FUNCTION__ << " PeerMgr reported external" + << " address " + << sockaddr_storage_iptostring(tmpaddr) << std::endl; } #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - else - std::cerr << " No reliable address returned." << std::endl; + else + std::cerr << " No reliable address returned." << std::endl; #endif } - + /* any other sources ??? */ /* finalise address */ @@ -950,14 +946,6 @@ void p3NetMgrIMPL::netExtCheck() #endif netAssistSetAddress(mNetFlags.mLocalAddr, mNetFlags.mExtAddr, mNetMode); } -#if 0 - else - { - std::cerr << "p3NetMgrIMPL::netExtCheck() setting ERR netAssistSetAddress(0)" << std::endl; - /* mode = 0 for error */ - netAssistSetAddress(mNetFlags.mLocalAddr, mNetFlags.mExtAddr, mNetMode); - } -#endif /* flag unreachables! */ if ((mNetFlags.mExtAddrOk) && (!mNetFlags.mExtAddrStableOk)) @@ -966,9 +954,6 @@ void p3NetMgrIMPL::netExtCheck() std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Unstable - Unreachable Check" << std::endl; #endif } - - - } if (netSetupDone) @@ -988,9 +973,9 @@ void p3NetMgrIMPL::netExtCheck() RsPeerId fakeId; netAssistKnownPeer(fakeId, mExtAddr, NETASSIST_KNOWN_PEER_SELF | NETASSIST_KNOWN_PEER_ONLINE); - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::netExtCheck() Network Setup Complete"); + std::cerr << __PRETTY_FUNCTION__ << " Network Setup Complete" + << std::endl; } - } /********************************************************************************************** @@ -1021,6 +1006,9 @@ bool p3NetMgrIMPL::checkNetAddress() * possible. It will require complete reenginering of the network layer * code. */ + /* For retro-compatibility strictly accept only IPv4 addresses here, + * IPv6 addresses are handled in a retro-compatible manner in + * p3PeerMgrIMPL::UpdateOwnAddress */ std::vector addrs; if (getLocalAddresses(addrs)) { @@ -1029,7 +1017,8 @@ bool p3NetMgrIMPL::checkNetAddress() sockaddr_storage& addr(*it); if( sockaddr_storage_isValidNet(addr) && !sockaddr_storage_isLoopbackNet(addr) && - !sockaddr_storage_isLinkLocalNet(addr)) + !sockaddr_storage_isLinkLocalNet(addr) && + sockaddr_storage_ipv6_to_ipv4(addr) ) { prefAddr = addr; validAddr = true; @@ -1038,15 +1027,13 @@ bool p3NetMgrIMPL::checkNetAddress() } /* If no satisfactory local address has been found yet relax and - * accept also IPv4 link local addresses, IPv6 link local is not - * accepted because of sin6_scope_id that depends on the host using - * it as an outgoing connection endpoint */ + * 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) && - !sockaddr_storage_ipv6_isLinkLocalNet(addr) ) + sockaddr_storage_ipv6_to_ipv4(addr) ) { prefAddr = addr; validAddr = true; @@ -1072,7 +1059,7 @@ bool p3NetMgrIMPL::checkNetAddress() /* check addresses */ { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); oldAddr = mLocalAddr; addrChanged = !sockaddr_storage_sameip(prefAddr, mLocalAddr); @@ -1174,8 +1161,10 @@ bool p3NetMgrIMPL::checkNetAddress() { mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); } - - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::checkNetAddress() local address changed, resetting network"); + + std::cerr << __PRETTY_FUNCTION__ + << " local address changed, resetting network" << std::endl; + netReset(); } diff --git a/libretroshare/src/pqi/p3peermgr.h b/libretroshare/src/pqi/p3peermgr.h index 8fa73cf78..55d99b569 100644 --- a/libretroshare/src/pqi/p3peermgr.h +++ b/libretroshare/src/pqi/p3peermgr.h @@ -119,17 +119,20 @@ class p3NetMgrIMPL; class p3PeerMgr { - public: +public: - p3PeerMgr() { return; } -virtual ~p3PeerMgr() { return; } + p3PeerMgr() {} + virtual ~p3PeerMgr() {} -virtual bool addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id, uint32_t netMode = RS_NET_MODE_UDP, - uint16_t vsDisc = RS_VS_DISC_FULL, uint16_t vsDht = RS_VS_DHT_FULL, - time_t lastContact = 0,ServicePermissionFlags = ServicePermissionFlags(RS_NODE_PERM_DEFAULT)) = 0; -virtual bool removeFriend(const RsPeerId &ssl_id, bool removePgpId) = 0; + virtual bool addFriend( const RsPeerId &ssl_id, const RsPgpId &gpg_id, + uint32_t netMode = RS_NET_MODE_UDP, + uint16_t vsDisc = RS_VS_DISC_FULL, + uint16_t vsDht = RS_VS_DHT_FULL, + time_t lastContact = 0, + ServicePermissionFlags = ServicePermissionFlags(RS_NODE_PERM_DEFAULT) ) = 0; -virtual bool isFriend(const RsPeerId& ssl_id) = 0; + virtual bool removeFriend(const RsPeerId &ssl_id, bool removePgpId) = 0; + virtual bool isFriend(const RsPeerId& ssl_id) = 0; virtual bool getAssociatedPeers(const RsPgpId &gpg_id, std::list &ids) = 0; virtual bool removeAllFriendLocations(const RsPgpId &gpgid) = 0; @@ -146,7 +149,7 @@ virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo &gr virtual bool getGroupInfoList(std::list &groupInfoList) = 0; virtual bool assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign) = 0; - virtual bool resetOwnExternalAddressList() = 0 ; + virtual bool resetOwnExternalAddressList() = 0 ; virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) =0; virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) =0; From f4a60901505f2ffab9591730e150d9d54bd01741 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 26 Feb 2018 15:55:20 +0100 Subject: [PATCH 07/10] More ipv6_to_ipv4 conversions --- libretroshare/src/pqi/p3peermgr.cc | 30 +++++++++++---------------- libretroshare/src/pqi/p3peermgr.h | 6 +++--- libretroshare/src/rsserver/p3peers.cc | 7 +++++-- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/libretroshare/src/pqi/p3peermgr.cc b/libretroshare/src/pqi/p3peermgr.cc index f275170d6..bd1b40528 100644 --- a/libretroshare/src/pqi/p3peermgr.cc +++ b/libretroshare/src/pqi/p3peermgr.cc @@ -331,8 +331,8 @@ const RsPeerId& p3PeerMgrIMPL::getOwnId() bool p3PeerMgrIMPL::getOwnNetStatus(peerState &state) { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - state = mOwnState; + RS_STACK_MUTEX(mPeerMtx); + state = mOwnState; return true; } @@ -817,15 +817,12 @@ int p3PeerMgrIMPL::getFriendCount(bool ssl, bool online) bool p3PeerMgrIMPL::getFriendNetStatus(const RsPeerId &id, peerState &state) { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mPeerMtx); /* check for existing */ std::map::iterator it; it = mFriendList.find(id); - if (it == mFriendList.end()) - { - return false; - } + if (it == mFriendList.end()) return false; state = it->second; return true; @@ -834,27 +831,24 @@ bool p3PeerMgrIMPL::getFriendNetStatus(const RsPeerId &id, peerState &state) bool p3PeerMgrIMPL::getOthersNetStatus(const RsPeerId &id, peerState &state) { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mPeerMtx); /* check for existing */ std::map::iterator it; it = mOthersList.find(id); - if (it == mOthersList.end()) - { - return false; - } + if (it == mOthersList.end()) return false; state = it->second; return true; } -int p3PeerMgrIMPL::getConnectAddresses(const RsPeerId &id, - struct sockaddr_storage &lAddr, struct sockaddr_storage &eAddr, - pqiIpAddrSet &histAddrs, std::string &dyndns) +int p3PeerMgrIMPL::getConnectAddresses( + const RsPeerId &id, sockaddr_storage &lAddr, sockaddr_storage &eAddr, + pqiIpAddrSet &histAddrs, std::string &dyndns ) { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - + RS_STACK_MUTEX(mPeerMtx); + /* check for existing */ std::map::iterator it; it = mFriendList.find(id); @@ -865,7 +859,7 @@ int p3PeerMgrIMPL::getConnectAddresses(const RsPeerId &id, std::cerr << std::endl; return 0; } - + lAddr = it->second.localaddr; eAddr = it->second.serveraddr; histAddrs = it->second.ipAddrs; diff --git a/libretroshare/src/pqi/p3peermgr.h b/libretroshare/src/pqi/p3peermgr.h index 55d99b569..8a0ac5235 100644 --- a/libretroshare/src/pqi/p3peermgr.h +++ b/libretroshare/src/pqi/p3peermgr.h @@ -357,9 +357,9 @@ public: bool setOwnNetworkMode(uint32_t netMode); bool setOwnVisState(uint16_t vs_disc, uint16_t vs_dht); - int getConnectAddresses(const RsPeerId &id, - struct sockaddr_storage &lAddr, struct sockaddr_storage &eAddr, - pqiIpAddrSet &histAddrs, std::string &dyndns); + int getConnectAddresses( const RsPeerId &id, sockaddr_storage &lAddr, + sockaddr_storage &eAddr, pqiIpAddrSet &histAddrs, + std::string &dyndns ); protected: diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index c27943f62..9f0d7d73d 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -333,8 +333,9 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) d.hiddenNodePort = 0; d.hiddenType = RS_HIDDEN_TYPE_NONE; - if (sockaddr_storage_ipv6_to_ipv4(ps.localaddr)) + if(!sockaddr_storage_isnull(ps.localaddr)) { + sockaddr_storage_ipv6_to_ipv4(ps.localaddr); d.localAddr = sockaddr_storage_iptostring(ps.localaddr); d.localPort = sockaddr_storage_port(ps.localaddr); } @@ -344,8 +345,9 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) d.localPort = 0; } - if (sockaddr_storage_ipv6_to_ipv4(ps.serveraddr)) + if(!sockaddr_storage_isnull(ps.serveraddr)) { + sockaddr_storage_ipv6_to_ipv4(ps.serveraddr); d.extAddr = sockaddr_storage_iptostring(ps.serveraddr); d.extPort = sockaddr_storage_port(ps.serveraddr); } @@ -417,6 +419,7 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) if (pcs.state & RS_PEER_S_CONNECTED) { + sockaddr_storage_ipv6_to_ipv4(pcs.connectaddr); d.connectAddr = sockaddr_storage_iptostring(pcs.connectaddr); d.connectPort = sockaddr_storage_port(pcs.connectaddr); } From 7d765ec04edef46c995483a94dc3b905a226e57c Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 26 Feb 2018 16:30:27 +0100 Subject: [PATCH 08/10] pqissl::Initiate_Connection remove duplicated code --- libretroshare/src/pqi/pqissl.cc | 82 ++++++++------------------------- 1 file changed, 20 insertions(+), 62 deletions(-) diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index d549e9542..48186b755 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -577,33 +577,28 @@ int pqissl::Delay_Connection() } rslog(RSL_WARNING, pqisslzone, - "pqissl::Initiate_Connection() Already Attempt in Progress!"); + "pqissl::Delay_Connection() Already Attempt in Progress!"); return -1; } int pqissl::Initiate_Connection() { - int err; - struct sockaddr_storage addr = remote_addr; - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_Connection() Attempting Outgoing Connection...."); +#ifdef PQISSL_DEBUG + std::cout << __PRETTY_FUNCTION__ << std::endl; #endif - if (waiting != WAITING_DELAY) + int err; + sockaddr_storage addr = remote_addr; + + + if(waiting != WAITING_DELAY) { - rslog(RSL_WARNING, pqisslzone, - "pqissl::Initiate_Connection() Already Attempt in Progress!"); + std::cerr << __PRETTY_FUNCTION__ << " Already Attempt in Progress!" + << std::endl; return -1; } -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_Connection() Opening Socket"); -#endif - // open socket connection to addr. int osock = unix_socket(PF_INET6, SOCK_STREAM, 0); @@ -631,7 +626,7 @@ int pqissl::Initiate_Connection() "pqissl::Initiate_Connection() Making Non-Blocking"); #endif - err = unix_fcntl_nonblock(osock); + err = unix_fcntl_nonblock(osock); if (err < 0) { std::string out; @@ -728,61 +723,24 @@ int pqissl::Initiate_Connection() sockaddr_storage_ipv4_to_ipv6(addr); if (0 != (err = unix_connect(osock, addr))) { - std::string out; - rs_sprintf(out, "pqissl::Initiate_Connection() connect returns:%d -> errno: %d error: %s\n", err, errno, socket_errorType(errno).c_str()); - - if (errno == EINPROGRESS) + switch (errno) { - // set state to waiting..... + case EINPROGRESS: waiting = WAITING_SOCK_CONNECT; sockfd = osock; - -#ifdef PQISSL_LOG_DEBUG - out += " EINPROGRESS Waiting for Socket Connection"; - rslog(RSL_DEBUG_BASIC, pqisslzone, out); -#endif - return 0; - } - else if ((errno == ENETUNREACH) || (errno == ETIMEDOUT)) - { - out += "ENETUNREACHABLE: cert: " + PeerId().toStdString(); - rslog(RSL_WARNING, pqisslzone, out); + default: + std::cerr << __PRETTY_FUNCTION__ << " Failure connect " + << sockaddr_storage_tostring(addr) + << " returns: " + << err << " -> errno: " << errno << " " + << socket_errorType(errno) << std::endl; - // Then send unreachable message. net_internal_close(osock); - osock=-1; - //reset(); - + osock = -1; waiting = WAITING_FAIL_INTERFACE; - return -1; } - - /* IF we get here ---- we Failed for some other reason. - * Should abandon this interface - * Known reasons to get here: EINVAL (bad address) - */ - - rs_sprintf_append(out, "Error: Connection Failed: %d - %s", errno, socket_errorType(errno).c_str()); - - net_internal_close(osock); - osock=-1; - waiting = WAITING_FAIL_INTERFACE; - - rslog(RSL_WARNING, pqisslzone, out); - - // extra output for the moment. - std::cerr << out; - - return -1; - } - else - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Init_Connection() connect returned 0"); -#endif } waiting = WAITING_SOCK_CONNECT; From dedfcb2b603da0f03547b7bb0c63164f10558f76 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 26 Feb 2018 17:11:54 +0100 Subject: [PATCH 09/10] More ipv6 to ipv4 conversion around More safe sockaddr_storage copy --- libretroshare/src/pqi/p3peermgr.cc | 37 +++++++++++++++++---------- libretroshare/src/rsserver/p3peers.cc | 4 +-- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/libretroshare/src/pqi/p3peermgr.cc b/libretroshare/src/pqi/p3peermgr.cc index bd1b40528..1927b457e 100644 --- a/libretroshare/src/pqi/p3peermgr.cc +++ b/libretroshare/src/pqi/p3peermgr.cc @@ -1226,9 +1226,17 @@ void p3PeerMgrIMPL::printPeerLists(std::ostream &out) * as it doesn't call back to there. */ -bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& localAddr, - const sockaddr_storage& extAddr ) +bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& pLocalAddr, + const sockaddr_storage& pExtAddr ) { + sockaddr_storage localAddr; + sockaddr_storage_copy(pLocalAddr, localAddr); + sockaddr_storage_ipv6_to_ipv4(localAddr); + + sockaddr_storage extAddr; + sockaddr_storage_copy(pExtAddr, extAddr); + sockaddr_storage_ipv6_to_ipv4(extAddr); + #ifdef PEER_DEBUG std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress(" << sockaddr_storage_tostring(localAddr) << ", " @@ -1251,7 +1259,7 @@ bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& localAddr, //update ip address list pqiIpAddress ipAddressTimed; - ipAddressTimed.mAddr = localAddr; + sockaddr_storage_copy(localAddr, ipAddressTimed.mAddr); ipAddressTimed.mSeenTime = time(NULL); ipAddressTimed.mSrc = 0; mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed); @@ -1284,6 +1292,7 @@ bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& localAddr, * networking stack */ !sockaddr_storage_ipv6_isLinkLocalNet(addr) ) { + sockaddr_storage_ipv6_to_ipv4(addr); pqiIpAddress pqiIp; sockaddr_storage_clear(pqiIp.mAddr); pqiIp.mAddr.ss_family = addr.ss_family; @@ -1299,19 +1308,19 @@ bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& localAddr, } } - mOwnState.localaddr = localAddr; + sockaddr_storage_copy(mOwnState.localaddr, localAddr); } { RS_STACK_MUTEX(mPeerMtx); - //update ip address list - pqiIpAddress ipAddressTimed; - ipAddressTimed.mAddr = extAddr; - ipAddressTimed.mSeenTime = time(NULL); - ipAddressTimed.mSrc = 0 ; - mOwnState.ipAddrs.updateExtAddrs(ipAddressTimed); + //update ip address list + pqiIpAddress ipAddressTimed; + sockaddr_storage_copy(extAddr, ipAddressTimed.mAddr); + ipAddressTimed.mSeenTime = time(NULL); + ipAddressTimed.mSrc = 0; + mOwnState.ipAddrs.updateExtAddrs(ipAddressTimed); /* Attempted Fix to MANUAL FORWARD Mode.... * don't update the server address - if we are in this mode @@ -1331,8 +1340,8 @@ bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& localAddr, std::cerr << std::endl; } 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 << " as MANUAL FORWARD Mode"; @@ -1342,8 +1351,8 @@ bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& localAddr, std::cerr << std::endl; } else - { - mOwnState.serveraddr = extAddr; + { + sockaddr_storage_copy(extAddr, mOwnState.serveraddr); } } diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index 9f0d7d73d..52f6c3dba 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -363,16 +363,16 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) for(it = ps.ipAddrs.mLocal.mAddrs.begin(); it != ps.ipAddrs.mLocal.mAddrs.end(); ++it) { + sockaddr_storage_ipv6_to_ipv4(it->mAddr); std::string toto; - toto += "L:"; toto += sockaddr_storage_tostring(it->mAddr); rs_sprintf_append(toto, " %ld sec", time(NULL) - it->mSeenTime); d.ipAddressList.push_back(toto); } for(it = ps.ipAddrs.mExt.mAddrs.begin(); it != ps.ipAddrs.mExt.mAddrs.end(); ++it) { + sockaddr_storage_ipv6_to_ipv4(it->mAddr); std::string toto; - toto += "E:"; toto += sockaddr_storage_tostring(it->mAddr); rs_sprintf_append(toto, " %ld sec", time(NULL) - it->mSeenTime); d.ipAddressList.push_back(toto); From 52ef72d7614f23fd398b0b203267fe16020adb95 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sat, 3 Mar 2018 01:39:50 +0100 Subject: [PATCH 10/10] Fix p3PeerMgrIMPL::UpdateOwnAddress local address Due to a regression introduced in dedfcb2b603da0f03547b7bb0c63164f10558f76 the local address was not updated correctly causing part of RS networking being stuck and printing lot of invalid sockaddr_storage messages, this commit fix the regression --- libretroshare/src/pqi/p3peermgr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretroshare/src/pqi/p3peermgr.cc b/libretroshare/src/pqi/p3peermgr.cc index 1927b457e..3b81d903d 100644 --- a/libretroshare/src/pqi/p3peermgr.cc +++ b/libretroshare/src/pqi/p3peermgr.cc @@ -1308,7 +1308,7 @@ bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& pLocalAddr, } } - sockaddr_storage_copy(mOwnState.localaddr, localAddr); + sockaddr_storage_copy(localAddr, mOwnState.localaddr); }