69 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n",
74 std::string strUsage =
78 "\nUsage: bitcoin-seeder -host=<host> -ns=<ns> " 79 "[-mbox=<mbox>] [-threads=<threads>] [-port=<port>]\n\n" +
102 std::string flagString =
gArgs.
GetArg(
"-filter",
"");
103 size_t flagstartpos = 0;
104 while (flagstartpos < flagString.size()) {
105 size_t flagendpos = flagString.find_first_of(
',', flagstartpos);
106 uint64_t flag =
atoi64(flagString.substr(
107 flagstartpos, (flagendpos - flagstartpos)));
108 filter_whitelist.insert(flag);
109 if (flagendpos == std::string::npos) {
112 flagstartpos = flagendpos + 1;
115 if (filter_whitelist.empty()) {
125 argsman.
AddArg(
"-help-debug",
126 "Show all debugging options (usage: --help -help-debug)",
131 argsman.
AddArg(
"-version",
"Print version and exit",
133 argsman.
AddArg(
"-host=<host>",
"Hostname of the DNS seed",
135 argsman.
AddArg(
"-ns=<ns>",
"Hostname of the nameserver",
137 argsman.
AddArg(
"-mbox=<mbox>",
"E-Mail address reported in SOA records",
139 argsman.
AddArg(
"-threads=<threads>",
140 "Number of crawlers to run in parallel (default 96)",
142 argsman.
AddArg(
"-dnsthreads=<threads>",
143 "Number of DNS server threads (default 4)",
145 argsman.
AddArg(
"-port=<port>",
"UDP port to listen on (default 53)",
147 argsman.
AddArg(
"-onion=<ip:port>",
"Tor proxy IP/Port",
149 argsman.
AddArg(
"-proxyipv4=<ip:port>",
"IPV4 SOCKS5 proxy IP/Port",
151 argsman.
AddArg(
"-proxyipv6=<ip:port>",
"IPV6 SOCKS5 proxy IP/Port",
153 argsman.
AddArg(
"-filter=<f1,f2,...>",
154 "Allow these flag combinations as filters",
156 argsman.
AddArg(
"-wipeban",
"Wipe list of banned nodes",
158 argsman.
AddArg(
"-wipeignore",
"Wipe list of ignored nodes",
172 std::vector<CServiceResult> ips;
183 std::vector<CAddress> addr;
184 for (
size_t i = 0; i < ips.size(); i++) {
193 bool ret = node.
Run();
205 }
catch (std::ios_base::failure &e) {
217 extern "C" uint32_t
GetIPList(
void *thread,
char *requestedHostname,
218 addr_t *addr, uint32_t max, uint32_t ipv4,
237 void cacheHit(uint64_t requestedFlags,
bool force =
false) {
238 static bool nets[
NET_MAX] = {};
248 (thisflag.
cache.size() * thisflag.
cache.size()) ||
250 thisflag.
cache.size() &&
252 std::set<CNetAddr> ips;
253 db.
GetIPs(ips, requestedFlags, 1000, nets);
255 thisflag.
cache.clear();
258 thisflag.
cache.reserve(ips.size());
259 for (
auto &ip : ips) {
261 struct in6_addr addr6;
262 if (ip.GetInAddr(&addr)) {
265 memcpy(&a.
data.
v4, &addr, 4);
266 thisflag.
cache.push_back(a);
268 }
else if (ip.GetIn6Addr(&addr6)) {
271 memcpy(&a.
data.
v6, &addr6, 16);
272 thisflag.
cache.push_back(a);
283 dns_opt.
ns = opts->
ns.c_str();
286 dns_opt.
nsttl = 40000;
299 uint32_t max, uint32_t ipv4, uint32_t ipv6) {
302 uint64_t requestedFlags = 0;
303 int hostlen = strlen(requestedHostname);
304 if (hostlen > 1 && requestedHostname[0] ==
'x' &&
305 requestedHostname[1] !=
'0') {
307 uint64_t
flags = (uint64_t)strtoull(requestedHostname + 1, &pEnd, 16);
308 if (*pEnd ==
'.' && pEnd <= requestedHostname + 17 &&
312 requestedFlags =
flags;
316 }
else if (strcasecmp(requestedHostname, thread->
dns_opt.
host)) {
320 auto &thisflag = thread->
perflag[requestedFlags];
321 uint32_t size = thisflag.cache.size();
322 uint32_t maxmax = (ipv4 ? thisflag.nIPv4 : 0) + (ipv6 ? thisflag.nIPv6 : 0);
331 uint32_t j = i + (rand() % (size - i));
333 bool ok = (ipv4 && thisflag.cache[j].v == 4) ||
334 (ipv6 && thisflag.cache[j].v == 6);
343 addr[i] = thisflag.cache[j];
344 thisflag.cache[j] = thisflag.cache[i];
345 thisflag.cache[i] = addr[i];
375 Sleep(100000 << count);
381 std::vector<CAddrReport> v = db.
GetAll();
389 rename(
"dnsseed.dat.new",
"dnsseed.dat");
394 "lastSuccess %%(2h) %%(8h) %%(1d) %%(7d) " 395 "%%(30d) blocks svcs version\n");
396 double stat[5] = {0, 0, 0, 0, 0};
400 "%-47s %4d %11" PRId64
401 " %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6i %08" PRIx64
403 rep.ip.ToString(), (int)rep.fGood, rep.lastSuccess,
404 100.0 * rep.uptime[0], 100.0 * rep.uptime[1],
405 100.0 * rep.uptime[2], 100.0 * rep.uptime[3],
406 100.0 * rep.uptime[4], rep.blocks, rep.services,
407 rep.clientVersion, rep.clientSubVersion);
408 stat[0] += rep.uptime[0];
409 stat[1] += rep.uptime[1];
410 stat[2] += rep.uptime[2];
411 stat[3] += rep.uptime[3];
412 stat[4] += rep.uptime[4];
416 stat[1], stat[2], stat[3], stat[4]);
426 time_t tim = time(
nullptr);
427 struct tm *tmp = localtime(&tim);
428 strftime(c, 256,
"[%y-%m-%d %H:%M:%S]", tmp);
438 uint64_t requests = 0;
439 uint64_t queries = 0;
440 for (
unsigned int i = 0; i <
dnsThread.size(); i++) {
441 requests +=
dnsThread[i]->dns_opt.nRequests;
446 "%s %i/%i available (%i tried in %is, %i new, %i active), %i " 447 "banned; %llu DNS requests, %llu db queries\n",
450 stats.
nBanned, (
unsigned long long)requests,
451 (
unsigned long long)queries);
461 for (
const std::string &seed :
Params().DNSSeeds()) {
462 std::vector<CNetAddr> ips;
464 for (
auto &ip : ips) {
474 int main(
int argc,
char **argv) {
478 signal(SIGPIPE, SIG_IGN);
479 setbuf(stdout,
nullptr);
486 tfm::format(std::cout,
"Supporting whitelisted filters: ");
492 tfm::format(std::cout,
"0x%lx", (
unsigned long)*it);
495 if (!opts.
tor.empty()) {
521 if (opts.
ns.empty()) {
522 tfm::format(std::cout,
"No nameserver set. Not starting DNS server.\n");
525 if (fDNS && opts.
host.empty()) {
526 tfm::format(std::cerr,
"No hostname set. Please use -h.\n");
529 if (fDNS && opts.
mbox.empty()) {
530 tfm::format(std::cerr,
"No e-mail address set. Please use -m.\n");
548 pthread_t threadDns, threadSeed, threadDump, threadStats;
551 "Starting %i DNS threads for %s on %s (port %i)...",
563 pthread_create(&threadSeed,
nullptr,
ThreadSeeder,
nullptr);
566 pthread_attr_t attr_crawler;
567 pthread_attr_init(&attr_crawler);
568 pthread_attr_setstacksize(&attr_crawler, 0x20000);
569 for (
int i = 0; i < opts.
nThreads; i++) {
573 pthread_attr_destroy(&attr_crawler);
575 pthread_create(&threadStats,
nullptr,
ThreadStats,
nullptr);
576 pthread_create(&threadDump,
nullptr,
ThreadDumper,
nullptr);
578 pthread_join(threadDump, &res);
static const int DEFAULT_PORT
static unsigned short GetDefaultPort()
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
void cacheHit(uint64_t requestedFlags, bool force=false)
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
std::set< uint64_t > filterWhitelist
CService LookupNumeric(const std::string &name, int portDefault)
Resolve a service string with a numeric IP to its first corresponding service.
static const unsigned int MAX_HOSTS_PER_SEED
BCLog::Logger & LogInstance()
ServiceFlags
nServices flags.
FILE * fopen(const fs::path &p, const char *mode)
std::map< CService, int64_t > banned
void * ThreadDumper(void *)
std::vector< CDnsThread * > dnsThread
int ParseCommandLine(int argc, char **argv)
void SetupSeederArgs(ArgsManager &argsman)
static const bool DEFAULT_WIPE_BAN
static const std::string DEFAULT_NAMESERVER
NODISCARD bool ParseParameters(int argc, const char *const argv[], std::string &error)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
void * ThreadStats(void *)
void * ThreadDNS(void *arg)
CDnsThread(CDnsSeedOpts *opts, int idIn)
static const int DEFAULT_NUM_DNS_THREADS
std::string GetHelpMessage() const
Get the help string.
static const std::string DEFAULT_IPV6_PROXY
void ResultMany(const std::vector< CServiceResult > &ips)
void GetIPs(std::set< CNetAddr > &ips, uint64_t requestedFlags, uint32_t max, const bool *nets)
static const int DEFAULT_NUM_THREADS
static const std::string DEFAULT_HOST
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
A combination of a network address (CNetAddr) and a (TCP) port.
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
bool HelpRequested(const ArgsManager &args)
A CService with information about it as peer.
static const int CONTINUE_EXECUTION
static const std::string DEFAULT_IPV4_PROXY
static const std::string DEFAULT_TOR_PROXY
std::string GetClientSubVersion()
std::string FormatFullVersion()
bool SetProxy(enum Network net, const proxyType &addrProxy)
std::atomic< uint64_t > dbQueries
static const std::string DEFAULT_EMAIL
seen nodes / \ (a) banned nodes available nodes-----------— / | \ tracked n...
bool LookupHost(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Resolve a host string to its corresponding network addresses.
int64_t atoi64(const char *psz)
int StatCompare(const CAddrReport &a, const CAddrReport &b)
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
std::vector< CAddrReport > GetAll()
const CChainParams & Params()
Return the currently selected parameters.
std::vector< addr_t > cache
void Add(const CAddress &addr, bool fForce=false)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
std::string ToStringIPPort() const
void * ThreadCrawler(void *data)
std::map< uint64_t, FlagSpecificData > perflag
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
int main(int argc, char *argv[])
uint32_t(* cb)(void *opt, char *requested_hostname, addr_t *addr, uint32_t max, uint32_t ipv4, uint32_t ipv6)
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
std::set< uint64_t > filter_whitelist
int dnsserver(dns_opt_t *opt)
uint32_t GetIPList(void *thread, char *requestedHostname, addr_t *addr, uint32_t max, uint32_t ipv4, uint32_t ipv6)
void * ThreadSeeder(void *)
int64_t GetTime()
Return system time (or mocked time, if set)
static void Sleep(int nMilliSec)
void GetMany(std::vector< CServiceResult > &ips, int max, int &wait)
bool error(const char *fmt, const Args &... args)
void GetStats(CAddrDbStats &stats) const
Non-refcounted RAII wrapper for FILE*.
static const bool DEFAULT_WIPE_IGNORE