From a09db6717b551d1f9c0fb48352c02086031a7d81 Mon Sep 17 00:00:00 2001 From: Phenom Date: Sat, 25 Apr 2020 12:55:45 +0200 Subject: [PATCH 1/4] Add ability to retrieve External IP using DNS server. IPV6 compatible. --- libretroshare/src/util/dnsresolver.cc | 2 - libretroshare/src/util/extaddrfinder.cc | 147 +------- libretroshare/src/util/rsdebug.cc | 49 +++ libretroshare/src/util/rsdebug.h | 44 +++ libretroshare/src/util/rsnet.cc | 326 ++++++++++++++++++ libretroshare/src/util/rsnet.h | 6 + libretroshare/src/util/rsnet_ss.cc | 2 + retroshare-gui/src/gui/settings/ServerPage.ui | 3 + 8 files changed, 444 insertions(+), 135 deletions(-) diff --git a/libretroshare/src/util/dnsresolver.cc b/libretroshare/src/util/dnsresolver.cc index 3b68a052e..7ce9edee6 100644 --- a/libretroshare/src/util/dnsresolver.cc +++ b/libretroshare/src/util/dnsresolver.cc @@ -41,8 +41,6 @@ const rstime_t MAX_TIME_BEFORE_RETRY = 300 ; /* seconds before retrying an ip address */ const rstime_t MAX_KEEP_DNS_ENTRY = 3600 ; /* seconds during which a DNS entry is considered valid */ -static const std::string ADDR_AGENT = "Mozilla/5.0"; - void *solveDNSEntries(void *p) { bool more_to_go = true ; diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc index b214dc779..6c281a74a 100644 --- a/libretroshare/src/util/extaddrfinder.cc +++ b/libretroshare/src/util/extaddrfinder.cc @@ -38,132 +38,10 @@ #include #include "util/rstime.h" -const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ +const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ //#define EXTADDRSEARCH_DEBUG -static const std::string ADDR_AGENT = "Mozilla/5.0"; - -static std::string scan_ip(const std::string& text) -{ - std::set digits ; - digits.insert('0') ; digits.insert('3') ; digits.insert('6') ; - digits.insert('1') ; digits.insert('4') ; digits.insert('7') ; - digits.insert('2') ; digits.insert('5') ; digits.insert('8') ; - digits.insert('9') ; - - for(int i=0;i<(int)text.size();++i) - { - while(i < (int)text.size() && digits.find(text[i])==digits.end()) ++i ; - - if(i>=(int)text.size()) - return "" ; - - unsigned int a,b,c,d ; - - if(sscanf(text.c_str()+i,"%u.%u.%u.%u",&a,&b,&c,&d) != 4) - continue ; - - if(a < 256 && b<256 && c<256 && d<256) - { - std::string s ; - rs_sprintf(s, "%u.%u.%u.%u", a, b, c, d) ; - return s; - } - } - return "" ; -} - -static void getPage(const std::string& server_name,std::string& page) -{ - page = "" ; - int sockfd,n=0; // socket descriptor - struct sockaddr_in serveur; // server's parameters - memset(&serveur.sin_zero, 0, sizeof(serveur.sin_zero)); - - char buf[1024]; - char request[1024]; -#ifdef EXTADDRSEARCH_DEBUG - std::cout << "ExtAddrFinder: connecting to " << server_name << std::endl ; -#endif - // socket creation - - sockfd = unix_socket(PF_INET,SOCK_STREAM,0); - if (sockfd < 0) - { - std::cerr << "ExtAddrFinder: Failed to create socket" << std::endl; - return ; - } - - serveur.sin_family = AF_INET; - - // get server's ipv4 adress - - in_addr in ; - - if(!rsGetHostByName(server_name.c_str(),in)) /* l'hôte n'existe pas */ - { - std::cerr << "ExtAddrFinder: Unknown host " << server_name << std::endl; - unix_close(sockfd); - return ; - } - serveur.sin_addr = in ; - serveur.sin_port = htons(80); - -#ifdef EXTADDRSEARCH_DEBUG - printf("Connection attempt\n"); -#endif - std::cerr << "ExtAddrFinder: resolved hostname " << server_name << " to " << rs_inet_ntoa(in) << std::endl; - - 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); - return ; - } -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Connection established to " << server_name << std::endl ; -#endif - - // envoi - if(snprintf( request, - 1024, - "GET / HTTP/1.0\r\n" - "Host: %s:%d\r\n" - "Connection: Close\r\n" - "\r\n", - server_name.c_str(), 80) > 1020) - { - std::cerr << "ExtAddrFinder: buffer overrun. The server name \"" << server_name << "\" is too long. This is quite unexpected." << std::endl; - unix_close(sockfd); - return ; - } - - if(send(sockfd,request,strlen(request),0)== -1) - { - std::cerr << "ExtAddrFinder: Could not send request to " << server_name << std::endl ; - unix_close(sockfd); - return ; - } - // recéption - - while((n = recv(sockfd, buf, sizeof buf - 1, 0)) > 0) - { - buf[n] = '\0'; - page += std::string(buf,n) ; - } - // fermeture de la socket - - unix_close(sockfd); -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Got full page from " << server_name << std::endl ; -#endif -} - - void* doExtAddrSearch(void *p) { @@ -173,15 +51,12 @@ void* doExtAddrSearch(void *p) for(std::list::const_iterator it(af->_ip_servers.begin());it!=af->_ip_servers.end();++it) { - std::string page ; - - getPage(*it,page) ; - std::string ip = scan_ip(page) ; - + std::string ip = ""; + rsGetHostByNameSpecDNS(*it,"myip.opendns.com",ip); if(ip != "") res.push_back(ip) ; #ifdef EXTADDRSEARCH_DEBUG - std::cout << "ip found through " << *it << ": \"" << ip << "\"" << std::endl ; + std::cout << "ip found through DNS " << *it << ": \"" << ip << "\"" << std::endl ; #endif } @@ -315,9 +190,15 @@ ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder") mFoundTS = time(NULL) - MAX_IP_STORE; sockaddr_storage_clear(mAddr); - _ip_servers.push_back(std::string( "checkip.dyndns.org" )) ; - _ip_servers.push_back(std::string( "www.myip.dk" )) ; - _ip_servers.push_back(std::string( "showip.net" )) ; - _ip_servers.push_back(std::string( "www.displaymyip.com")) ; +//https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script + //Enter direct ip so local DNS cannot change it. + //DNS servers must recognize "myip.opendns.com" + _ip_servers.push_back(std::string( "208.67.222.222" )) ;//resolver1.opendns.com + _ip_servers.push_back(std::string( "208.67.220.220" )) ;//resolver2.opendns.com + _ip_servers.push_back(std::string( "208.67.222.220" )) ;//resolver3.opendns.com + _ip_servers.push_back(std::string( "208.67.220.222" )) ;//resolver4.opendns.com + //Ipv6 server disabled as Current ip only manage ipv4 for now. + //_ip_servers.push_back(std::string( "2620:119:35::35" )) ;//resolver1.opendns.com + //_ip_servers.push_back(std::string( "2620:119:53::53" )) ;//resolver2.opendns.com } diff --git a/libretroshare/src/util/rsdebug.cc b/libretroshare/src/util/rsdebug.cc index ac121bca3..2bf093c27 100644 --- a/libretroshare/src/util/rsdebug.cc +++ b/libretroshare/src/util/rsdebug.cc @@ -40,6 +40,51 @@ std::error_condition rs_errno_to_condition(int errno_code) { return std::make_error_condition(static_cast(errno_code)); } +std::ostream& hex_dump(std::ostream& os, const void *buffer, + std::size_t bufsize, bool showPrintableChars /*= true*/) +{ + if (buffer == nullptr) { + return os; + } + auto oldFormat = os.flags(); + auto oldFillChar = os.fill(); + constexpr std::size_t maxline{8}; + // create a place to store text version of string + char renderString[maxline+1]; + char *rsptr{renderString}; + // convenience cast + const unsigned char *buf{reinterpret_cast(buffer)}; + + for (std::size_t linecount=maxline; bufsize; --bufsize, ++buf) { + os << std::setw(2) << std::setfill('0') << std::hex + << static_cast(*buf) << ' '; + *rsptr++ = std::isprint(*buf) ? *buf : '.'; + if (--linecount == 0) { + *rsptr++ = '\0'; // terminate string + if (showPrintableChars) { + os << " | " << renderString; + } + os << '\n'; + rsptr = renderString; + linecount = std::min(maxline, bufsize); + } + } + // emit newline if we haven't already + if (rsptr != renderString) { + if (showPrintableChars) { + for (*rsptr++ = '\0'; rsptr != &renderString[maxline+1]; ++rsptr) { + os << " "; + } + os << " | " << renderString; + } + os << '\n'; + } + + os.fill(oldFillChar); + os.flags(oldFormat); + return os; +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -211,3 +256,7 @@ void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg lineCount++; } } +/// All the lines before are DEPRECATED!! +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// diff --git a/libretroshare/src/util/rsdebug.h b/libretroshare/src/util/rsdebug.h index e37e3070f..cb5e1748e 100644 --- a/libretroshare/src/util/rsdebug.h +++ b/libretroshare/src/util/rsdebug.h @@ -318,3 +318,47 @@ void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg #define PQL_DEBUG_ALERT RSL_DEBUG_ALERT #define PQL_DEBUG_BASIC RSL_DEBUG_BASIC #define PQL_DEBUG_ALL RSL_DEBUG_ALL + +//From https://codereview.stackexchange.com/a/165162 +/** + * @brief hex_dump: Send Hexadecimal Dump to stream + * @param os: Output Stream + * @param buffer: Buffer to send + * @param bufsize: Buffer's size + * @param showPrintableChars: If must send printable Char too + * @return + * basic string: + * 61 62 63 64 65 66 31 32 | abcdef12 + * 33 34 35 36 00 7a 79 78 | 3456.zyx + * 77 76 75 39 38 37 36 35 | wvu98765 + * 34 45 64 77 61 72 64 00 | 4Edward. + * + * wide string: + * 41 00 00 00 20 00 00 00 | A... ... + * 77 00 00 00 69 00 00 00 | w...i... + * 64 00 00 00 65 00 00 00 | d...e... + * 20 00 00 00 73 00 00 00 | ...s... + * 74 00 00 00 72 00 00 00 | t...r... + * 69 00 00 00 6e 00 00 00 | i...n... + * 67 00 00 00 2e 00 00 00 | g....... + * + * a double + * 49 92 24 49 92 24 09 40 | I.$I.$.@ + */ +std::ostream& hex_dump(std::ostream& os, const void *buffer, + std::size_t bufsize, bool showPrintableChars = true); + +/** + * @brief The hexDump struct + * Enable to print dump calling like that: + * const char test[] = "abcdef123456\0zyxwvu987654Edward"; + * RsDbg()< 256 chars:"< 256) + { + RsErr()<<__PRETTY_FUNCTION__<<": hostname is too long > 256 chars:"<id = static_cast(htons(getpid())); //Transaction Id + //dns flags = 0x0100 Standard Query + dns->qr = 0; //Query/Response: Message is a query + dns->opcode = 0; //OpCode: Standard query + dns->aa = 0; //Authoritative: Server is not an authority for domain + dns->tc = 0; //TrunCated: Message is not truncated + dns->rd = 1; //Recursion Desired: Do query recursively + dns->ra = 0; //Recursion Available: Server cannot do recursive queries + dns->z = 0; //Z: reserved + dns->ad = 0; //Authentic Data: Answer/authority portion was not authenticated by the server + dns->cd = 0; //Checking Disabled: Unacceptable + dns->rcode = 0; //Response Code: No error + + dns->q_count = htons(1); //1 Question + dns->ans_count = 0; //0 Answer + dns->auth_count = 0; //0 Authority RRs + dns->add_count = 0; //0 Additional RRs + size_t curSendSize = sizeof(struct DNS_HEADER); + + //Point to the query server name portion + unsigned char* qname =static_cast(&buf[curSendSize]); + //First byte is Label Type: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-10 + qname[0] = 0x04; //One Label with Normal label lower 6 bits is the length of the label + memcpy(&qname[1],hostname.c_str(),strlen(hostname.c_str())); + size_t qnameSize = strlen((const char*)qname); + // Format Hostname like www.google.com to 3www6google3com + { + size_t last = qnameSize; + for(size_t i = qnameSize-1 ; i > 0 ; i--) + if(qname[i]=='.') + { + qname[i]=last-i-1; + last = i; + } + } + curSendSize += qnameSize +1; //With \0 terminator + + //Point to the query constant portion + struct QUESTION* qinfo =(struct QUESTION*)&buf[curSendSize]; + qinfo->qtype = htons(isIPV4 ? DNST_A : DNST_AAAA); //Type: A / AAAA(Host Address) + qinfo->qclass = htons(DNSC_IN); //Class: IN + curSendSize += sizeof(struct QUESTION); + +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<< " Sending Packet: " << std::endl << hexDump(buf, curSendSize) << std::endl; +#endif + int s = isIPV4 ? socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP) + : socket(AF_INET6 , SOCK_DGRAM , IPPROTO_UDP) ; //UDP packet for DNS queries + ssize_t send_size = sendto(s, (char*)buf, curSendSize, 0 + ,isIPV4 ? (struct sockaddr*)&dest4 + : (struct sockaddr*)&dest6 + ,isIPV4 ? sizeof(dest4) + : sizeof(dest6) + ); + if( send_size < 0) + { + RsErr()<<__PRETTY_FUNCTION__<<": Send Failed with size = " << send_size << std::endl; + return false; + } + +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<< " Waiting answer..." << std::endl; +#endif + //****************************************************************************************// + //--- Receive the answer ---// + //****************************************************************************************// + socklen_t dest_size = static_cast(sizeof dest4); + ssize_t rec_size=recvfrom(s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest4 , &dest_size ); + if(rec_size <= 0) + { + RsErr()<<__PRETTY_FUNCTION__<<": Receive Failed"<(sizeof(struct DNS_HEADER)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get DNSHeader."<q_count) << " Questions." << std::endl + <ans_count) << " Answers." << std::endl + <auth_count) << " Authoritative Servers." << std::endl + <add_count) << " Additional records." << std::endl; +#endif + size_t curRecSize = sizeof(struct DNS_HEADER); + + + if (rec_size< static_cast(curRecSize + 1 + sizeof(struct QUESTION)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Question return."<(&buf[curRecSize]); + if (memcmp(qname,qnameRecv,qnameSize + 1 + sizeof(struct QUESTION)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received different from that sent."<(curRecSize + 2) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Answer return."<(curRecSize + sizeof(struct RR_DATA)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Data return."<rtype!=qinfo->qtype) + { + RsErr()<<__PRETTY_FUNCTION__<<": Answer's type received different from query sent."<rclass!=qinfo->qclass) + { + RsErr()<<__PRETTY_FUNCTION__<<": Answer's class received different from query sent."<(curRecSize + ntohs(rec_data->data_len)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Full Data return."<data_len)==4) + { + if (isIPV4) + { + in_addr ipv4Add; + ipv4Add.s_addr=*(in_addr_t*)&buf[curRecSize]; +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<< " Retrieve address: " << rs_inet_ntoa(ipv4Add) << std::endl; +#endif + returned_addr = rs_inet_ntoa(ipv4Add); + return true; + } + } + else if(ntohs(rec_data->data_len)==16) + { + if (!isIPV4) + { + in6_addr ipv6Add; + ipv6Add =*(in6_addr*)&buf[curRecSize]; +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<< " Retrieve address: " << rs_inet_ntoa(ipv6Add) << std::endl; +#endif + returned_addr = rs_inet_ntoa(ipv6Add); + return true; + } + } + + RsErr()<<__PRETTY_FUNCTION__<< " Retrieve unmanaged data size=" << ntohs(rec_data->data_len) << std::endl; + return false; +} + bool isValidNet(const struct in_addr *addr) { // invalid address. @@ -174,3 +485,18 @@ std::string rs_inet_ntoa(struct in_addr in) rs_sprintf(str, "%u.%u.%u.%u", (int) bytes[0], (int) bytes[1], (int) bytes[2], (int) bytes[3]); return str; } + +std::string rs_inet_ntoa(const in6_addr& in) +{ + std::string str; + rs_sprintf(str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + (int)in.s6_addr[0] , (int)in.s6_addr[1], + (int)in.s6_addr[2] , (int)in.s6_addr[3], + (int)in.s6_addr[4] , (int)in.s6_addr[5], + (int)in.s6_addr[6] , (int)in.s6_addr[7], + (int)in.s6_addr[8] , (int)in.s6_addr[9], + (int)in.s6_addr[10], (int)in.s6_addr[11], + (int)in.s6_addr[12], (int)in.s6_addr[13], + (int)in.s6_addr[14], (int)in.s6_addr[15]); + return str; +} diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index cad2c116a..f88adca30 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -84,11 +84,17 @@ bool isExternalNet(const struct in_addr *addr); // uses a re-entrant version of gethostbyname bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) ; +// Get hostName address using specific DNS server +// Using it allow to direct ask our Address to IP, so no need to have a DNS (IPv4 or IPv6 ???). +// If we ask to a IPv6 DNS Server, it respond for our IPv6 address. +bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr); + std::ostream& operator<<(std::ostream& o, const sockaddr_in&); std::ostream& operator<<(std::ostream& o, const sockaddr_storage&); /* thread-safe version of inet_ntoa */ std::string rs_inet_ntoa(struct in_addr in); +std::string rs_inet_ntoa(const in6_addr &in); /***************************/ diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc index c084f516e..2a1475bee 100644 --- a/libretroshare/src/util/rsnet_ss.cc +++ b/libretroshare/src/util/rsnet_ss.cc @@ -262,6 +262,7 @@ bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 } #ifdef WINDOWS_SYS +#ifndef InetPtonA int inet_pton(int af, const char *src, void *dst) { sockaddr_storage ss; @@ -288,6 +289,7 @@ int inet_pton(int af, const char *src, void *dst) return 0; } #endif +#endif bool sockaddr_storage_inet_pton( sockaddr_storage &addr, const std::string& ipStr ) diff --git a/retroshare-gui/src/gui/settings/ServerPage.ui b/retroshare-gui/src/gui/settings/ServerPage.ui index d97187b54..2d6f81959 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.ui +++ b/retroshare-gui/src/gui/settings/ServerPage.ui @@ -719,6 +719,9 @@ behind a firewall or a VPN. 0 + + List of OpenDns servers used. + QAbstractItemView::NoEditTriggers From 81d2ddd7c7b9fde2819fc8f73d7b309b6582956a Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 3 Nov 2021 15:08:55 +0100 Subject: [PATCH 2/4] Enable IPv6 DNS ExtIpFinder Now empty node with only IPv6 can connect to other. --- libretroshare/src/pqi/p3netmgr.cc | 169 ++++++++++------ libretroshare/src/pqi/p3netmgr.h | 7 +- libretroshare/src/retroshare/rspeers.h | 1 + libretroshare/src/rsserver/p3peers.cc | 40 +++- libretroshare/src/rsserver/p3peers.h | 1 + libretroshare/src/util/extaddrfinder.cc | 190 +++++++++++++----- libretroshare/src/util/extaddrfinder.h | 23 ++- libretroshare/src/util/rsdebug.h | 94 +++++---- libretroshare/src/util/rsnet.cc | 14 +- libretroshare/src/util/rsnet.h | 2 +- .../src/gui/settings/ServerPage.cpp | 52 +++-- retroshare-gui/src/gui/settings/ServerPage.ui | 2 +- 12 files changed, 407 insertions(+), 188 deletions(-) diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 32b413e7b..5b4a6f692 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -55,6 +55,7 @@ const uint32_t RS_NET_EXT_SETUP = 0x0004; const uint32_t RS_NET_DONE = 0x0005; const uint32_t RS_NET_LOOPBACK = 0x0006; //const uint32_t RS_NET_DOWN = 0x0007; +const uint32_t RS_NET_SHUTDOWN = 0x00FF; //Highest value to not restart UPnP nor ExtAddrFinder /* Stun modes (TODO) */ //const uint32_t RS_STUN_DHT = 0x0001; @@ -68,6 +69,8 @@ const uint32_t MAX_UPNP_COMPLETE = 600; /* 10 min... seems to take a while */ //const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5; +const uint32_t MIN_TIME_EXT_FINDER_UPDATE = 300; /* 5min to check if external IP is changed */ + /**** * #define NETMGR_DEBUG 1 * #define NETMGR_DEBUG_RESET 1 @@ -107,19 +110,17 @@ void pqiNetStatus::print(std::ostream &out) } -p3NetMgrIMPL::p3NetMgrIMPL() : mPeerMgr(nullptr), mLinkMgr(nullptr), - mNetMtx("p3NetMgr"), mNetStatus(RS_NET_UNKNOWN), mStatusChanged(false), - mDoNotNetCheckUntilTs(0) +p3NetMgrIMPL::p3NetMgrIMPL() + : mPeerMgr(nullptr), mLinkMgr(nullptr) + , mNetMtx("p3NetMgr"), mNetMode(RS_NET_MODE_UDP), mVsDisc(RS_VS_DISC_FULL), mVsDht(RS_VS_DHT_FULL)// default to full. + , mNetInitTS(0), mNetStatus(RS_NET_UNKNOWN), mStatusChanged(false) + , mUseExtAddrFinder(true), mNetExtAddrFinderTs(0), mDoNotNetCheckUntilTs(0) { { RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetMode = RS_NET_MODE_UDP; - - mUseExtAddrFinder = true; mExtAddrFinder = new ExtAddrFinder(); - mNetInitTS = 0; mNetFlags = pqiNetStatus(); mOldNetFlags = pqiNetStatus(); @@ -133,10 +134,6 @@ p3NetMgrIMPL::p3NetMgrIMPL() : mPeerMgr(nullptr), mLinkMgr(nullptr), mLocalAddr.ss_family = AF_INET; mExtAddr.ss_family = AF_INET; - // default to full. - mVsDisc = RS_VS_DISC_FULL; - mVsDht = RS_VS_DHT_FULL; - } #ifdef NETMGR_DEBUG @@ -235,6 +232,10 @@ void p3NetMgrIMPL::netReset() rslog(RSL_ALERT, p3netmgrzone, "p3NetMgr::netReset() Called"); shutdown(); /* blocking shutdown call */ + { + RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + mNetStatus = RS_NET_UNKNOWN; + } // Will initiate a new call for determining the external ip. if (mUseExtAddrFinder) @@ -242,7 +243,7 @@ void p3NetMgrIMPL::netReset() #ifdef NETMGR_DEBUG_RESET std::cerr << "p3NetMgrIMPL::netReset() restarting AddrFinder" << std::endl; #endif - mExtAddrFinder->reset() ; + mExtAddrFinder->reset(true) ; } else { @@ -284,7 +285,6 @@ void p3NetMgrIMPL::netReset() { RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStatus = RS_NET_UNKNOWN; netStatusReset_locked(); } @@ -312,7 +312,7 @@ bool p3NetMgrIMPL::shutdown() /* blocking shutdown call */ #endif { RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStatus = RS_NET_UNKNOWN; + mNetStatus = RS_NET_SHUTDOWN; mNetInitTS = time(NULL); netStatusReset_locked(); } @@ -460,35 +460,50 @@ void p3NetMgrIMPL::netStatusTick() uint32_t netStatus = 0; rstime_t age = 0; + bool needExtFinderUpdate = false; { RsStackMutex stack(mNetMtx); /************** LOCK MUTEX ***************/ netStatus = mNetStatus; age = time(NULL) - mNetInitTS; - } + needExtFinderUpdate = netStatus == RS_NET_DONE; + needExtFinderUpdate &= mNetExtAddrFinderTs < time(nullptr); + if(needExtFinderUpdate) + mNetExtAddrFinderTs = time(nullptr) + MIN_TIME_EXT_FINDER_UPDATE; + } - if(netStatus <= RS_NET_UPNP_SETUP && mUseExtAddrFinder) - { - sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family + if( mUseExtAddrFinder + && ( netStatus <= RS_NET_UPNP_SETUP + || needExtFinderUpdate) ) + { + sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "Asking ExtAddrFinder for IP. Initializing port with " << sockaddr_storage_port(tmpip) << std::endl; + RsDbg(__PRETTY_FUNCTION__, " Asking ExtAddrFinder for IP. Initializing port with ", sockaddr_storage_port(tmpip)); #endif - if(mExtAddrFinder->hasValidIP(tmpip) && sockaddr_storage_ipv6_to_ipv4(tmpip) && !sockaddr_storage_same(tmpip,mExtAddr)) - { + if(mExtAddrFinder->hasValidIPV4(tmpip)) + { + if(!sockaddr_storage_same(tmpip,mExtAddr)) + { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; + RsDbg(__PRETTY_FUNCTION__, " Ext supplied by ExtAddrFinder", " ExtAddr: ", sockaddr_storage_tostring(tmpip)); #endif - + setExtAddress(tmpip); + } + } + else if(mExtAddrFinder->hasValidIPV6(tmpip)) + { + if(!sockaddr_storage_same(tmpip,mExtAddr)) + { + //Only if no IPv4 else, reset connections on setExtAddress() #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; + RsDbg(__PRETTY_FUNCTION__, " Ext supplied by ExtAddrFinder", " ExtAddr: ", sockaddr_storage_tostring(tmpip)); #endif - setExtAddress(tmpip); - } - } + setExtAddress(tmpip); + } + } + } switch(netStatus) { @@ -745,25 +760,18 @@ void p3NetMgrIMPL::netExtCheck() if (mUseExtAddrFinder) { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() checking ExtAddrFinder" << std::endl; + RsDbg(__PRETTY_FUNCTION__, " checking ExtAddrFinder"); #endif - sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family + sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family - bool extFinderOk = mExtAddrFinder->hasValidIP(tmpip); - - if (extFinderOk && sockaddr_storage_ipv6_to_ipv4(tmpip)) + // Test for IPv4 first to be compatible with older versions. + if (mExtAddrFinder->hasValidIPV4(tmpip)) { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; + RsDbg(__PRETTY_FUNCTION__, " Ext IPv4 supplied by ExtAddrFinder", sockaddr_storage_tostring(tmpip)); #endif sockaddr_storage_setport(tmpip, guessNewExtPort()); -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; -#endif - mNetFlags.mExtAddrOk = true; address_votes[tmpip].n++ ; @@ -773,10 +781,25 @@ void p3NetMgrIMPL::netExtCheck() * (which it is not normally) */ mNetFlags.mExtAddrStableOk = true; - std::cerr << __PRETTY_FUNCTION__ << " ExtAddrFinder " - << " reported external address " - << sockaddr_storage_iptostring(tmpip) - << std::endl; + RsErr(__PRETTY_FUNCTION__, " reported external IPv4 address ", sockaddr_storage_iptostring(tmpip)); + } + else if (mExtAddrFinder->hasValidIPV6(tmpip)) + { +#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) + RsDbg(__PRETTY_FUNCTION__, " Ext IPv6 supplied by ExtAddrFinder", sockaddr_storage_tostring(tmpip)); +#endif + sockaddr_storage_setport(tmpip, guessNewExtPort()); + + mNetFlags.mExtAddrOk = true; + + address_votes[tmpip].n++ ; + + /* XXX HACK TO FIX drbob: ALLOWING + * ExtAddrFinder -> ExtAddrStableOk = true + * (which it is not normally) */ + mNetFlags.mExtAddrStableOk = true; + + RsErr(__PRETTY_FUNCTION__, " reported external IPv6 address ", sockaddr_storage_iptostring(tmpip)); } } } @@ -967,7 +990,7 @@ void p3NetMgrIMPL::netExtCheck() if (netSetupDone) { - std::cerr << "p3NetMgrIMPL::netExtCheck() netSetupDone" << std::endl; + RsDbg(__PRETTY_FUNCTION__, " netSetupDone"); /* Setup NetStateBox with this info */ updateNetStateBox_startup(); @@ -978,12 +1001,14 @@ void p3NetMgrIMPL::netExtCheck() mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); } - /* inform DHT about our external address */ - RsPeerId fakeId; - netAssistKnownPeer(fakeId, mExtAddr, NETASSIST_KNOWN_PEER_SELF | NETASSIST_KNOWN_PEER_ONLINE); + /* inform DHT about our external IPV4 address, it doesn't support IPv6 for now.*/ + if(sockaddr_storage_ipv6_to_ipv4(mExtAddr)) + { + RsPeerId fakeId; + netAssistKnownPeer(fakeId, mExtAddr, NETASSIST_KNOWN_PEER_SELF | NETASSIST_KNOWN_PEER_ONLINE); + } - std::cerr << __PRETTY_FUNCTION__ << " Network Setup Complete" - << std::endl; + RsDbg(__PRETTY_FUNCTION__, " Network Setup Complete"); } } @@ -994,7 +1019,8 @@ void p3NetMgrIMPL::netExtCheck() bool p3NetMgrIMPL::checkNetAddress() { bool addrChanged = false; - bool validAddr = false; + bool validAddr = false; + bool needOwnAddrUpdate = false; sockaddr_storage prefAddr; sockaddr_storage oldAddr; @@ -1109,6 +1135,7 @@ bool p3NetMgrIMPL::checkNetAddress() sockaddr_storage_setport(mExtAddr, port); // this accounts for when the port was updated addrChanged = true; } + } // RS_STACK_MUTEX(mNetMtx); if (addrChanged) @@ -1123,11 +1150,24 @@ bool p3NetMgrIMPL::checkNetAddress() rsEvents->postEvent(ev); } - if (mPeerMgr) mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); + needOwnAddrUpdate = true; netReset(); } + if (mPeerMgr) + { + // Retrieve last known IP, if none, update own addresse to get current. + peerState ps; + mPeerMgr->getOwnNetStatus(ps); + needOwnAddrUpdate |= ps.ipAddrs.mLocal.mAddrs.empty(); + needOwnAddrUpdate |= ps.ipAddrs.mExt.mAddrs.empty(); + if (needOwnAddrUpdate) + { + mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); + } + } + return true; } @@ -1661,15 +1701,32 @@ void p3NetMgrIMPL::getIPServersList(std::list& ip_servers) mExtAddrFinder->getIPServersList(ip_servers); } +void p3NetMgrIMPL::getCurrentExtIPList(std::list& ip_list) +{ + ip_list.clear(); + sockaddr_storage addr; + if(mExtAddrFinder->hasValidIPV4(addr)) + ip_list.push_back(sockaddr_storage_iptostring(addr)); + if(mExtAddrFinder->hasValidIPV6(addr)) + ip_list.push_back(sockaddr_storage_iptostring(addr)); +} + void p3NetMgrIMPL::setIPServersEnabled(bool b) { + if (mUseExtAddrFinder != b) + { + mExtAddrFinder->reset(true); + if (b) + mExtAddrFinder->start_request(); + } + { RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ mUseExtAddrFinder = b; } #ifdef NETMGR_DEBUG - std::cerr << "p3NetMgr: setIPServers to " << b << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " set mUseExtAddrFinder to ", b); #endif } @@ -1973,8 +2030,8 @@ void p3NetMgrIMPL::updateNetStateBox_startup() /* ExtAddrFinder */ if (mUseExtAddrFinder) { - tmpip = mLocalAddr; - bool extFinderOk = mExtAddrFinder->hasValidIP(tmpip); + tmpip = mLocalAddr; + bool extFinderOk = mExtAddrFinder->hasValidIPV4(tmpip); if (extFinderOk) { diff --git a/libretroshare/src/pqi/p3netmgr.h b/libretroshare/src/pqi/p3netmgr.h index a847c07b1..e7b341098 100644 --- a/libretroshare/src/pqi/p3netmgr.h +++ b/libretroshare/src/pqi/p3netmgr.h @@ -120,6 +120,7 @@ virtual bool shutdown() = 0; /* blocking shutdown call */ virtual bool getIPServersEnabled() = 0; virtual void setIPServersEnabled(bool b) = 0; virtual void getIPServersList(std::list& ip_servers) = 0; +virtual void getCurrentExtIPList(std::list& ip_list) = 0; // ONLY USED by p3face-config.cc WHICH WILL BE REMOVED. virtual void getNetStatus(pqiNetStatus &status) = 0; @@ -171,6 +172,7 @@ virtual bool shutdown(); /* blocking shutdown call */ virtual bool getIPServersEnabled(); virtual void setIPServersEnabled(bool b); virtual void getIPServersList(std::list& ip_servers); +virtual void getCurrentExtIPList(std::list& ip_list); // ONLY USED by p3face-config.cc WHICH WILL BE REMOVED. virtual void getNetStatus(pqiNetStatus &status); @@ -307,12 +309,13 @@ void netStatusReset_locked(); uint16_t mVsDisc; uint16_t mVsDht; - rstime_t mNetInitTS; + rstime_t mNetInitTS; uint32_t mNetStatus; bool mStatusChanged; - bool mUseExtAddrFinder; + bool mUseExtAddrFinder; + rstime_t mNetExtAddrFinderTs; /* network status flags (read by rsiface) */ pqiNetStatus mNetFlags; diff --git a/libretroshare/src/retroshare/rspeers.h b/libretroshare/src/retroshare/rspeers.h index 3fdbbaf17..f49ef7fc2 100644 --- a/libretroshare/src/retroshare/rspeers.h +++ b/libretroshare/src/retroshare/rspeers.h @@ -788,6 +788,7 @@ public: virtual bool setProxyServer(const uint32_t type, const std::string &addr, const uint16_t port) = 0; virtual void getIPServersList(std::list& ip_servers) = 0; + virtual void getCurrentExtIPList(std::list& ip_list) = 0; virtual void allowServerIPDetermination(bool) = 0; virtual bool resetOwnExternalAddressList() = 0; virtual bool getAllowServerIPDetermination() = 0 ; diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index c44877fc5..16dda2a75 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -373,7 +373,7 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) sockaddr_storage_ipv6_to_ipv4(it->mAddr); std::string toto; toto += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(toto, " %ld sec", time(NULL) - it->mSeenTime); + rs_sprintf_append(toto, " %ld sec loc", time(NULL) - it->mSeenTime); d.ipAddressList.push_back(toto); } for(it = ps.ipAddrs.mExt.mAddrs.begin(); it != ps.ipAddrs.mExt.mAddrs.end(); ++it) @@ -381,7 +381,7 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) sockaddr_storage_ipv6_to_ipv4(it->mAddr); std::string toto; toto += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(toto, " %ld sec", time(NULL) - it->mSeenTime); + rs_sprintf_append(toto, " %ld sec ext", time(NULL) - it->mSeenTime); d.ipAddressList.push_back(toto); } } @@ -859,9 +859,15 @@ void p3Peers::getIPServersList(std::list& ip_servers) { mNetMgr->getIPServersList(ip_servers) ; } +void p3Peers::getCurrentExtIPList(std::list& ip_list) +{ + mNetMgr->getCurrentExtIPList(ip_list) ; +} bool p3Peers::resetOwnExternalAddressList() { - return mPeerMgr->resetOwnExternalAddressList(); + //TODO Phenom 2021-10-30: Need to call something like mNetMgr->netReset(); + // to update this addresslist. + return mPeerMgr->resetOwnExternalAddressList(); } void p3Peers::allowServerIPDetermination(bool b) { @@ -1305,6 +1311,7 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros } sockaddr_storage tExt; + struct in6_addr sin6_addr; if(sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && sockaddr_storage_isValidNet(tExt) && sockaddr_storage_ipv6_to_ipv4(tExt) && tDetails.extPort ) { uint32_t t4Addr = reinterpret_cast(tExt).sin_addr.s_addr; @@ -1321,6 +1328,16 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros offset += 4+2; } + else if(inet_pton(AF_INET6, tDetails.extAddr.c_str(), &(sin6_addr))) + { + // External address is IPv6, save it on LOCATOR + std::string tLocator = "ipv6://[" + tDetails.extAddr + "]:" + std::to_string(tDetails.extPort); + + addPacketHeader(RsShortInviteFieldType::LOCATOR, tLocator.size(),buf,offset,buf_size); + memcpy(&buf[offset],tLocator.c_str(),tLocator.size()); + + offset += tLocator.size(); + } #endif } @@ -1595,13 +1612,24 @@ std::string p3Peers::GetRetroshareInvite( const RsPeerId& sslId, RetroshareInvit if (getPeerDetails(ssl_id, detail)) { - if(!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) || detail.isHiddenNode) - detail.ipAddressList.clear(); + if(!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) || detail.isHiddenNode) + detail.ipAddressList.clear(); + + //Check if external address is IPv6, then move it to ipAddressList as RsCertificate only allow 4 numbers. + struct in6_addr sin6_addr; + if( inet_pton(AF_INET6, detail.extAddr.c_str(), &(sin6_addr)) + && !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) + && !detail.isHiddenNode) + { + detail.ipAddressList.push_front("ipv6://[" + detail.extAddr + "]:" + std::to_string(detail.extPort) + " "); + detail.extAddr = ""; //Clear it to not trigg error. + detail.extPort = 0; + } unsigned char *mem_block = nullptr; size_t mem_block_size = 0; - if(!AuthGPG::getAuthGPG()->exportPublicKey( RsPgpId(detail.gpg_id), mem_block, mem_block_size, false, !!(invite_flags & RetroshareInviteFlags::PGP_SIGNATURES) )) + if(!AuthGPG::getAuthGPG()->exportPublicKey( RsPgpId(detail.gpg_id), mem_block, mem_block_size, false, !!(invite_flags & RetroshareInviteFlags::PGP_SIGNATURES) )) { std::cerr << "Cannot output certificate for id \"" << detail.gpg_id << "\". Sorry." << std::endl; diff --git a/libretroshare/src/rsserver/p3peers.h b/libretroshare/src/rsserver/p3peers.h index 56f1f73e6..c2ff96d10 100644 --- a/libretroshare/src/rsserver/p3peers.h +++ b/libretroshare/src/rsserver/p3peers.h @@ -132,6 +132,7 @@ public: virtual bool isProxyAddress(const uint32_t type, const sockaddr_storage &addr); virtual void getIPServersList(std::list& ip_servers) override; + virtual void getCurrentExtIPList(std::list& ip_list) override; virtual void allowServerIPDetermination(bool) override; virtual bool getAllowServerIPDetermination() override; virtual bool resetOwnExternalAddressList() override; diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc index 6c281a74a..fa487c63e 100644 --- a/libretroshare/src/util/extaddrfinder.cc +++ b/libretroshare/src/util/extaddrfinder.cc @@ -22,6 +22,7 @@ #include "extaddrfinder.h" #include "pqi/pqinetwork.h" +#include "rsdebug.h" #include "util/rsstring.h" #include "util/rsmemory.h" @@ -38,10 +39,19 @@ #include #include "util/rstime.h" +#include + const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ //#define EXTADDRSEARCH_DEBUG +class ZeroInt +{ +public: + ZeroInt() : n(0) {} + uint32_t n ; +}; + void* doExtAddrSearch(void *p) { @@ -52,49 +62,90 @@ void* doExtAddrSearch(void *p) for(std::list::const_iterator it(af->_ip_servers.begin());it!=af->_ip_servers.end();++it) { std::string ip = ""; - rsGetHostByNameSpecDNS(*it,"myip.opendns.com",ip); + rsGetHostByNameSpecDNS(*it,"myip.opendns.com",ip,2); if(ip != "") res.push_back(ip) ; #ifdef EXTADDRSEARCH_DEBUG - std::cout << "ip found through DNS " << *it << ": \"" << ip << "\"" << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " ip found through DNS ", *it, ": \"", ip, "\""); #endif } if(res.empty()) { - // thread safe copy results. - // - { - RsStackMutex mtx(af->mAddrMtx) ; - - af->mFound = false ; - af->mFoundTS = time(NULL) ; - af->mSearching = false ; - } + af->reset(); return NULL ; } - sort(res.begin(),res.end()) ; // eliminates outliers. + std::map addrV4_votes; + std::map addrV6_votes; + std::string addrV4_Found; + std::string addrV6_Found; - - - if(!sockaddr_storage_ipv4_aton(af->mAddr, res[res.size()/2].c_str())) + for(auto curRes : res) { - std::cerr << "ExtAddrFinder: Could not convert " << res[res.size()/2] << " into an address." << std::endl ; + sockaddr_storage addr; + sockaddr_storage_clear(addr); + //sockaddr_storage_inet_pton convert IPv4 to IPv6 + struct sockaddr_in * addrv4p = (struct sockaddr_in *) &addr; + struct sockaddr_in6 * addrv6p = (struct sockaddr_in6 *) &addr; + if( inet_pton(AF_INET, curRes.c_str(), &(addrv4p->sin_addr)) ) { - RsStackMutex mtx(af->mAddrMtx) ; - af->mFound = false ; - af->mFoundTS = time(NULL) ; - af->mSearching = false ; + addr.ss_family = AF_INET; + addrV4_votes[addr].n++ ; + addrV4_Found += sockaddr_storage_tostring(addr) + "\n"; } + else if( inet_pton(AF_INET6, curRes.c_str(), &(addrv6p->sin6_addr)) ) + { + addr.ss_family = AF_INET6; + addrV6_votes[addr].n++ ; + addrV6_Found += sockaddr_storage_tostring(addr) + "\n"; + } + else + RsErr(__PRETTY_FUNCTION__, " Invalid addresse reported: ", curRes) ; + + } + + if( (0 == addrV4_votes.size()) && (0 == addrV6_votes.size()) ) + { + RsErr(__PRETTY_FUNCTION__, " Could not find any external address."); + af->reset(); return NULL ; } + if( 1 < addrV4_votes.size() ) + RsErr(__PRETTY_FUNCTION__, " Multiple external IPv4 addresses reported: " + , addrV4_Found ) ; + + if( 1 < addrV6_votes.size() ) + RsErr(__PRETTY_FUNCTION__, " Multiple external IPv6 addresses reported: " + , addrV6_Found ) ; + { RsStackMutex mtx(af->mAddrMtx) ; - af->mFound = true ; - af->mFoundTS = time(NULL) ; af->mSearching = false ; + af->mFoundTS = time(NULL) ; + + // Only save more reported address if not only once. + uint32_t admax = 0 ; + sockaddr_storage_clear(af->mAddrV4); + for (auto it : addrV4_votes) + if (admax < it.second.n) + { + af->mAddrV4 = it.first ; + af->mFoundV4 = true ; + admax = it.second.n ; + } + + admax = 0 ; + sockaddr_storage_clear(af->mAddrV6); + for (auto it : addrV6_votes) + if (admax < it.second.n) + { + af->mAddrV6 = it.first ; + af->mFoundV6 = true ; + admax = it.second.n ; + } + } return NULL ; @@ -105,75 +156,112 @@ void ExtAddrFinder::start_request() { void *data = (void *)this; pthread_t tid ; - - if(! pthread_create(&tid, 0, &doExtAddrSearch, data)) + + if(! pthread_create(&tid, 0, &doExtAddrSearch, data)) pthread_detach(tid); /* so memory is reclaimed in linux */ - else - std::cerr << "(EE) Could not start ExtAddrFinder thread." << std::endl; + else + RsErr(__PRETTY_FUNCTION__, " Could not start ExtAddrFinder thread."); } -bool ExtAddrFinder::hasValidIP(struct sockaddr_storage &addr) +bool ExtAddrFinder::hasValidIPV4(struct sockaddr_storage &addr) { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Getting ip." << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " Getting ip."); #endif { RsStackMutex mut(mAddrMtx) ; - if(mFound) + if(mFoundV4) { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Has stored ip: responding with this ip." << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV4)) ; #endif - sockaddr_storage_copyip(addr,mAddr); // just copy the IP so we dont erase the port. + sockaddr_storage_copyip(addr,mAddrV4); // just copy the IP so we dont erase the port. } } - rstime_t delta; + + testTimeOut(); + + RsStackMutex mut(mAddrMtx) ; + return mFoundV4; +} + +bool ExtAddrFinder::hasValidIPV6(struct sockaddr_storage &addr) +{ +#ifdef EXTADDRSEARCH_DEBUG + RsDbg(__PRETTY_FUNCTION__, " Getting ip."); +#endif + + { + RsStackMutex mut(mAddrMtx) ; + if(mFoundV6) + { +#ifdef EXTADDRSEARCH_DEBUG + RsDbg(__PRETTY_FUNCTION__, " Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV6)) ; +#endif + sockaddr_storage_copyip(addr,mAddrV6); // just copy the IP so we dont erase the port. + } + } + + testTimeOut(); + + RsStackMutex mut(mAddrMtx) ; + return mFoundV6; +} + +void ExtAddrFinder::testTimeOut() +{ + bool timeOut; { RsStackMutex mut(mAddrMtx) ; //timeout the current ip - delta = time(NULL) - mFoundTS; + timeOut = (mFoundTS + MAX_IP_STORE < time(NULL)); } - if((uint32_t)delta > MAX_IP_STORE) {//launch a research + if(timeOut || mFirstTime) {//launch a research if( mAddrMtx.trylock()) { if(!mSearching) { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: No stored ip: Initiating new search." << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " No stored ip: Initiating new search."); #endif mSearching = true ; start_request() ; } #ifdef EXTADDRSEARCH_DEBUG else - std::cerr << "ExtAddrFinder: Already searching." << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " Already searching."); #endif + mFirstTime = false; mAddrMtx.unlock(); } #ifdef EXTADDRSEARCH_DEBUG else - std::cerr << "ExtAddrFinder: (Note) Could not acquire lock. Busy." << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " (Note) Could not acquire lock. Busy."); #endif } - - RsStackMutex mut(mAddrMtx) ; - return mFound ; } -void ExtAddrFinder::reset() +void ExtAddrFinder::reset(bool firstTime /*=false*/) { +#ifdef EXTADDRSEARCH_DEBUG + RsDbg(__PRETTY_FUNCTION__, " firstTime=", firstTime?"true":"false"); +#endif RsStackMutex mut(mAddrMtx) ; - mFound = false ; mSearching = false ; - mFoundTS = time(NULL) - MAX_IP_STORE; + mFoundV4 = false ; + mFoundV6 = false ; + mFirstTime = firstTime; + mFoundTS = time(NULL); + sockaddr_storage_clear(mAddrV4); + sockaddr_storage_clear(mAddrV6); } ExtAddrFinder::~ExtAddrFinder() { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Deleting ExtAddrFinder." << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " Deleting ExtAddrFinder."); #endif } @@ -181,14 +269,9 @@ ExtAddrFinder::~ExtAddrFinder() ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder") { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Creating new ExtAddrFinder." << std::endl ; + RsDbg(__PRETTY_FUNCTION__, " Creating new ExtAddrFinder."); #endif - RsStackMutex mut(mAddrMtx) ; - - mFound = false; - mSearching = false; - mFoundTS = time(NULL) - MAX_IP_STORE; - sockaddr_storage_clear(mAddr); + reset( true ); //https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script //Enter direct ip so local DNS cannot change it. @@ -197,8 +280,7 @@ ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder") _ip_servers.push_back(std::string( "208.67.220.220" )) ;//resolver2.opendns.com _ip_servers.push_back(std::string( "208.67.222.220" )) ;//resolver3.opendns.com _ip_servers.push_back(std::string( "208.67.220.222" )) ;//resolver4.opendns.com - //Ipv6 server disabled as Current ip only manage ipv4 for now. - //_ip_servers.push_back(std::string( "2620:119:35::35" )) ;//resolver1.opendns.com - //_ip_servers.push_back(std::string( "2620:119:53::53" )) ;//resolver2.opendns.com + _ip_servers.push_back(std::string( "2620:119:35::35" )) ;//resolver1.opendns.com + _ip_servers.push_back(std::string( "2620:119:53::53" )) ;//resolver2.opendns.com } diff --git a/libretroshare/src/util/extaddrfinder.h b/libretroshare/src/util/extaddrfinder.h index 22a9a5689..bf7bfd878 100644 --- a/libretroshare/src/util/extaddrfinder.h +++ b/libretroshare/src/util/extaddrfinder.h @@ -36,20 +36,25 @@ class ExtAddrFinder ExtAddrFinder() ; ~ExtAddrFinder() ; - bool hasValidIP(struct sockaddr_storage &addr) ; + bool hasValidIPV4(struct sockaddr_storage &addr) ; + bool hasValidIPV6(struct sockaddr_storage &addr) ; void getIPServersList(std::list& ip_servers) { ip_servers = _ip_servers ; } void start_request() ; - void reset() ; + void reset(bool firstTime = false) ; private: - friend void* doExtAddrSearch(void *p) ; + friend void* doExtAddrSearch(void *p); + void testTimeOut(); - RsMutex mAddrMtx ; - rstime_t mFoundTS; - struct sockaddr_storage mAddr; - bool mFound ; - bool mSearching ; - std::list _ip_servers ; + RsMutex mAddrMtx; + bool mSearching; + bool mFoundV4; + bool mFoundV6; + bool mFirstTime; + rstime_t mFoundTS; + struct sockaddr_storage mAddrV4; + struct sockaddr_storage mAddrV6; + std::list _ip_servers; }; diff --git a/libretroshare/src/util/rsdebug.h b/libretroshare/src/util/rsdebug.h index cb5e1748e..25d1f1969 100644 --- a/libretroshare/src/util/rsdebug.h +++ b/libretroshare/src/util/rsdebug.h @@ -210,6 +210,53 @@ struct RsNoDbg }; +//From https://codereview.stackexchange.com/a/165162 +/** + * @brief hex_dump: Send Hexadecimal Dump to stream + * @param os: Output Stream + * @param buffer: Buffer to send + * @param bufsize: Buffer's size + * @param showPrintableChars: If must send printable Char too + * @return + * basic string: + * 61 62 63 64 65 66 31 32 | abcdef12 + * 33 34 35 36 00 7a 79 78 | 3456.zyx + * 77 76 75 39 38 37 36 35 | wvu98765 + * 34 45 64 77 61 72 64 00 | 4Edward. + * + * wide string: + * 41 00 00 00 20 00 00 00 | A... ... + * 77 00 00 00 69 00 00 00 | w...i... + * 64 00 00 00 65 00 00 00 | d...e... + * 20 00 00 00 73 00 00 00 | ...s... + * 74 00 00 00 72 00 00 00 | t...r... + * 69 00 00 00 6e 00 00 00 | i...n... + * 67 00 00 00 2e 00 00 00 | g....... + * + * a double + * 49 92 24 49 92 24 09 40 | I.$I.$.@ + */ +std::ostream& hex_dump(std::ostream& os, const void *buffer, + std::size_t bufsize, bool showPrintableChars = true); + +/** + * @brief The hexDump struct + * Enable to print dump calling like that: + * const char test[] = "abcdef123456\0zyxwvu987654Edward"; + * RsDbg()<setCurrentIndex(netIndex); @@ -824,9 +824,9 @@ void ServerPage::ipWhiteListContextMenu(const QPoint& /* point */) return ; } - QString range0 = RsNetUtil::printAddrRange(addr,0) ; - QString range1 = RsNetUtil::printAddrRange(addr,1) ; - QString range2 = RsNetUtil::printAddrRange(addr,2) ; +// QString range0 = RsNetUtil::printAddrRange(addr,0) ; +// QString range1 = RsNetUtil::printAddrRange(addr,1) ; +// QString range2 = RsNetUtil::printAddrRange(addr,2) ; // contextMenu.addAction(QObject::tr("Whitelist only IP " )+range0,this,SLOT(enableBannedIp()))->setEnabled(false) ; //#warning UNIMPLEMENTED CODE @@ -930,6 +930,28 @@ void ServerPage::updateStatus() else ui.iconlabel_ext->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/ledoff1.png")); + if (ui.ipAddressList->isEnabled() ) + { + whileBlocking(ui.ipAddressList)->clear(); + detail.ipAddressList.sort(); + for(auto& it : detail.ipAddressList) + whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(it).replace("sec",tr("sec")).replace("loc",tr("local")).replace("ext",tr("external"))); + } + + QString toolTip = tr("List of OpenDns servers used."); + if (ui.IPServersLV->isEnabled() ) + { + std::list ip_list; + rsPeers->getCurrentExtIPList(ip_list); + if ( !ip_list.empty() ) + { + toolTip += tr("\n\nList of found external IP:\n"); + for(std::list::const_iterator it(ip_list.begin());it!=ip_list.end();++it) + toolTip += " " + QString::fromStdString(*it) +"\n" ; + } + } + if(ui.IPServersLV->toolTip() != toolTip) + ui.IPServersLV->setToolTip(toolTip); } void ServerPage::toggleUPnP() diff --git a/retroshare-gui/src/gui/settings/ServerPage.ui b/retroshare-gui/src/gui/settings/ServerPage.ui index 2d6f81959..6b78b988c 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.ui +++ b/retroshare-gui/src/gui/settings/ServerPage.ui @@ -704,7 +704,7 @@ connecting when you have few friends. It also helps if you're behind a firewall or a VPN. - Allow RetroShare to ask my ip to these websites: + Allow RetroShare to ask my ip to these DNS servers: true From 7755f85c4c9eb984d74658c4aeedbbdae40fefef Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 3 Nov 2021 19:41:57 +0100 Subject: [PATCH 3/4] Move DNS stuff to single new file rsdnsutils.cc. --- libretroshare/src/libretroshare.pro | 1 + libretroshare/src/util/rsdnsutils.cc | 360 +++++++++++++++++++++++++++ libretroshare/src/util/rsnet.cc | 338 ------------------------- libretroshare/src/util/rsnet.h | 1 - 4 files changed, 361 insertions(+), 339 deletions(-) create mode 100644 libretroshare/src/util/rsdnsutils.cc diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 075da3581..d42f68328 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -635,6 +635,7 @@ SOURCES += util/folderiterator.cc \ util/rsdiscspace.cc \ util/rsnet.cc \ util/rsnet_ss.cc \ + util/rsdnsutils.cc \ util/extaddrfinder.cc \ util/dnsresolver.cc \ util/rsprint.cc \ diff --git a/libretroshare/src/util/rsdnsutils.cc b/libretroshare/src/util/rsdnsutils.cc new file mode 100644 index 000000000..cfe8418b7 --- /dev/null +++ b/libretroshare/src/util/rsdnsutils.cc @@ -0,0 +1,360 @@ +/******************************************************************************* + * libretroshare/src/util: rsdnsutils.cc * + * * + * libretroshare: retroshare core library * + * * + * Copyright 2021 Phenom * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +//#define DEBUG_SPEC_DNS 1 +#include "util/rsnet.h" + +#include "util/rsdebug.h" +#include "util/rsthreads.h" +#include "util/rsstring.h" + +#ifdef WINDOWS_SYS +#else +#include +#endif + +//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 +constexpr uint16_t DNSC_IN = 1; //Internet (IN) +//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 +constexpr uint16_t DNST_A = 1; //Ipv4 address +constexpr uint16_t DNST_AAAA =28; //Ipv6 address + +///Need to pack as we use sizeof them. (avoid padding) +#pragma pack(1) +//DNS header structure +struct DNS_HEADER +{ + unsigned short id; // identification number + + //Header flags https://www.bind9.net/dns-header-flags + unsigned char rd :1; //bit 07 Recursion Desired, indicates if the client means a recursive query + unsigned char tc :1; //bit 06 TrunCation, indicates that this message was truncated due to excessive length + unsigned char aa :1; //bit 05 Authoritative Answer, in a response, indicates if the DNS server is authoritative for the queried hostname + unsigned char opcode :4;//bit 01-04 The type can be QUERY (standard query, 0), IQUERY (inverse query, 1), or STATUS (server status request, 2) + unsigned char qr :1; //bit 00 Indicates if the message is a query (0) or a reply (1) + + unsigned char rcode :4; //bit 12-15 Response Code can be NOERROR (0), FORMERR (1, Format error), SERVFAIL (2), NXDOMAIN (3, Nonexistent domain), etc. + unsigned char cd :1; //bit 11 Checking Disabled [RFC 4035][RFC 6840][RFC Errata 4927] used by DNSSEC + unsigned char ad :1; //bit 10 Authentic Data [RFC 4035][RFC 6840][RFC Errata 4924] used by DNSSEC + unsigned char z :1; //bit 09 Zero, reserved for future use + unsigned char ra :1; //bit 08 Recursion Available [RFC 1035] in a response, indicates if the replying DNS server supports recursion + + unsigned short q_count; // number of question entries + unsigned short ans_count; // number of answer entries + unsigned short auth_count; // number of authority resource records entries + unsigned short add_count; // number of additional resource record entries +}; +//// OpCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5 +//static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS", +// "RESERVED3", "NOTIFY", "UPDATE", +// "STATEFUL", "RESERVED7", "RESERVED8", +// "RESERVED9", "RESERVED10", "RESERVED11", +// "RESERVED12", "RESERVED13", "RESERVED14", +// "RESERVED15" }; +//// RCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 +//static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL", +// "NXDOMAIN", "NOTIMP", "REFUSED", +// "YXDOMAIN", "YXRRSET", "NXRRSET", +// "NOTAUTH", "NOTZONE", "DSOTYPENI", +// "RESERVED12", "RESERVED13", "RESERVED14", +// "RESERVED15", "BADVERS", "BADKEY", +// "BADTIME", "BADMODE", "BADNAME", +// "BADALG", "BADTRUNC", "BADCOOKIE"}; + +//Constant sized fields of query structure +//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml +struct QUESTION +{ + unsigned short qtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 + unsigned short qclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 +}; + +//Constant sized fields of the resource record structure +struct RR_DATA +{ + unsigned short rtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 + unsigned short rclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 + unsigned int rttl; //Time To Live is the number of seconds left before the information expires. (32bits integer, so maximum 140 years) + unsigned short data_len;//Lenght of following data +}; +#pragma pack() + +bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr, int timeout_s /*= -1*/) +{ +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<<" servername="<< servername << " hostname=" << hostname << std::endl; +#endif + + if (strlen(servername.c_str()) > 256) + { + RsErr()<<__PRETTY_FUNCTION__<<": servername is too long > 256 chars:"< 256) + { + RsErr()<<__PRETTY_FUNCTION__<<": hostname is too long > 256 chars:"<id = static_cast(htons(getpid())); //Transaction Id + //dns flags = 0x0100 Standard Query + dns->qr = 0; //Query/Response: Message is a query + dns->opcode = 0; //OpCode: Standard query + dns->aa = 0; //Authoritative: Server is not an authority for domain + dns->tc = 0; //TrunCated: Message is not truncated + dns->rd = 1; //Recursion Desired: Do query recursively + dns->ra = 0; //Recursion Available: Server cannot do recursive queries + dns->z = 0; //Z: reserved + dns->ad = 0; //Authentic Data: Answer/authority portion was not authenticated by the server + dns->cd = 0; //Checking Disabled: Unacceptable + dns->rcode = 0; //Response Code: No error + + dns->q_count = htons(1); //1 Question + dns->ans_count = 0; //0 Answer + dns->auth_count = 0; //0 Authority RRs + dns->add_count = 0; //0 Additional RRs + size_t curSendSize = sizeof(struct DNS_HEADER); + + //Point to the query server name portion + unsigned char* qname =static_cast(&buf[curSendSize]); + //First byte is Label Type: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-10 + qname[0] = 0x04; //One Label with Normal label lower 6 bits is the length of the label + memcpy(&qname[1],hostname.c_str(),strlen(hostname.c_str())); + size_t qnameSize = strlen((const char*)qname); + // Format Hostname like www.google.com to 3www6google3com + { + size_t last = qnameSize; + for(size_t i = qnameSize-1 ; i > 0 ; i--) + if(qname[i]=='.') + { + qname[i]=last-i-1; + last = i; + } + } + curSendSize += qnameSize +1; //With \0 terminator + + //Point to the query constant portion + struct QUESTION* qinfo =(struct QUESTION*)&buf[curSendSize]; + qinfo->qtype = htons(isIPV4 ? DNST_A : DNST_AAAA); //Type: A / AAAA(Host Address) + qinfo->qclass = htons(DNSC_IN); //Class: IN + curSendSize += sizeof(struct QUESTION); + +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<< " Sending Packet: " << std::endl << hexDump(buf, curSendSize) << std::endl; +#endif + int s = isIPV4 ? socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP) + : socket(AF_INET6 , SOCK_DGRAM , IPPROTO_UDP) ; //UDP packet for DNS queries + if (timeout_s > -1) + { +#ifdef WINDOWS_SYS + DWORD timeout = timeout_s * 1000; + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout); +#else + struct timeval tv; + tv.tv_sec = timeout_s; + tv.tv_usec = 0; + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); +#endif + } + ssize_t send_size = sendto(s, (char*)buf, curSendSize, 0 + ,isIPV4 ? (struct sockaddr*)&dest4 + : (struct sockaddr*)&dest6 + ,isIPV4 ? sizeof(dest4) + : sizeof(dest6) + ); + if( send_size < 0) + { + RsErr()<<__PRETTY_FUNCTION__<<": Send Failed with size = " << send_size << std::endl; + return false; + } + +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<< " Waiting answer..." << std::endl; +#endif + //****************************************************************************************// + //--- Receive the answer ---// + //****************************************************************************************// + socklen_t dest_size = static_cast(sizeof dest4); + ssize_t rec_size=recvfrom(s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest4 , &dest_size ); + if(rec_size <= 0) + { + RsErr()<<__PRETTY_FUNCTION__<<": Receive Failed"<(sizeof(struct DNS_HEADER)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get DNSHeader."<q_count) << " Questions." << std::endl + <ans_count) << " Answers." << std::endl + <auth_count) << " Authoritative Servers." << std::endl + <add_count) << " Additional records." << std::endl; +#endif + size_t curRecSize = sizeof(struct DNS_HEADER); + + + if (rec_size< static_cast(curRecSize + 1 + sizeof(struct QUESTION)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Question return."<(&buf[curRecSize]); + if (memcmp(qname,qnameRecv,qnameSize + 1 + sizeof(struct QUESTION)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received different from that sent."<(curRecSize + 2) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Answer return."<(curRecSize + sizeof(struct RR_DATA)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Data return."<rtype!=qinfo->qtype) + { + RsErr()<<__PRETTY_FUNCTION__<<": Answer's type received different from query sent."<rclass!=qinfo->qclass) + { + RsErr()<<__PRETTY_FUNCTION__<<": Answer's class received different from query sent."<(curRecSize + ntohs(rec_data->data_len)) ) + { + RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Full Data return."<data_len)==4) + { + if (isIPV4) + { + in_addr ipv4Add; + ipv4Add.s_addr=*(in_addr_t*)&buf[curRecSize]; +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<< " Retrieve address: " << rs_inet_ntoa(ipv4Add) << std::endl; +#endif + returned_addr = rs_inet_ntoa(ipv4Add); + return true; + } + } + else if(ntohs(rec_data->data_len)==16) + { + if (!isIPV4) + { + in6_addr ipv6Add; + ipv6Add =*(in6_addr*)&buf[curRecSize]; + + struct sockaddr_storage ss; + sockaddr_storage_clear(ss); + sockaddr_in6 addr_ipv6; + addr_ipv6.sin6_addr = ipv6Add; + sockaddr_storage_setipv6(ss,&addr_ipv6); + +#ifdef DEBUG_SPEC_DNS + RsDbg()<<__PRETTY_FUNCTION__<< " Retrieve address: " << sockaddr_storage_iptostring(ss).c_str() << std::endl; +#endif + returned_addr = sockaddr_storage_iptostring(ss); + return true; + } + } + + RsErr()<<__PRETTY_FUNCTION__<< " Retrieve unmanaged data size=" << ntohs(rec_data->data_len) << std::endl; + return false; +} diff --git a/libretroshare/src/util/rsnet.cc b/libretroshare/src/util/rsnet.cc index a4678e7be..1e5f79181 100644 --- a/libretroshare/src/util/rsnet.cc +++ b/libretroshare/src/util/rsnet.cc @@ -21,9 +21,6 @@ * * *******************************************************************************/ -//#define DEBUG_SPEC_DNS 1 - -#include "util/rsdebug.h" #include "util/rsnet.h" #include "util/rsthreads.h" #include "util/rsstring.h" @@ -43,72 +40,6 @@ #define BIG_ENDIAN 4321 #endif -//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 -constexpr uint16_t DNSC_IN = 1; //Internet (IN) -//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 -constexpr uint16_t DNST_A = 1; //Ipv4 address -constexpr uint16_t DNST_AAAA =28; //Ipv6 address - -///Need to pack as we use sizeof them. (avoid padding) -#pragma pack(1) -//DNS header structure -struct DNS_HEADER -{ - unsigned short id; // identification number - - //Header flags https://www.bind9.net/dns-header-flags - unsigned char rd :1; //bit 07 Recursion Desired, indicates if the client means a recursive query - unsigned char tc :1; //bit 06 TrunCation, indicates that this message was truncated due to excessive length - unsigned char aa :1; //bit 05 Authoritative Answer, in a response, indicates if the DNS server is authoritative for the queried hostname - unsigned char opcode :4;//bit 01-04 The type can be QUERY (standard query, 0), IQUERY (inverse query, 1), or STATUS (server status request, 2) - unsigned char qr :1; //bit 00 Indicates if the message is a query (0) or a reply (1) - - unsigned char rcode :4; //bit 12-15 Response Code can be NOERROR (0), FORMERR (1, Format error), SERVFAIL (2), NXDOMAIN (3, Nonexistent domain), etc. - unsigned char cd :1; //bit 11 Checking Disabled [RFC 4035][RFC 6840][RFC Errata 4927] used by DNSSEC - unsigned char ad :1; //bit 10 Authentic Data [RFC 4035][RFC 6840][RFC Errata 4924] used by DNSSEC - unsigned char z :1; //bit 09 Zero, reserved for future use - unsigned char ra :1; //bit 08 Recursion Available [RFC 1035] in a response, indicates if the replying DNS server supports recursion - - unsigned short q_count; // number of question entries - unsigned short ans_count; // number of answer entries - unsigned short auth_count; // number of authority resource records entries - unsigned short add_count; // number of additional resource record entries -}; -//// OpCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5 -//static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS", -// "RESERVED3", "NOTIFY", "UPDATE", -// "STATEFUL", "RESERVED7", "RESERVED8", -// "RESERVED9", "RESERVED10", "RESERVED11", -// "RESERVED12", "RESERVED13", "RESERVED14", -// "RESERVED15" }; -//// RCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 -//static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL", -// "NXDOMAIN", "NOTIMP", "REFUSED", -// "YXDOMAIN", "YXRRSET", "NXRRSET", -// "NOTAUTH", "NOTZONE", "DSOTYPENI", -// "RESERVED12", "RESERVED13", "RESERVED14", -// "RESERVED15", "BADVERS", "BADKEY", -// "BADTIME", "BADMODE", "BADNAME", -// "BADALG", "BADTRUNC", "BADCOOKIE"}; - -//Constant sized fields of query structure -//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml -struct QUESTION -{ - unsigned short qtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 - unsigned short qclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 -}; - -//Constant sized fields of the resource record structure -struct RR_DATA -{ - unsigned short rtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 - unsigned short rclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 - unsigned int rttl; //Time To Live is the number of seconds left before the information expires. (32bits integer, so maximum 140 years) - unsigned short data_len;//Lenght of following data -}; -#pragma pack() - #ifndef ntohll uint64_t ntohll(uint64_t x) { @@ -168,260 +99,6 @@ bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) return ok; } -bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr, int timeout_s /*= -1*/) -{ -#ifdef DEBUG_SPEC_DNS - RsDbg()<<__PRETTY_FUNCTION__<<" servername="<< servername << " hostname=" << hostname << std::endl; -#endif - - if (strlen(servername.c_str()) > 256) - { - RsErr()<<__PRETTY_FUNCTION__<<": servername is too long > 256 chars:"< 256) - { - RsErr()<<__PRETTY_FUNCTION__<<": hostname is too long > 256 chars:"<id = static_cast(htons(getpid())); //Transaction Id - //dns flags = 0x0100 Standard Query - dns->qr = 0; //Query/Response: Message is a query - dns->opcode = 0; //OpCode: Standard query - dns->aa = 0; //Authoritative: Server is not an authority for domain - dns->tc = 0; //TrunCated: Message is not truncated - dns->rd = 1; //Recursion Desired: Do query recursively - dns->ra = 0; //Recursion Available: Server cannot do recursive queries - dns->z = 0; //Z: reserved - dns->ad = 0; //Authentic Data: Answer/authority portion was not authenticated by the server - dns->cd = 0; //Checking Disabled: Unacceptable - dns->rcode = 0; //Response Code: No error - - dns->q_count = htons(1); //1 Question - dns->ans_count = 0; //0 Answer - dns->auth_count = 0; //0 Authority RRs - dns->add_count = 0; //0 Additional RRs - size_t curSendSize = sizeof(struct DNS_HEADER); - - //Point to the query server name portion - unsigned char* qname =static_cast(&buf[curSendSize]); - //First byte is Label Type: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-10 - qname[0] = 0x04; //One Label with Normal label lower 6 bits is the length of the label - memcpy(&qname[1],hostname.c_str(),strlen(hostname.c_str())); - size_t qnameSize = strlen((const char*)qname); - // Format Hostname like www.google.com to 3www6google3com - { - size_t last = qnameSize; - for(size_t i = qnameSize-1 ; i > 0 ; i--) - if(qname[i]=='.') - { - qname[i]=last-i-1; - last = i; - } - } - curSendSize += qnameSize +1; //With \0 terminator - - //Point to the query constant portion - struct QUESTION* qinfo =(struct QUESTION*)&buf[curSendSize]; - qinfo->qtype = htons(isIPV4 ? DNST_A : DNST_AAAA); //Type: A / AAAA(Host Address) - qinfo->qclass = htons(DNSC_IN); //Class: IN - curSendSize += sizeof(struct QUESTION); - -#ifdef DEBUG_SPEC_DNS - RsDbg()<<__PRETTY_FUNCTION__<< " Sending Packet: " << std::endl << hexDump(buf, curSendSize) << std::endl; -#endif - int s = isIPV4 ? socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP) - : socket(AF_INET6 , SOCK_DGRAM , IPPROTO_UDP) ; //UDP packet for DNS queries - if (timeout_s > -1) - { -#ifdef WINDOWS_SYS - DWORD timeout = timeout_s * 1000; - setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout); -#else - struct timeval tv; - tv.tv_sec = timeout_s; - tv.tv_usec = 0; - setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); -#endif - } - ssize_t send_size = sendto(s, (char*)buf, curSendSize, 0 - ,isIPV4 ? (struct sockaddr*)&dest4 - : (struct sockaddr*)&dest6 - ,isIPV4 ? sizeof(dest4) - : sizeof(dest6) - ); - if( send_size < 0) - { - RsErr()<<__PRETTY_FUNCTION__<<": Send Failed with size = " << send_size << std::endl; - return false; - } - -#ifdef DEBUG_SPEC_DNS - RsDbg()<<__PRETTY_FUNCTION__<< " Waiting answer..." << std::endl; -#endif - //****************************************************************************************// - //--- Receive the answer ---// - //****************************************************************************************// - socklen_t dest_size = static_cast(sizeof dest4); - ssize_t rec_size=recvfrom(s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest4 , &dest_size ); - if(rec_size <= 0) - { - RsErr()<<__PRETTY_FUNCTION__<<": Receive Failed"<(sizeof(struct DNS_HEADER)) ) - { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get DNSHeader."<q_count) << " Questions." << std::endl - <ans_count) << " Answers." << std::endl - <auth_count) << " Authoritative Servers." << std::endl - <add_count) << " Additional records." << std::endl; -#endif - size_t curRecSize = sizeof(struct DNS_HEADER); - - - if (rec_size< static_cast(curRecSize + 1 + sizeof(struct QUESTION)) ) - { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Question return."<(&buf[curRecSize]); - if (memcmp(qname,qnameRecv,qnameSize + 1 + sizeof(struct QUESTION)) ) - { - RsErr()<<__PRETTY_FUNCTION__<<": Request received different from that sent."<(curRecSize + 2) ) - { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Answer return."<(curRecSize + sizeof(struct RR_DATA)) ) - { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Data return."<rtype!=qinfo->qtype) - { - RsErr()<<__PRETTY_FUNCTION__<<": Answer's type received different from query sent."<rclass!=qinfo->qclass) - { - RsErr()<<__PRETTY_FUNCTION__<<": Answer's class received different from query sent."<(curRecSize + ntohs(rec_data->data_len)) ) - { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Full Data return."<data_len)==4) - { - if (isIPV4) - { - in_addr ipv4Add; - ipv4Add.s_addr=*(in_addr_t*)&buf[curRecSize]; -#ifdef DEBUG_SPEC_DNS - RsDbg()<<__PRETTY_FUNCTION__<< " Retrieve address: " << rs_inet_ntoa(ipv4Add) << std::endl; -#endif - returned_addr = rs_inet_ntoa(ipv4Add); - return true; - } - } - else if(ntohs(rec_data->data_len)==16) - { - if (!isIPV4) - { - in6_addr ipv6Add; - ipv6Add =*(in6_addr*)&buf[curRecSize]; -#ifdef DEBUG_SPEC_DNS - RsDbg()<<__PRETTY_FUNCTION__<< " Retrieve address: " << rs_inet_ntoa(ipv6Add) << std::endl; -#endif - returned_addr = rs_inet_ntoa(ipv6Add); - return true; - } - } - - RsErr()<<__PRETTY_FUNCTION__<< " Retrieve unmanaged data size=" << ntohs(rec_data->data_len) << std::endl; - return false; -} - bool isValidNet(const struct in_addr *addr) { // invalid address. @@ -497,18 +174,3 @@ std::string rs_inet_ntoa(struct in_addr in) rs_sprintf(str, "%u.%u.%u.%u", (int) bytes[0], (int) bytes[1], (int) bytes[2], (int) bytes[3]); return str; } - -std::string rs_inet_ntoa(const in6_addr& in) -{ - std::string str; - rs_sprintf(str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", - (int)in.s6_addr[0] , (int)in.s6_addr[1], - (int)in.s6_addr[2] , (int)in.s6_addr[3], - (int)in.s6_addr[4] , (int)in.s6_addr[5], - (int)in.s6_addr[6] , (int)in.s6_addr[7], - (int)in.s6_addr[8] , (int)in.s6_addr[9], - (int)in.s6_addr[10], (int)in.s6_addr[11], - (int)in.s6_addr[12], (int)in.s6_addr[13], - (int)in.s6_addr[14], (int)in.s6_addr[15]); - return str; -} diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index 16bc55386..b2e0e7cf8 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -94,7 +94,6 @@ std::ostream& operator<<(std::ostream& o, const sockaddr_storage&); /* thread-safe version of inet_ntoa */ std::string rs_inet_ntoa(struct in_addr in); -std::string rs_inet_ntoa(const in6_addr &in); /***************************/ From 91a35f4a21e9320ff81f0b7433a8e3bb35f5a4b6 Mon Sep 17 00:00:00 2001 From: Phenom Date: Thu, 4 Nov 2021 13:10:15 +0100 Subject: [PATCH 4/4] Change some code according G10h4ck remarks. --- libretroshare/src/pqi/p3netmgr.cc | 109 +++++++------- libretroshare/src/rsserver/p3peers.cc | 37 +++-- libretroshare/src/util/extaddrfinder.cc | 120 ++++++++-------- libretroshare/src/util/extaddrfinder.h | 4 +- libretroshare/src/util/rsdnsutils.cc | 136 +++++++++--------- libretroshare/src/util/rsnet.cc | 14 ++ libretroshare/src/util/rsnet.h | 23 ++- libretroshare/src/util/rsnet_ss.cc | 7 +- .../src/gui/settings/ServerPage.cpp | 4 +- 9 files changed, 242 insertions(+), 212 deletions(-) diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 5b4a6f692..21e45ac16 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -47,15 +47,15 @@ struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"}; /* Network setup States */ -const uint32_t RS_NET_NEEDS_RESET = 0x0000; -const uint32_t RS_NET_UNKNOWN = 0x0001; -const uint32_t RS_NET_UPNP_INIT = 0x0002; -const uint32_t RS_NET_UPNP_SETUP = 0x0003; -const uint32_t RS_NET_EXT_SETUP = 0x0004; -const uint32_t RS_NET_DONE = 0x0005; -const uint32_t RS_NET_LOOPBACK = 0x0006; -//const uint32_t RS_NET_DOWN = 0x0007; -const uint32_t RS_NET_SHUTDOWN = 0x00FF; //Highest value to not restart UPnP nor ExtAddrFinder +constexpr uint32_t RS_NET_NEEDS_RESET = 0x0000; +constexpr uint32_t RS_NET_UNKNOWN = 0x0001; +constexpr uint32_t RS_NET_UPNP_INIT = 0x0002; +constexpr uint32_t RS_NET_UPNP_SETUP = 0x0003; +constexpr uint32_t RS_NET_EXT_SETUP = 0x0004; +constexpr uint32_t RS_NET_DONE = 0x0005; +constexpr uint32_t RS_NET_LOOPBACK = 0x0006; +//constexpr uint32_t RS_NET_DOWN = 0x0007; +constexpr uint32_t RS_NET_SHUTDOWN = 0x00FF; //Highest value to not restart UPnP nor ExtAddrFinder /* Stun modes (TODO) */ //const uint32_t RS_STUN_DHT = 0x0001; @@ -118,7 +118,7 @@ p3NetMgrIMPL::p3NetMgrIMPL() { { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mExtAddrFinder = new ExtAddrFinder(); @@ -233,7 +233,7 @@ void p3NetMgrIMPL::netReset() shutdown(); /* blocking shutdown call */ { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStatus = RS_NET_UNKNOWN; } @@ -266,7 +266,7 @@ void p3NetMgrIMPL::netReset() * as it calls back to p3ConnMgr. */ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ struct sockaddr_storage iaddr = mLocalAddr; @@ -284,7 +284,7 @@ void p3NetMgrIMPL::netReset() } { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ netStatusReset_locked(); } @@ -311,7 +311,7 @@ bool p3NetMgrIMPL::shutdown() /* blocking shutdown call */ std::cerr << std::endl; #endif { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStatus = RS_NET_SHUTDOWN; mNetInitTS = time(NULL); netStatusReset_locked(); @@ -347,7 +347,7 @@ void p3NetMgrIMPL::netStartup() */ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetInitTS = time(NULL); netStatusReset_locked(); @@ -462,7 +462,7 @@ void p3NetMgrIMPL::netStatusTick() rstime_t age = 0; bool needExtFinderUpdate = false; { - RsStackMutex stack(mNetMtx); /************** LOCK MUTEX ***************/ + RS_STACK_MUTEX(mNetMtx); /************** LOCK MUTEX ***************/ netStatus = mNetStatus; age = time(NULL) - mNetInitTS; @@ -477,9 +477,10 @@ void p3NetMgrIMPL::netStatusTick() && ( netStatus <= RS_NET_UPNP_SETUP || needExtFinderUpdate) ) { - sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family + sockaddr_storage tmpip; + sockaddr_storage_copy( mLocalAddr, tmpip); // copies local port and correctly inits the IP family #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RsDbg(__PRETTY_FUNCTION__, " Asking ExtAddrFinder for IP. Initializing port with ", sockaddr_storage_port(tmpip)); + RS_DBG("Asking ExtAddrFinder for IP. Initializing port with ", sockaddr_storage_port(tmpip)); #endif if(mExtAddrFinder->hasValidIPV4(tmpip)) @@ -487,7 +488,7 @@ void p3NetMgrIMPL::netStatusTick() if(!sockaddr_storage_same(tmpip,mExtAddr)) { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RsDbg(__PRETTY_FUNCTION__, " Ext supplied by ExtAddrFinder", " ExtAddr: ", sockaddr_storage_tostring(tmpip)); + RS_DBG("Ext supplied by ExtAddrFinder. ExtAddr: ", tmpip); #endif setExtAddress(tmpip); } @@ -498,7 +499,7 @@ void p3NetMgrIMPL::netStatusTick() { //Only if no IPv4 else, reset connections on setExtAddress() #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RsDbg(__PRETTY_FUNCTION__, " Ext supplied by ExtAddrFinder", " ExtAddr: ", sockaddr_storage_tostring(tmpip)); + RS_DBG("Ext supplied by ExtAddrFinder. ExtAddr: ", tmpip); #endif setExtAddress(tmpip); } @@ -593,7 +594,7 @@ void p3NetMgrIMPL::netDhtInit() uint32_t vs = 0; { - RsStackMutex stack(mNetMtx); /*********** LOCKED MUTEX ************/ + RS_STACK_MUTEX(mNetMtx); /*********** LOCKED MUTEX ************/ vs = mVsDht; } @@ -760,16 +761,14 @@ void p3NetMgrIMPL::netExtCheck() if (mUseExtAddrFinder) { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RsDbg(__PRETTY_FUNCTION__, " checking ExtAddrFinder"); + RS_DBG("checking ExtAddrFinder"); #endif - sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family + sockaddr_storage tmpip; + sockaddr_storage_copy( mLocalAddr, tmpip); // copies local port and correctly inits the IP family // Test for IPv4 first to be compatible with older versions. if (mExtAddrFinder->hasValidIPV4(tmpip)) { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RsDbg(__PRETTY_FUNCTION__, " Ext IPv4 supplied by ExtAddrFinder", sockaddr_storage_tostring(tmpip)); -#endif sockaddr_storage_setport(tmpip, guessNewExtPort()); mNetFlags.mExtAddrOk = true; @@ -781,13 +780,10 @@ void p3NetMgrIMPL::netExtCheck() * (which it is not normally) */ mNetFlags.mExtAddrStableOk = true; - RsErr(__PRETTY_FUNCTION__, " reported external IPv4 address ", sockaddr_storage_iptostring(tmpip)); + RS_DBG("Reported external IPv4 address ", sockaddr_storage_iptostring(tmpip)); } else if (mExtAddrFinder->hasValidIPV6(tmpip)) { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RsDbg(__PRETTY_FUNCTION__, " Ext IPv6 supplied by ExtAddrFinder", sockaddr_storage_tostring(tmpip)); -#endif sockaddr_storage_setport(tmpip, guessNewExtPort()); mNetFlags.mExtAddrOk = true; @@ -799,7 +795,7 @@ void p3NetMgrIMPL::netExtCheck() * (which it is not normally) */ mNetFlags.mExtAddrStableOk = true; - RsErr(__PRETTY_FUNCTION__, " reported external IPv6 address ", sockaddr_storage_iptostring(tmpip)); + RS_DBG("Reported external IPv6 address ", sockaddr_storage_iptostring(tmpip)); } } } @@ -990,7 +986,7 @@ void p3NetMgrIMPL::netExtCheck() if (netSetupDone) { - RsDbg(__PRETTY_FUNCTION__, " netSetupDone"); + RS_DBG("netSetupDone"); /* Setup NetStateBox with this info */ updateNetStateBox_startup(); @@ -1008,7 +1004,7 @@ void p3NetMgrIMPL::netExtCheck() netAssistKnownPeer(fakeId, mExtAddr, NETASSIST_KNOWN_PEER_SELF | NETASSIST_KNOWN_PEER_ONLINE); } - RsDbg(__PRETTY_FUNCTION__, " Network Setup Complete"); + RS_INFO("Network Setup Complete"); } } @@ -1093,8 +1089,7 @@ bool p3NetMgrIMPL::checkNetAddress() if (!validAddr) { - RsErr() << __PRETTY_FUNCTION__ << " no valid local network address " - <<" found. Report to developers." << std::endl; + RS_ERR("no valid local network address found. Report to developers."); print_stacktrace(); return false; @@ -1179,7 +1174,7 @@ bool p3NetMgrIMPL::checkNetAddress() /* to allow resets of network stuff */ void p3NetMgrIMPL::addNetListener(pqiNetListener *listener) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetListeners.push_back(listener); } @@ -1189,7 +1184,7 @@ bool p3NetMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr) { bool changed = false; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ if (!sockaddr_storage_same(mLocalAddr, addr)) { changed = true; @@ -1211,7 +1206,7 @@ bool p3NetMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr) } bool p3NetMgrIMPL::getExtAddress(struct sockaddr_storage& addr) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ if(mNetFlags.mExtAddrOk) { @@ -1226,7 +1221,7 @@ bool p3NetMgrIMPL::setExtAddress(const struct sockaddr_storage &addr) { bool changed = false; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ if (!sockaddr_storage_same(mExtAddr, addr)) { changed = true; @@ -1260,7 +1255,7 @@ bool p3NetMgrIMPL::setNetworkMode(uint32_t netMode) { uint32_t oldNetMode; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ /* only change TRY flags */ oldNetMode = mNetMode; @@ -1306,7 +1301,7 @@ bool p3NetMgrIMPL::setNetworkMode(uint32_t netMode) bool p3NetMgrIMPL::setVisState(uint16_t vs_disc, uint16_t vs_dht) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mVsDisc = vs_disc; mVsDht = vs_dht; @@ -1668,7 +1663,7 @@ void p3NetMgrIMPL::getNetStatus(pqiNetStatus &status) uint32_t netsize = 0, rsnetsize = 0; netAssistConnectStats(netsize, rsnetsize); - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ /* quick update of the stuff that can change! */ mNetFlags.mDhtOk = dhtOk; @@ -1692,7 +1687,7 @@ void p3NetMgrIMPL::getNetStatus(pqiNetStatus &status) bool p3NetMgrIMPL::getIPServersEnabled() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mUseExtAddrFinder; } @@ -1721,12 +1716,12 @@ void p3NetMgrIMPL::setIPServersEnabled(bool b) } { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mUseExtAddrFinder = b; } #ifdef NETMGR_DEBUG - RsDbg(__PRETTY_FUNCTION__, " set mUseExtAddrFinder to ", b); + RS_DBG("set mUseExtAddrFinder to ", b); #endif } @@ -1739,31 +1734,31 @@ void p3NetMgrIMPL::setIPServersEnabled(bool b) RsNetState p3NetMgrIMPL::getNetStateMode() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getNetStateMode(); } RsNetworkMode p3NetMgrIMPL::getNetworkMode() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getNetworkMode(); } RsNatTypeMode p3NetMgrIMPL::getNatTypeMode() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getNatTypeMode(); } RsNatHoleMode p3NetMgrIMPL::getNatHoleMode() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getNatHoleMode(); } RsConnectModes p3NetMgrIMPL::getConnectModes() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getConnectModes(); } @@ -1787,7 +1782,7 @@ void p3NetMgrIMPL::updateNetStateBox_temporal() /* input network bits */ if (mDhtStunner->getExternalAddr(tmpaddr, isstable)) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStateBox.setAddressStunDht(tmpaddr, isstable); #ifdef NETMGR_DEBUG_STATEBOX @@ -1806,7 +1801,7 @@ void p3NetMgrIMPL::updateNetStateBox_temporal() /* input network bits */ if (mProxyStunner->getExternalAddr(tmpaddr, isstable)) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStateBox.setAddressStunProxy(tmpaddr, isstable); #ifdef NETMGR_DEBUG_STATEBOX @@ -1825,7 +1820,7 @@ void p3NetMgrIMPL::updateNetStateBox_temporal() bool dhtOn = netAssistConnectEnabled(); bool dhtActive = netAssistConnectActive(); - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStateBox.setDhtState(dhtOn, dhtActive); } @@ -1834,7 +1829,7 @@ void p3NetMgrIMPL::updateNetStateBox_temporal() #ifdef NETMGR_DEBUG_STATEBOX { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ auto netstate = mNetStateBox.getNetStateMode(); auto netMode = mNetStateBox.getNetworkMode(); @@ -1880,7 +1875,7 @@ void p3NetMgrIMPL::updateNatSetting() RsNatTypeMode natType = RsNatTypeMode::UNKNOWN; RsNatHoleMode natHole = RsNatHoleMode::UNKNOWN; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ natType = mNetStateBox.getNatTypeMode(); natHole = mNetStateBox.getNatHoleMode(); @@ -1982,7 +1977,7 @@ void p3NetMgrIMPL::updateNetStateBox_startup() std::cerr << std::endl; #endif { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ /* fill in the data */ struct sockaddr_storage tmpip; @@ -2077,7 +2072,7 @@ void p3NetMgrIMPL::updateNetStateBox_startup() void p3NetMgrIMPL::updateNetStateBox_reset() { { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStateBox.reset(); diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index 16dda2a75..7011d7aef 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -1293,7 +1293,11 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros } #else sockaddr_storage tLocal; - if(sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) && sockaddr_storage_isValidNet(tLocal) && sockaddr_storage_ipv6_to_ipv4(tLocal) && tDetails.localPort ) + bool validLoc = sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) + && sockaddr_storage_isValidNet(tLocal) + && tDetails.localPort; + bool isLocIpv4 = sockaddr_storage_ipv6_to_ipv4(tLocal); + if(validLoc && isLocIpv4) { uint32_t t4Addr = reinterpret_cast(tLocal).sin_addr.s_addr; @@ -1311,8 +1315,11 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros } sockaddr_storage tExt; - struct in6_addr sin6_addr; - if(sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && sockaddr_storage_isValidNet(tExt) && sockaddr_storage_ipv6_to_ipv4(tExt) && tDetails.extPort ) + bool validExt = sockaddr_storage_inet_pton(tExt, tDetails.extAddr) + && sockaddr_storage_isValidNet(tExt) + && tDetails.extPort; + bool isExtIpv4 = sockaddr_storage_ipv6_to_ipv4(tExt); + if(validExt && isExtIpv4) { uint32_t t4Addr = reinterpret_cast(tExt).sin_addr.s_addr; @@ -1328,10 +1335,11 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros offset += 4+2; } - else if(inet_pton(AF_INET6, tDetails.extAddr.c_str(), &(sin6_addr))) + else if(validExt && !isExtIpv4) { // External address is IPv6, save it on LOCATOR - std::string tLocator = "ipv6://[" + tDetails.extAddr + "]:" + std::to_string(tDetails.extPort); + sockaddr_storage_setport(tExt,tDetails.extPort); + std::string tLocator = sockaddr_storage_tostring(tExt); addPacketHeader(RsShortInviteFieldType::LOCATOR, tLocator.size(),buf,offset,buf_size); memcpy(&buf[offset],tLocator.c_str(),tLocator.size()); @@ -1612,16 +1620,23 @@ std::string p3Peers::GetRetroshareInvite( const RsPeerId& sslId, RetroshareInvit if (getPeerDetails(ssl_id, detail)) { - if(!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) || detail.isHiddenNode) + if( !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) + || detail.isHiddenNode) detail.ipAddressList.clear(); //Check if external address is IPv6, then move it to ipAddressList as RsCertificate only allow 4 numbers. - struct in6_addr sin6_addr; - if( inet_pton(AF_INET6, detail.extAddr.c_str(), &(sin6_addr)) - && !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) - && !detail.isHiddenNode) + sockaddr_storage tExt; + bool validExt = sockaddr_storage_inet_pton(tExt, detail.extAddr) + && sockaddr_storage_isValidNet(tExt) + && detail.extPort; + bool isExtIpv4 = sockaddr_storage_ipv6_to_ipv4(tExt); + + if( !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) + && !detail.isHiddenNode + && validExt && !isExtIpv4) { - detail.ipAddressList.push_front("ipv6://[" + detail.extAddr + "]:" + std::to_string(detail.extPort) + " "); + sockaddr_storage_setport(tExt,detail.extPort); + detail.ipAddressList.push_front(sockaddr_storage_tostring(tExt) + " "); // Space needed to later parse. detail.extAddr = ""; //Clear it to not trigg error. detail.extPort = 0; } diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc index fa487c63e..03b9f33a9 100644 --- a/libretroshare/src/util/extaddrfinder.cc +++ b/libretroshare/src/util/extaddrfinder.cc @@ -19,6 +19,9 @@ * along with this program. If not, see . * * * *******************************************************************************/ + +//#define EXTADDRSEARCH_DEBUG + #include "extaddrfinder.h" #include "pqi/pqinetwork.h" @@ -43,8 +46,6 @@ const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ -//#define EXTADDRSEARCH_DEBUG - class ZeroInt { public: @@ -52,129 +53,122 @@ public: uint32_t n ; }; -void* doExtAddrSearch(void *p) +void ExtAddrFinder::run() { std::vector res ; - ExtAddrFinder *af = (ExtAddrFinder*)p ; - - for(std::list::const_iterator it(af->_ip_servers.begin());it!=af->_ip_servers.end();++it) + for(auto& it : _ip_servers) { std::string ip = ""; - rsGetHostByNameSpecDNS(*it,"myip.opendns.com",ip,2); + rsGetHostByNameSpecDNS(it,"myip.opendns.com",ip,2); if(ip != "") res.push_back(ip) ; #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " ip found through DNS ", *it, ": \"", ip, "\""); + RS_DBG("ip found through DNS ", it, ": \"", ip, "\""); #endif } if(res.empty()) { - af->reset(); - return NULL ; + reset(); + return ; } std::map addrV4_votes; std::map addrV6_votes; - std::string addrV4_Found; - std::string addrV6_Found; + std::string all_addrV4_Found; + std::string all_addrV6_Found; for(auto curRes : res) { sockaddr_storage addr; sockaddr_storage_clear(addr); - //sockaddr_storage_inet_pton convert IPv4 to IPv6 - struct sockaddr_in * addrv4p = (struct sockaddr_in *) &addr; - struct sockaddr_in6 * addrv6p = (struct sockaddr_in6 *) &addr; - if( inet_pton(AF_INET, curRes.c_str(), &(addrv4p->sin_addr)) ) + bool validIP = sockaddr_storage_inet_pton(addr, curRes) + && sockaddr_storage_isValidNet(addr); + bool isIPv4 = sockaddr_storage_ipv6_to_ipv4(addr); + if( validIP && isIPv4 ) { addr.ss_family = AF_INET; addrV4_votes[addr].n++ ; - addrV4_Found += sockaddr_storage_tostring(addr) + "\n"; + all_addrV4_Found += sockaddr_storage_tostring(addr) + "\n"; } - else if( inet_pton(AF_INET6, curRes.c_str(), &(addrv6p->sin6_addr)) ) + else if( validIP && !isIPv4) { addr.ss_family = AF_INET6; addrV6_votes[addr].n++ ; - addrV6_Found += sockaddr_storage_tostring(addr) + "\n"; + all_addrV6_Found += sockaddr_storage_tostring(addr) + "\n"; } else - RsErr(__PRETTY_FUNCTION__, " Invalid addresse reported: ", curRes) ; + RS_ERR("Invalid addresse reported: ", curRes) ; } if( (0 == addrV4_votes.size()) && (0 == addrV6_votes.size()) ) { - RsErr(__PRETTY_FUNCTION__, " Could not find any external address."); - af->reset(); - return NULL ; + RS_ERR("Could not find any external address."); + reset(); + return ; } if( 1 < addrV4_votes.size() ) - RsErr(__PRETTY_FUNCTION__, " Multiple external IPv4 addresses reported: " - , addrV4_Found ) ; + RS_ERR("Multiple external IPv4 addresses reported: " + , all_addrV4_Found ) ; if( 1 < addrV6_votes.size() ) - RsErr(__PRETTY_FUNCTION__, " Multiple external IPv6 addresses reported: " - , addrV6_Found ) ; + RS_ERR("Multiple external IPv6 addresses reported: " + , all_addrV6_Found ) ; { - RsStackMutex mtx(af->mAddrMtx) ; - af->mSearching = false ; - af->mFoundTS = time(NULL) ; + RS_STACK_MUTEX(mAddrMtx); + + mSearching = false ; + mFoundTS = time(NULL) ; // Only save more reported address if not only once. uint32_t admax = 0 ; - sockaddr_storage_clear(af->mAddrV4); + sockaddr_storage_clear(mAddrV4); for (auto it : addrV4_votes) if (admax < it.second.n) { - af->mAddrV4 = it.first ; - af->mFoundV4 = true ; + mAddrV4 = it.first ; + mFoundV4 = true ; admax = it.second.n ; } admax = 0 ; - sockaddr_storage_clear(af->mAddrV6); + sockaddr_storage_clear(mAddrV6); for (auto it : addrV6_votes) if (admax < it.second.n) { - af->mAddrV6 = it.first ; - af->mFoundV6 = true ; + mAddrV6 = it.first ; + mFoundV6 = true ; admax = it.second.n ; } } - return NULL ; + return ; } - void ExtAddrFinder::start_request() { - void *data = (void *)this; - pthread_t tid ; - - if(! pthread_create(&tid, 0, &doExtAddrSearch, data)) - pthread_detach(tid); /* so memory is reclaimed in linux */ - else - RsErr(__PRETTY_FUNCTION__, " Could not start ExtAddrFinder thread."); + if (!isRunning()) + start("ExtAddrFinder"); } bool ExtAddrFinder::hasValidIPV4(struct sockaddr_storage &addr) { #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " Getting ip."); + RS_DBG("Getting ip."); #endif { - RsStackMutex mut(mAddrMtx) ; + RS_STACK_MUTEX(mAddrMtx) ; if(mFoundV4) { #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV4)) ; + RS_DBG("Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV4)) ; #endif sockaddr_storage_copyip(addr,mAddrV4); // just copy the IP so we dont erase the port. } @@ -182,22 +176,22 @@ bool ExtAddrFinder::hasValidIPV4(struct sockaddr_storage &addr) testTimeOut(); - RsStackMutex mut(mAddrMtx) ; + RS_STACK_MUTEX(mAddrMtx) ; return mFoundV4; } bool ExtAddrFinder::hasValidIPV6(struct sockaddr_storage &addr) { #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " Getting ip."); + RS_DBG("Getting ip."); #endif { - RsStackMutex mut(mAddrMtx) ; + RS_STACK_MUTEX(mAddrMtx) ; if(mFoundV6) { #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV6)) ; + RS_DBG("Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV6)) ; #endif sockaddr_storage_copyip(addr,mAddrV6); // just copy the IP so we dont erase the port. } @@ -205,7 +199,7 @@ bool ExtAddrFinder::hasValidIPV6(struct sockaddr_storage &addr) testTimeOut(); - RsStackMutex mut(mAddrMtx) ; + RS_STACK_MUTEX(mAddrMtx) ; return mFoundV6; } @@ -213,7 +207,7 @@ void ExtAddrFinder::testTimeOut() { bool timeOut; { - RsStackMutex mut(mAddrMtx) ; + RS_STACK_MUTEX(mAddrMtx) ; //timeout the current ip timeOut = (mFoundTS + MAX_IP_STORE < time(NULL)); } @@ -223,21 +217,21 @@ void ExtAddrFinder::testTimeOut() if(!mSearching) { #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " No stored ip: Initiating new search."); + RS_DBG("No stored ip: Initiating new search."); #endif mSearching = true ; start_request() ; } #ifdef EXTADDRSEARCH_DEBUG else - RsDbg(__PRETTY_FUNCTION__, " Already searching."); + RS_DBG("Already searching."); #endif mFirstTime = false; mAddrMtx.unlock(); } #ifdef EXTADDRSEARCH_DEBUG else - RsDbg(__PRETTY_FUNCTION__, " (Note) Could not acquire lock. Busy."); + RS_DBG("(Note) Could not acquire lock. Busy."); #endif } } @@ -245,15 +239,15 @@ void ExtAddrFinder::testTimeOut() void ExtAddrFinder::reset(bool firstTime /*=false*/) { #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " firstTime=", firstTime?"true":"false"); + RS_DBG("firstTime=", firstTime); #endif - RsStackMutex mut(mAddrMtx) ; + RS_STACK_MUTEX(mAddrMtx) ; mSearching = false ; mFoundV4 = false ; mFoundV6 = false ; mFirstTime = firstTime; - mFoundTS = time(NULL); + mFoundTS = time(nullptr); sockaddr_storage_clear(mAddrV4); sockaddr_storage_clear(mAddrV6); } @@ -261,15 +255,14 @@ void ExtAddrFinder::reset(bool firstTime /*=false*/) ExtAddrFinder::~ExtAddrFinder() { #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " Deleting ExtAddrFinder."); + RS_DBG("Deleting ExtAddrFinder."); #endif - } ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder") { #ifdef EXTADDRSEARCH_DEBUG - RsDbg(__PRETTY_FUNCTION__, " Creating new ExtAddrFinder."); + RS_DBG("Creating new ExtAddrFinder."); #endif reset( true ); @@ -283,4 +276,3 @@ ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder") _ip_servers.push_back(std::string( "2620:119:35::35" )) ;//resolver1.opendns.com _ip_servers.push_back(std::string( "2620:119:53::53" )) ;//resolver2.opendns.com } - diff --git a/libretroshare/src/util/extaddrfinder.h b/libretroshare/src/util/extaddrfinder.h index bf7bfd878..1a2360bab 100644 --- a/libretroshare/src/util/extaddrfinder.h +++ b/libretroshare/src/util/extaddrfinder.h @@ -30,7 +30,7 @@ struct sockaddr ; -class ExtAddrFinder +class ExtAddrFinder: public RsThread { public: ExtAddrFinder() ; @@ -45,7 +45,7 @@ class ExtAddrFinder void reset(bool firstTime = false) ; private: - friend void* doExtAddrSearch(void *p); + virtual void run(); void testTimeOut(); RsMutex mAddrMtx; diff --git a/libretroshare/src/util/rsdnsutils.cc b/libretroshare/src/util/rsdnsutils.cc index cfe8418b7..46564c0a4 100644 --- a/libretroshare/src/util/rsdnsutils.cc +++ b/libretroshare/src/util/rsdnsutils.cc @@ -21,6 +21,7 @@ *******************************************************************************/ //#define DEBUG_SPEC_DNS 1 + #include "util/rsnet.h" #include "util/rsdebug.h" @@ -101,51 +102,49 @@ struct RR_DATA bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr, int timeout_s /*= -1*/) { #ifdef DEBUG_SPEC_DNS - RsDbg()<<__PRETTY_FUNCTION__<<" servername="<< servername << " hostname=" << hostname << std::endl; + RS_DBG("servername=", servername, " hostname=", hostname); #endif if (strlen(servername.c_str()) > 256) { - RsErr()<<__PRETTY_FUNCTION__<<": servername is too long > 256 chars:"< 256 chars: ", servername); return false; } if (strlen(hostname.c_str()) > 256) { - RsErr()<<__PRETTY_FUNCTION__<<": hostname is too long > 256 chars:"< 256 chars: ", hostname); return false; } - bool isIPV4 = false; - in_addr dns_server_4; in6_addr dns_server_6; - if (inet_pton(AF_INET, servername.c_str(), &dns_server_4)) - isIPV4 = true; - else if (inet_pton(AF_INET6, servername.c_str(), &dns_server_6)) - isIPV4 = false; - else if (rsGetHostByName(servername, dns_server_4)) - isIPV4 = true; - else + sockaddr_storage serverAddr; + bool validServer = sockaddr_storage_inet_pton(serverAddr, servername) + && sockaddr_storage_isValidNet(serverAddr); + bool isIPV4 = validServer && sockaddr_storage_ipv6_to_ipv4(serverAddr); + + if (!validServer) { - RsErr()<<__PRETTY_FUNCTION__<<": servername is on an unknow format: "<id = static_cast(htons(getpid())); //Transaction Id //dns flags = 0x0100 Standard Query @@ -191,86 +190,81 @@ bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& ho curSendSize += sizeof(struct QUESTION); #ifdef DEBUG_SPEC_DNS - RsDbg()<<__PRETTY_FUNCTION__<< " Sending Packet: " << std::endl << hexDump(buf, curSendSize) << std::endl; + RS_DBG("Sending Packet:\n", hexDump(buf, curSendSize)); #endif - int s = isIPV4 ? socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP) - : socket(AF_INET6 , SOCK_DGRAM , IPPROTO_UDP) ; //UDP packet for DNS queries + int s = socket(serverAddr.ss_family , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries + if (timeout_s > -1) - { -#ifdef WINDOWS_SYS - DWORD timeout = timeout_s * 1000; - setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout); -#else - struct timeval tv; - tv.tv_sec = timeout_s; - tv.tv_usec = 0; - setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); -#endif - } - ssize_t send_size = sendto(s, (char*)buf, curSendSize, 0 - ,isIPV4 ? (struct sockaddr*)&dest4 - : (struct sockaddr*)&dest6 - ,isIPV4 ? sizeof(dest4) - : sizeof(dest6) + rs_setSockTimeout(s, true, timeout_s); + + ssize_t send_size = sendto( s, (char*)buf, curSendSize, 0 + , (struct sockaddr*)&serverAddr + , isIPV4 ? sizeof(sockaddr_in) + : sizeof(sockaddr_in6) ); if( send_size < 0) { - RsErr()<<__PRETTY_FUNCTION__<<": Send Failed with size = " << send_size << std::endl; + RS_ERR("Send Failed with size = ", send_size); return false; } #ifdef DEBUG_SPEC_DNS - RsDbg()<<__PRETTY_FUNCTION__<< " Waiting answer..." << std::endl; + RS_DBG("Waiting answer..."); #endif //****************************************************************************************// //--- Receive the answer ---// //****************************************************************************************// - socklen_t dest_size = static_cast(sizeof dest4); - ssize_t rec_size=recvfrom(s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest4 , &dest_size ); + socklen_t sa_size = static_cast(isIPV4 ? sizeof(sockaddr_in) + : sizeof(sockaddr_in6) + ); + ssize_t rec_size=recvfrom( s,(char*)buf , 65536 , 0 + , (struct sockaddr*)&serverAddr + , &sa_size + ); if(rec_size <= 0) { - RsErr()<<__PRETTY_FUNCTION__<<": Receive Failed"<(sizeof(struct DNS_HEADER)) ) { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get DNSHeader."<q_count) << " Questions." << std::endl - <ans_count) << " Answers." << std::endl - <auth_count) << " Authoritative Servers." << std::endl - <add_count) << " Additional records." << std::endl; + RS_DBG("The response contains :\n" + ,ntohs(dns->q_count) , " Questions.\n" + ,ntohs(dns->ans_count) , " Answers.\n" + ,ntohs(dns->auth_count) , " Authoritative Servers.\n" + ,ntohs(dns->add_count) , " Additional records."); #endif size_t curRecSize = sizeof(struct DNS_HEADER); if (rec_size< static_cast(curRecSize + 1 + sizeof(struct QUESTION)) ) { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Question return."<(&buf[curRecSize]); if (memcmp(qname,qnameRecv,qnameSize + 1 + sizeof(struct QUESTION)) ) { - RsErr()<<__PRETTY_FUNCTION__<<": Request received different from that sent."<(curRecSize + 2) ) { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Answer return."<(curRecSize + sizeof(struct RR_DATA)) ) { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Data return."<rtype!=qinfo->qtype) { - RsErr()<<__PRETTY_FUNCTION__<<": Answer's type received different from query sent."<rclass!=qinfo->qclass) { - RsErr()<<__PRETTY_FUNCTION__<<": Answer's class received different from query sent."<(curRecSize + ntohs(rec_data->data_len)) ) { - RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Full Data return."<clear(); + detail.ipAddressList.sort(); for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(*it)); @@ -827,7 +828,7 @@ void ServerPage::ipWhiteListContextMenu(const QPoint& /* point */) // QString range0 = RsNetUtil::printAddrRange(addr,0) ; // QString range1 = RsNetUtil::printAddrRange(addr,1) ; // QString range2 = RsNetUtil::printAddrRange(addr,2) ; - +// // contextMenu.addAction(QObject::tr("Whitelist only IP " )+range0,this,SLOT(enableBannedIp()))->setEnabled(false) ; //#warning UNIMPLEMENTED CODE // contextMenu.addAction(QObject::tr("Whitelist entire range ")+range1,this,SLOT(enableBannedIp()))->setEnabled(false) ; @@ -1180,6 +1181,7 @@ void ServerPage::loadHiddenNode() // show what we have in ipAddresses. (should be nothing!) ui.ipAddressList->clear(); + detail.ipAddressList.sort(); for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(*it));