diff --git a/db.cpp b/db.cpp index b89904a..4acdeaa 100644 --- a/db.cpp +++ b/db.cpp @@ -166,7 +166,7 @@ void CAddrDb::Add_(const CAddress &addr, bool force) { nDirty++; } -void CAddrDb::GetIPs_(set& ips, int max, const bool* nets) { +void CAddrDb::GetIPs_(set& ips, int max, const bool* nets) { if (goodId.size() == 0) { int id = -1; if (ourId.size() == 0) { diff --git a/db.h b/db.h index 3fdebb0..e3050f0 100644 --- a/db.h +++ b/db.h @@ -102,7 +102,7 @@ public: } bool IsGood() const { - if (ip.GetPort() != GetDefaultPort()) return false; + /*if (ip.GetPort() != GetDefaultPort()) return false;*/ // [MF] we now permit non std ports if (!(services & NODE_NETWORK)) return false; if (!ip.IsRoutable()) return false; if (clientVersion && clientVersion < REQUIRE_VERSION) return false; @@ -220,7 +220,7 @@ protected: void Bad_(const CService &ip, int ban); // mark an IP as bad (and optionally ban it) (must have been returned by Get_) void Skipped_(const CService &ip); // mark an IP as skipped (must have been returned by Get_) int Lookup_(const CService &ip); // look up id of an IP - void GetIPs_(std::set& ips, int max, const bool *nets); // get a random set of IPs (shared lock only) + void GetIPs_(std::set& ips, int max, const bool *nets); // get a random set of IPs (shared lock only) public: std::map banned; // nodes that are banned, with their unban time (a) @@ -352,7 +352,7 @@ public: } } } - void GetIPs(std::set& ips, int max, const bool *nets) { + void GetIPs(std::set& ips, int max, const bool *nets) { SHARED_CRITICAL_BLOCK(cs) GetIPs_(ips, max, nets); } diff --git a/dns.c b/dns.c index 8b01458..108a036 100644 --- a/dns.c +++ b/dns.c @@ -269,6 +269,8 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi if (ret == -2) { error = 5; goto error; } int namel = strlen(name), hostl = strlen(opt->host); if (strcasecmp(name, opt->host) && (namelhost))) { error = 5; goto error; } + static char nonStdStr[] = "nonstd."; + int nonStd = (strncmp(name,nonStdStr,strlen(nonStdStr)) == 0); if (inend - inpos < 4) { error = 1; goto error; } // copy question to output memcpy(outbuf+12, inbuf+12, inpos+4 - (inbuf+12)); @@ -322,7 +324,12 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi // A/AAAA records if ((typ == TYPE_A || typ == TYPE_AAAA || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) { addr_t addr[32]; - int naddr = opt->cb((void*)opt, addr, 32, typ == TYPE_A || typ == QTYPE_ANY, typ == TYPE_AAAA || typ == QTYPE_ANY); + int naddr; + if( !nonStd) { + naddr = opt->cb((void*)opt, addr, 32, typ == TYPE_A || typ == QTYPE_ANY, typ == TYPE_AAAA || typ == QTYPE_ANY); + } else { + naddr = opt->cbNonStd((void*)opt, addr, 32, typ == TYPE_A || typ == QTYPE_ANY, typ == TYPE_AAAA || typ == QTYPE_ANY); + } int n = 0; while (n < naddr) { int ret = 1; diff --git a/dns.h b/dns.h index 97dd321..9f1240f 100644 --- a/dns.h +++ b/dns.h @@ -5,6 +5,7 @@ typedef struct { int v; + unsigned short port; union { unsigned char v4[4]; unsigned char v6[16]; @@ -19,6 +20,7 @@ typedef struct { const char *ns; const char *mbox; int (*cb)(void *opt, addr_t *addr, int max, int ipv4, int ipv6); + int (*cbNonStd)(void *opt, addr_t *addr, int max, int ipv4, int ipv6); // stats uint64_t nRequests; } dns_opt_t; diff --git a/main.cpp b/main.cpp index 88e9675..d6cc3b3 100644 --- a/main.cpp +++ b/main.cpp @@ -160,13 +160,16 @@ extern "C" void* ThreadCrawler(void* data) { } extern "C" int GetIPList(void *thread, addr_t *addr, int max, int ipv4, int ipv6); +extern "C" int GetIPListNonStd(void *thread, addr_t *addr, int max, int ipv4, int ipv6); class CDnsThread { public: dns_opt_t dns_opt; // must be first const int id; vector cache; + vector cacheNonStd; // [MF] non std port int nIPv4, nIPv6; + int nonStdIPv4, nonStdIPv6; time_t cacheTime; unsigned int cacheHits; uint64_t dbQueries; @@ -180,29 +183,43 @@ public: time_t now = time(NULL); cacheHits++; if (force || cacheHits > (cache.size()*cache.size()/400) || (cacheHits*cacheHits > cache.size() / 20 && (now - cacheTime > 5))) { - set ips; + set ips; db.GetIPs(ips, 1000, nets); dbQueries++; cache.clear(); - nIPv4 = 0; - nIPv6 = 0; + cacheNonStd.clear(); + nIPv4 = nonStdIPv4 = 0; + nIPv6 = nonStdIPv6 = 0; cache.reserve(ips.size()); - for (set::iterator it = ips.begin(); it != ips.end(); it++) { + cacheNonStd.reserve(ips.size()); + for (set::iterator it = ips.begin(); it != ips.end(); it++) { struct in_addr addr; struct in6_addr addr6; if ((*it).GetInAddr(&addr)) { addr_t a; a.v = 4; + a.port = (*it).GetPort(); memcpy(&a.data.v4, &addr, 4); - cache.push_back(a); - nIPv4++; + if( a.port == GetDefaultPort() ) { + cache.push_back(a); + nIPv4++; + } else { + cacheNonStd.push_back(a); + nonStdIPv4++; + } #ifdef USE_IPV6 } else if ((*it).GetIn6Addr(&addr6)) { addr_t a; a.v = 6; + a.port = (*it).GetPort(); memcpy(&a.data.v6, &addr6, 16); - cache.push_back(a); - nIPv6++; + if( a.port == GetDefaultPort() ) { + cache.push_back(a); + nIPv6++; + } else { + cacheNonStd.push_back(a); + nonStdIPv6++; + } #endif } } @@ -218,6 +235,7 @@ public: dns_opt.datattl = 60; dns_opt.nsttl = 40000; dns_opt.cb = GetIPList; + dns_opt.cbNonStd = GetIPListNonStd; dns_opt.port = opts->nPort; dns_opt.nRequests = 0; cache.clear(); @@ -235,6 +253,18 @@ public: } }; +unsigned short crc16(unsigned char* data_p, unsigned char length){ + unsigned char x; + unsigned short crc = 0xFFFF; + + while (length--){ + x = crc >> 8 ^ *data_p++; + x ^= x>>4; + crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x); + } + return crc; +} + extern "C" int GetIPList(void *data, addr_t* addr, int max, int ipv4, int ipv6) { CDnsThread *thread = (CDnsThread*)data; thread->cacheHit(); @@ -264,6 +294,48 @@ extern "C" int GetIPList(void *data, addr_t* addr, int max, int ipv4, int ipv6) return max; } +extern "C" int GetIPListNonStd(void *data, addr_t* addr, int max, int ipv4, int ipv6) { + CDnsThread *thread = (CDnsThread*)data; + thread->cacheHit(); + unsigned int size = thread->cacheNonStd.size(); + unsigned int maxmax = (ipv4 ? thread->nonStdIPv4 : 0) + (ipv6 ? thread->nonStdIPv6 : 0); + + if (max > 2 * size) + max = 2 * size; + if (max > 2 * maxmax) + max = 2 * maxmax; + max -= max % 2; + int i=0; + while (i+1cacheNonStd[j].v == 4) || + (ipv6 && thread->cacheNonStd[j].v == 6); + if (ok) break; + j++; + if (j==size) + j=i/2; + } while(1); + addr[i] = thread->cacheNonStd[j]; + thread->cacheNonStd[j] = thread->cacheNonStd[i/2]; + thread->cacheNonStd[i/2] = addr[i]; + + if( addr[i].v == 4 ) { + crcAddr = crc16(addr[i].data.v4,4); + } else { + crcAddr = crc16(addr[i].data.v6,16); + } + addr[i+1].v = 4; + addr[i+1].data.v4[0] = crcAddr >> 8; + addr[i+1].data.v4[1] = crcAddr & 0xff; + addr[i+1].data.v4[2] = addr[i].port >> 8; + addr[i+1].data.v4[3] = addr[i].port & 0xff; + i+=2; + } + return max; +} + vector dnsThread; extern "C" void* ThreadDNS(void* arg) {