diff --git a/doc/release-notes.md b/doc/release-notes.md
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -3,3 +3,5 @@
This release includes the following features and fixes:
+ - bitcoin-seeder no longer takes single letter parameter name. Please use
+ full length parameter names. See `bitcoin-seeder -?` for more information.
diff --git a/src/seeder/README.md b/src/seeder/README.md
--- a/src/seeder/README.md
+++ b/src/seeder/README.md
@@ -33,10 +33,10 @@
On the system vps.example.com, you can now run dnsseed:
-./bitcoin-seeder -h dnsseed.example.com -n vps.example.com
+./bitcoin-seeder -host=dnsseed.example.com -ns=vps.example.com
If you want the DNS server to report SOA records, please provide an
-e-mail address (with the @ part replaced by .) using -m.
+e-mail address (with the @ part replaced by .) using -mbox.
RUNNING AS NON-ROOT
@@ -50,7 +50,7 @@
$ iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-port 5353
If properly configured, this will allow you to run dnsseed in userspace, using
-the -p 5353 option.
+the -post=5353 option.
Generate Seed Lists
-------------------
diff --git a/src/seeder/main.cpp b/src/seeder/main.cpp
--- a/src/seeder/main.cpp
+++ b/src/seeder/main.cpp
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#include
#include
@@ -13,160 +14,10 @@
#include
#include
#include
-#include
#include
const std::function G_TRANSLATION_FUN = nullptr;
-class CDnsSeedOpts {
-public:
- int nThreads;
- int nPort;
- int nDnsThreads;
- int fUseTestNet;
- int fWipeBan;
- int fWipeIgnore;
- const char *mbox;
- const char *ns;
- const char *host;
- const char *tor;
- const char *ipv4_proxy;
- const char *ipv6_proxy;
- std::set filter_whitelist;
-
- CDnsSeedOpts()
- : nThreads(96), nPort(53), nDnsThreads(4), fUseTestNet(false),
- fWipeBan(false), fWipeIgnore(false), mbox(nullptr), ns(nullptr),
- host(nullptr), tor(nullptr), ipv4_proxy(nullptr),
- ipv6_proxy(nullptr) {}
-
- void ParseCommandLine(int argc, char **argv) {
- static const char *help =
- "Bitcoin-cash-seeder\n"
- "Usage: %s -h -n [-m ] [-t ] [-p "
- "]\n"
- "\n"
- "Options:\n"
- "-h Hostname of the DNS seed\n"
- "-n Hostname of the nameserver\n"
- "-m E-Mail address reported in SOA records\n"
- "-t Number of crawlers to run in parallel (default "
- "96)\n"
- "-d Number of DNS server threads (default 4)\n"
- "-p UDP port to listen on (default 53)\n"
- "-o Tor proxy IP/Port\n"
- "-i IPV4 SOCKS5 proxy IP/Port\n"
- "-k IPV6 SOCKS5 proxy IP/Port\n"
- "-w f1,f2,... Allow these flag combinations as filters\n"
- "--testnet Use testnet\n"
- "--wipeban Wipe list of banned nodes\n"
- "--wipeignore Wipe list of ignored nodes\n"
- "-?, --help Show this text\n"
- "\n";
- bool showHelp = false;
-
- while (1) {
- static struct option long_options[] = {
- {"host", required_argument, 0, 'h'},
- {"ns", required_argument, 0, 'n'},
- {"mbox", required_argument, 0, 'm'},
- {"threads", required_argument, 0, 't'},
- {"dnsthreads", required_argument, 0, 'd'},
- {"port", required_argument, 0, 'p'},
- {"onion", required_argument, 0, 'o'},
- {"proxyipv4", required_argument, 0, 'i'},
- {"proxyipv6", required_argument, 0, 'k'},
- {"filter", required_argument, 0, 'w'},
- {"testnet", no_argument, &fUseTestNet, 1},
- {"wipeban", no_argument, &fWipeBan, 1},
- {"wipeignore", no_argument, &fWipeBan, 1},
- {"help", no_argument, 0, 'h'},
- {0, 0, 0, 0}};
- int option_index = 0;
- int c =
- getopt_long(argc, argv, "h:n:m:t:p:d:o:i:k:w:", long_options,
- &option_index);
- if (c == -1) break;
- switch (c) {
- case 'h': {
- host = optarg;
- break;
- }
-
- case 'm': {
- mbox = optarg;
- break;
- }
-
- case 'n': {
- ns = optarg;
- break;
- }
-
- case 't': {
- int n = strtol(optarg, nullptr, 10);
- if (n > 0 && n < 1000) nThreads = n;
- break;
- }
-
- case 'd': {
- int n = strtol(optarg, nullptr, 10);
- if (n > 0 && n < 1000) nDnsThreads = n;
- break;
- }
-
- case 'p': {
- int p = strtol(optarg, nullptr, 10);
- if (p > 0 && p < 65536) nPort = p;
- break;
- }
-
- case 'o': {
- tor = optarg;
- break;
- }
-
- case 'i': {
- ipv4_proxy = optarg;
- break;
- }
-
- case 'k': {
- ipv6_proxy = optarg;
- break;
- }
-
- case 'w': {
- char *ptr = optarg;
- while (*ptr != 0) {
- unsigned long l = strtoul(ptr, &ptr, 0);
- if (*ptr == ',') {
- ptr++;
- } else if (*ptr != 0) {
- break;
- }
- filter_whitelist.insert(l);
- }
- break;
- }
-
- case '?': {
- showHelp = true;
- break;
- }
- }
- }
- if (filter_whitelist.empty()) {
- filter_whitelist.insert(NODE_NETWORK);
- filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM);
- filter_whitelist.insert(NODE_NETWORK | NODE_XTHIN);
- filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM | NODE_XTHIN);
- }
- if (host != nullptr && ns == nullptr) showHelp = true;
- if (showHelp) fprintf(stderr, help, argv[0]);
- }
-};
-
extern "C" {
#include
}
@@ -270,18 +121,18 @@
}
}
- CDnsThread(CDnsSeedOpts *opts, int idIn) : id(idIn) {
- dns_opt.host = opts->host;
- dns_opt.ns = opts->ns;
- dns_opt.mbox = opts->mbox;
+ CDnsThread(std::set &filter_whitelist, int idIn) : id(idIn) {
+ dns_opt.host = gArgs.GetArg("-host", "").c_str();
+ dns_opt.ns = gArgs.GetArg("-ns", "").c_str();
+ dns_opt.mbox = gArgs.GetArg("-mbox", "").c_str();
dns_opt.datattl = 3600;
dns_opt.nsttl = 40000;
dns_opt.cb = GetIPList;
- dns_opt.port = opts->nPort;
+ dns_opt.port = gArgs.GetArg("-port", 53);
dns_opt.nRequests = 0;
dbQueries = 0;
perflag.clear();
- filterWhitelist = opts->filter_whitelist;
+ filterWhitelist = filter_whitelist;
}
void run() { dnsserver(&dns_opt); }
@@ -472,101 +323,223 @@
return nullptr;
}
-int main(int argc, char **argv) {
- // The logger dump everything on the console by default.
- GetLogger().m_print_to_console = true;
+static void SetupSeederArgs() {
+ gArgs.AddArg("-?", _("Print this help message and exit"), false,
+ OptionsCategory::OPTIONS);
+ gArgs.AddArg("-host=", _("Hostname of the DNS seed"), false,
+ OptionsCategory::OPTIONS);
+ gArgs.AddArg("-ns=", _("Hostname of the nameserver"), false,
+ OptionsCategory::OPTIONS);
+ gArgs.AddArg("-mbox=", _("E-Mail address reported in SOA records"),
+ false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-threads=",
+ _("Number of crawlers to run in parallel (default 96)"), false,
+ OptionsCategory::OPTIONS);
+ gArgs.AddArg("-dnsthreads=",
+ _("Number of DNS server threads (default 4)"), false,
+ OptionsCategory::OPTIONS);
+ gArgs.AddArg("-port=", _("UDP port to listen on (default 53)"), false,
+ OptionsCategory::CONNECTION);
+ gArgs.AddArg("-onion=", _("Tor proxy IP/Port"), false,
+ OptionsCategory::CONNECTION);
+ gArgs.AddArg("-proxyipv4=", _("IPV4 SOCKS5 proxy IP/Port"), false,
+ OptionsCategory::CONNECTION);
+ gArgs.AddArg("-proxyipv6=", _("IPV6 SOCKS5 proxy IP/Port"), false,
+ OptionsCategory::CONNECTION);
+ gArgs.AddArg("-filter=",
+ _("Allow these flag combinations as filters"), false,
+ OptionsCategory::OPTIONS);
+ gArgs.AddArg("-testnet", _("Use testnet"), false,
+ OptionsCategory::CHAINPARAMS);
+ gArgs.AddArg("-wipeban", _("Wipe list of banned nodes"), false,
+ OptionsCategory::CONNECTION);
+ gArgs.AddArg("-wipeignore", _("Wipe list of ignored nodes"), false,
+ OptionsCategory::CONNECTION);
+
+ gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
+}
- signal(SIGPIPE, SIG_IGN);
- setbuf(stdout, nullptr);
- CDnsSeedOpts opts;
- opts.ParseCommandLine(argc, argv);
+static bool ProcessOptions(int argc, char *argv[],
+ std::set &filter_whitelist) {
+ std::string error;
+ if (!gArgs.ParseParameters(argc, argv, error)) {
+ fprintf(stderr, "Error parsing command line arguments: %s\n",
+ error.c_str());
+ return false;
+ }
+ if (HelpRequested(gArgs)) {
+ std::string strUsage = "Bitcoin-cash-seeder\n";
+ strUsage += "Usage: bitcoin-seeder -host= -ns= "
+ "[-mbox=] [-threads=] [-port=]\n";
+ strUsage += "\n" + gArgs.GetHelpMessage();
+
+ fprintf(stdout, "%s", strUsage.c_str());
+ return true;
+ }
+ // Get whitelist filter flags
+ if (gArgs.IsArgSet("-filter")) {
+ // Parse whitelist additions
+ auto flags = gArgs.GetArg("-filter", "");
+ size_t flagstartpos = 0;
+ while (flagstartpos < flags.size() &&
+ flagstartpos != std::string::npos) {
+ size_t flagendpos = flags.find_first_of(",", flagstartpos);
+ uint64_t flag =
+ atoi64(flags.substr(flagstartpos, (flagendpos - flagstartpos)));
+ filter_whitelist.insert(flag);
+ if (flagendpos == std::string::npos) {
+ break;
+ }
+ flagstartpos = flagendpos + 1;
+ }
+ }
+ if (filter_whitelist.empty()) {
+ filter_whitelist.insert(NODE_NETWORK);
+ filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM);
+ filter_whitelist.insert(NODE_NETWORK | NODE_XTHIN);
+ filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM | NODE_XTHIN);
+ }
fprintf(stdout, "Supporting whitelisted filters: ");
- for (std::set::const_iterator it = opts.filter_whitelist.begin();
- it != opts.filter_whitelist.end(); it++) {
- if (it != opts.filter_whitelist.begin()) {
+ for (std::set::const_iterator it = filter_whitelist.begin();
+ it != filter_whitelist.end(); it++) {
+ if (it != filter_whitelist.begin()) {
fprintf(stdout, ",");
}
fprintf(stdout, "0x%lx", (unsigned long)*it);
}
+
fprintf(stdout, "\n");
- if (opts.tor) {
- CService service(LookupNumeric(opts.tor, 9050));
+ // Check tor proxy
+ if (!gArgs.GetArg("-onion", "").empty()) {
+ CService service(
+ LookupNumeric(gArgs.GetArg("-onion", "").c_str(), 9050));
if (service.IsValid()) {
fprintf(stdout, "Using Tor proxy at %s\n",
service.ToStringIPPort().c_str());
SetProxy(NET_ONION, proxyType(service));
}
}
- if (opts.ipv4_proxy) {
- CService service(LookupNumeric(opts.ipv4_proxy, 9050));
+ // Check ipv4 proxy
+ if (!gArgs.GetArg("-proxyipv4", "").empty()) {
+ CService service(
+ LookupNumeric(gArgs.GetArg("-proxyipv4", "").c_str(), 9050));
if (service.IsValid()) {
fprintf(stdout, "Using IPv4 proxy at %s\n",
service.ToStringIPPort().c_str());
SetProxy(NET_IPV4, proxyType(service));
}
}
- if (opts.ipv6_proxy) {
- CService service(LookupNumeric(opts.ipv6_proxy, 9050));
+ // Check ipv6 proxy
+ if (!gArgs.GetArg("-proxyipv6", "").empty()) {
+ CService service(
+ LookupNumeric(gArgs.GetArg("-proxyipv6", "").c_str(), 9050));
if (service.IsValid()) {
fprintf(stdout, "Using IPv6 proxy at %s\n",
service.ToStringIPPort().c_str());
SetProxy(NET_IPV6, proxyType(service));
}
}
- bool fDNS = true;
- if (opts.fUseTestNet) {
+
+ // Get -testnet option
+ if (gArgs.GetBoolArg("-testnet", false)) {
fprintf(stdout, "Using testnet.\n");
netMagic[0] = 0xf4;
netMagic[1] = 0xe5;
netMagic[2] = 0xf3;
netMagic[3] = 0xf4;
seeds = testnet_seeds;
- fTestNet = true;
}
- if (!opts.ns) {
+ // Check hostname of nameserver
+ if (gArgs.GetArg("-ns", "").empty()) {
+ // No hostname set
fprintf(stdout, "No nameserver set. Not starting DNS server.\n");
- fDNS = false;
}
- if (fDNS && !opts.host) {
- fprintf(stderr, "No hostname set. Please use -h.\n");
- exit(1);
+
+ // Check hostname of DNS seed
+ if (!gArgs.GetArg("-ns", "").empty() && gArgs.GetArg("-host", "").empty()) {
+ fprintf(stderr, "No hostname set. Please use -host.\n");
+ return false;
}
- if (fDNS && !opts.mbox) {
- fprintf(stderr, "No e-mail address set. Please use -m.\n");
- exit(1);
+
+ // Check email
+ if (!gArgs.GetArg("-ns", "").empty() && gArgs.GetArg("-mbox", "").empty()) {
+ fprintf(stderr, "No e-mail address set. Please use -mbox.\n");
+ return false;
}
+
FILE *f = fsbridge::fopen("dnsseed.dat", "r");
if (f) {
fprintf(stdout, "Loading dnsseed.dat...");
CAutoFile cf(f, SER_DISK, CLIENT_VERSION);
cf >> db;
- if (opts.fWipeBan) db.banned.clear();
- if (opts.fWipeIgnore) db.ResetIgnores();
+ // Check for -wipeban and the -wipeignore
+ if (gArgs.GetBoolArg("-wipeban", false)) {
+ db.banned.clear();
+ fprintf(stdout, "Ban list wiped...");
+ }
+ if (gArgs.GetBoolArg("-wipeignore", false)) {
+ db.ResetIgnores();
+ fprintf(stdout, "Ignore list wiped...");
+ }
fprintf(stdout, "done\n");
}
+ // Get DNS threading and port options
+ if (gArgs.GetArg("-dnsthreads", 4) < 1 &&
+ gArgs.GetArg("-dnsthreads", 4) > 999) {
+ gArgs.ForceSetArg("-dnsthreads", "4");
+ }
+ if (gArgs.GetArg("-port", 53) < 1 && gArgs.GetArg("-port", 53) > 65535) {
+ gArgs.ForceSetArg("-port", "53");
+ }
+ // Get threading options
+ if (gArgs.GetArg("-threads", 96) < 1 &&
+ gArgs.GetArg("-threads", 96) > 999) {
+ gArgs.ForceSetArg("-threads", "96");
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv) {
+ // The logger dump everything on the console by default.
+ GetLogger().m_print_to_console = true;
+
+ signal(SIGPIPE, SIG_IGN);
+ setbuf(stdout, nullptr);
+ SetupSeederArgs();
+
+ std::set filter_whitelist;
+ if (!ProcessOptions(argc, argv, filter_whitelist)) {
+ return 0;
+ }
+
pthread_t threadDns, threadSeed, threadDump, threadStats;
- if (fDNS) {
- fprintf(stdout, "Starting %i DNS threads for %s on %s (port %i)...",
- opts.nDnsThreads, opts.host, opts.ns, opts.nPort);
+ if (!gArgs.GetArg("-ns", "").empty()) {
+ fprintf(stdout, "Starting %li DNS threads for %s on %s (port %li)...",
+ gArgs.GetArg("-dnsthreads", 4),
+ gArgs.GetArg("-host", "").c_str(),
+ gArgs.GetArg("-ns", "").c_str(), gArgs.GetArg("-port", 53));
dnsThread.clear();
- for (int i = 0; i < opts.nDnsThreads; i++) {
- dnsThread.push_back(new CDnsThread(&opts, i));
+ for (int i = 0; i < gArgs.GetArg("-dnsthreads", 4); i++) {
+ dnsThread.push_back(new CDnsThread(filter_whitelist, i));
pthread_create(&threadDns, nullptr, ThreadDNS, dnsThread[i]);
fprintf(stdout, ".");
Sleep(20);
}
fprintf(stdout, "done\n");
}
+ uint64_t threads = gArgs.GetArg("-threads", 96);
fprintf(stdout, "Starting seeder...");
pthread_create(&threadSeed, nullptr, ThreadSeeder, nullptr);
fprintf(stdout, "done\n");
- fprintf(stdout, "Starting %i crawler threads...", opts.nThreads);
+ fprintf(stdout, "Starting %li crawler threads...", threads);
pthread_attr_t attr_crawler;
pthread_attr_init(&attr_crawler);
pthread_attr_setstacksize(&attr_crawler, 0x20000);
- for (int i = 0; i < opts.nThreads; i++) {
+ for (size_t i = 0; i < threads; i++) {
pthread_t thread;
- pthread_create(&thread, &attr_crawler, ThreadCrawler, &opts.nThreads);
+ pthread_create(&thread, &attr_crawler, ThreadCrawler, &threads);
}
pthread_attr_destroy(&attr_crawler);
fprintf(stdout, "done\n");