/ libi2pd / Config.cpp
Config.cpp
  1  /*
  2  * Copyright (c) 2013-2026, The PurpleI2P Project
  3  *
  4  * This file is part of Purple i2pd project and licensed under BSD3
  5  *
  6  * See full license text in LICENSE file at top of project tree
  7  */
  8  
  9  #include <cstdlib>
 10  #include <iostream>
 11  #include <fstream>
 12  #include <map>
 13  #include <string>
 14  #include <boost/program_options/cmdline.hpp>
 15  #include <boost/program_options/options_description.hpp>
 16  #include <boost/program_options/parsers.hpp>
 17  #include <boost/program_options/variables_map.hpp>
 18  
 19  #include "Identity.h"
 20  #include "Config.h"
 21  #include "version.h"
 22  #include "Log.h"
 23  
 24  using namespace boost::program_options;
 25  
 26  namespace i2p {
 27  namespace config {
 28  	options_description m_OptionsDesc;
 29  	variables_map m_Options;
 30  
 31  #if defined(_WIN32)
 32  #define path_to_file(file) "%appdata%\\i2pd\\" #file
 33  #elif defined(MAC_OSX)
 34  #define path_to_file(file) "~/Library/Application Support/i2pd/" #file
 35  #elif defined(__HAIKU__)
 36  #define path_to_file(file) "~/config/settings/i2pd/" #file
 37  #else
 38  #define path_to_file(file) "~/.i2pd/" #file " or /var/lib/i2pd/" #file
 39  #endif
 40  
 41  	void Init()
 42  	{
 43  		options_description general("General options");
 44  		general.add_options()
 45  			("help",                                                          "Show this message")
 46  			("version",                                                       "Show i2pd version")
 47  			("conf", value<std::string>()->default_value(""),                 "Path to main i2pd config file (default: try " path_to_file(i2pd.conf) ")")
 48  			("tunconf", value<std::string>()->default_value(""),              "Path to config with tunnels list and options (default: try " path_to_file(tunnels.conf) ")")
 49  			("tunnelsdir", value<std::string>()->default_value(""),           "Path to extra tunnels' configs folder (default: " path_to_file(tunnels.d))
 50  			("certsdir", value<std::string>()->default_value(""),             "Path to certificates used for verifying .su3, families (default: " path_to_file(certificates))
 51  			("pidfile", value<std::string>()->default_value(""),              "Path to pidfile (default: " path_to_file(i2pd.pid))
 52  			("log", value<std::string>()->default_value(""),                  "Logs destination: stdout, file, syslog (stdout if not set)")
 53  			("logfile", value<std::string>()->default_value(""),              "Path to logfile (stdout if not set, autodetect if daemon)")
 54  			("loglevel", value<std::string>()->default_value("warn"),         "Set the minimal level of log messages (debug, info, warn, error, none)")
 55  			("logclftime", bool_switch()->default_value(false),               "Write full CLF-formatted date and time to log (default: disabled, write only time)")
 56  			("family", value<std::string>()->default_value(""),               "Specify a family, router belongs to")
 57  			("datadir", value<std::string>()->default_value(""),              "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
 58  			("host", value<std::string>()->default_value(""),                 "External IP")
 59  			("ifname", value<std::string>()->default_value(""),               "Network interface to bind to")
 60  			("ifname4", value<std::string>()->default_value(""),              "Network interface to bind to for ipv4")
 61  			("ifname6", value<std::string>()->default_value(""),              "Network interface to bind to for ipv6")
 62  			("nat", bool_switch()->default_value(true),                       "Should we assume we are behind NAT? (default: enabled)")
 63  			("port", value<uint16_t>()->default_value(0),                     "Port to listen for incoming connections (default: auto)")
 64  			("ipv4", bool_switch()->default_value(true),                      "Enable communication through ipv4 (default: enabled)")
 65  			("address4", value<std::string>()->default_value(""),             "Local address to bind ipv4 transport sockets to")
 66  			("ipv6", bool_switch()->default_value(false),                     "Enable communication through ipv6 (default: disabled)")
 67  			("address6", value<std::string>()->default_value(""),             "Local address to bind ipv6 transport sockets to")
 68  			("reservedrange", bool_switch()->default_value(true),             "Check remote RI for being in blacklist of reserved IP ranges (default: enabled)")
 69  			("netid", value<int>()->default_value(I2PD_NET_ID),               "Specify NetID. Main I2P is 2")
 70  			("daemon", bool_switch()->default_value(false),                   "Router will go to background after start (default: disabled)")
 71  			("service", bool_switch()->default_value(false),                  "Router will use system folders like '/var/lib/i2pd' (default: disabled)")
 72  			("notransit", bool_switch()->default_value(false),                "Router will not accept transit tunnels at startup (default: disabled)")
 73  			("floodfill", bool_switch()->default_value(false),                "Router will be floodfill (default: disabled)")
 74  			("bandwidth", value<std::string>()->default_value(""),            "Transit traffic bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
 75  			("share", value<int>()->default_value(100),                       "Limit of transit traffic from max bandwidth in percents. (default: 100)")
 76  			("ntcp", bool_switch()->default_value(false),                     "Ignored. Always false")
 77  			("ssu", bool_switch()->default_value(false),                      "Ignored. Always false")
 78  			("ntcpproxy", value<std::string>()->default_value(""),            "Ignored")
 79  #ifdef _WIN32
 80  			("svcctl", value<std::string>()->default_value(""),               "Ignored")
 81  			("insomnia", bool_switch()->default_value(false),                 "Prevent system from sleeping (default: disabled)")
 82  			("close", value<std::string>()->default_value("ask"),             "Action on close: minimize, exit, ask")
 83  #endif
 84  			("stan", bool_switch()->default_value(false), 					  "Router has limited connectivity (default: false)")
 85  		;
 86  
 87  		options_description limits("Limits options");
 88  		limits.add_options()
 89  			("limits.coresize", value<uint32_t>()->default_value(0),          "Maximum size of corefile in Kb (0 - use system limit)")
 90  #if defined(__HAIKU__)
 91  			// Haiku's system default is 512, so we set 4096 explicitly
 92  			("limits.openfiles", value<uint16_t>()->default_value(4096),		"Maximum number of open files (4096 by default)")
 93  #else
 94  			("limits.openfiles", value<uint16_t>()->default_value(0),         "Maximum number of open files (0 - use system default)")
 95  #endif
 96  			("limits.transittunnels", value<uint32_t>()->default_value(25000), "Maximum active transit tunnels (default:25000)")
 97  			("limits.zombies", value<double>()->default_value(0),             "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)")
 98  			("limits.ntcpsoft", value<uint16_t>()->default_value(0),          "Ignored")
 99  			("limits.ntcphard", value<uint16_t>()->default_value(0),          "Ignored")
100  			("limits.ntcpthreads", value<uint16_t>()->default_value(1),       "Ignored")
101  		;
102  
103  		options_description httpserver("HTTP Server options");
104  		httpserver.add_options()
105  			("http.enabled", value<bool>()->default_value(true),                "Enable or disable webconsole")
106  			("http.address", value<std::string>()->default_value("127.0.0.1"),  "Webconsole listen address")
107  			("http.port", value<uint16_t>()->default_value(7070),               "Webconsole listen port")
108  			("http.auth", value<bool>()->default_value(false),                  "Enable Basic HTTP auth for webconsole")
109  			("http.user", value<std::string>()->default_value("i2pd"),          "Username for basic auth")
110  			("http.pass", value<std::string>()->default_value(""),              "Password for basic auth (default: random, see logs)")
111  			("http.strictheaders", value<bool>()->default_value(true),          "Enable strict host checking on WebUI")
112  			("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
113  			("http.webroot", value<std::string>()->default_value("/"),          "WebUI root path (default: / )")
114  			("http.lang", value<std::string>()->default_value("english"),       "WebUI language (default: english )")
115  			("http.showTotalTCSR", value<bool>()->default_value(false),         "Show additional value with total TCSR since router's start (default: false)")
116  			("http.theme", value<std::string>()->default_value("light"), 	    "Theme for http web console")
117  		;
118  
119  		options_description httpproxy("HTTP Proxy options");
120  		httpproxy.add_options()
121  			("httpproxy.enabled", value<bool>()->default_value(true),                 "Enable or disable HTTP Proxy")
122  			("httpproxy.address", value<std::string>()->default_value("127.0.0.1"),   "HTTP Proxy listen address")
123  			("httpproxy.port", value<uint16_t>()->default_value(4444),                "HTTP Proxy listen port")
124  			("httpproxy.keys", value<std::string>()->default_value("transient-proxy"), "File to persist HTTP Proxy keys. Transient by default")
125  			("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->
126  				default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519),      "Signature type for new keys. 7 (EdDSA) by default")
127  			("httpproxy.inbound.length", value<std::string>()->default_value("3"),    "HTTP proxy inbound tunnel length")
128  			("httpproxy.outbound.length", value<std::string>()->default_value("3"),   "HTTP proxy outbound tunnel length")
129  			("httpproxy.inbound.quantity", value<std::string>()->default_value("5"),  "HTTP proxy inbound tunnels quantity")
130  			("httpproxy.outbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy outbound tunnels quantity")
131  			("httpproxy.inbound.lengthVariance", value<std::string>()->default_value("0"),  "HTTP proxy inbound tunnels length variance")
132  			("httpproxy.outbound.lengthVariance", value<std::string>()->default_value("0"), "HTTP proxy outbound tunnels length variance")
133  			("httpproxy.latency.min", value<std::string>()->default_value("0"),       "HTTP proxy min latency for tunnels")
134  			("httpproxy.latency.max", value<std::string>()->default_value("0"),       "HTTP proxy max latency for tunnels")
135  			("httpproxy.outproxy", value<std::string>()->default_value(""),           "HTTP proxy upstream out proxy url")
136  			("httpproxy.addresshelper", value<bool>()->default_value(true),           "Enable or disable addresshelper")
137  			("httpproxy.senduseragent", value<bool>()->default_value(false),          "Pass through user's User-Agent if enabled. Disabled by default")
138  			("httpproxy.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Local destination's LeaseSet type")
139  #if OPENSSL_PQ
140  			("httpproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("6,4,0"), "Local destination's LeaseSet encryption type")
141  #else
142  			("httpproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("4,0"), "Local destination's LeaseSet encryption type")
143  #endif
144  			("httpproxy.i2cp.leaseSetPrivKey", value<std::string>()->default_value(""), "LeaseSet private key")
145  			("httpproxy.i2p.streaming.maxOutboundSpeed", value<std::string>()->default_value("1730000000"), "Max outbound speed of HTTP proxy stream in bytes/sec")
146  			("httpproxy.i2p.streaming.maxInboundSpeed", value<std::string>()->default_value("1730000000"), "Max inbound speed of HTTP proxy stream in bytes/sec")
147  			("httpproxy.i2p.streaming.profile", value<std::string>()->default_value("1"), "HTTP Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)")
148  			("httpproxy.i2p.streaming.maxWindowSize", value<std::string>()->default_value("512"), "HTTP Proxy stream max window size. 512 by default")
149  		;
150  
151  		options_description socksproxy("SOCKS Proxy options");
152  		socksproxy.add_options()
153  			("socksproxy.enabled", value<bool>()->default_value(true),                 "Enable or disable SOCKS Proxy")
154  			("socksproxy.address", value<std::string>()->default_value("127.0.0.1"),   "SOCKS Proxy listen address")
155  			("socksproxy.port", value<uint16_t>()->default_value(4447),                "SOCKS Proxy listen port")
156  			("socksproxy.keys", value<std::string>()->default_value("transient-proxy"), "File to persist SOCKS Proxy keys. Transient by default")
157  			("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->
158  				default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519),       "Signature type for new keys. 7 (EdDSA) by default")
159  			("socksproxy.inbound.length", value<std::string>()->default_value("3"),    "SOCKS proxy inbound tunnel length")
160  			("socksproxy.outbound.length", value<std::string>()->default_value("3"),   "SOCKS proxy outbound tunnel length")
161  			("socksproxy.inbound.quantity", value<std::string>()->default_value("5"),  "SOCKS proxy inbound tunnels quantity")
162  			("socksproxy.outbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy outbound tunnels quantity")
163  			("socksproxy.inbound.lengthVariance", value<std::string>()->default_value("0"),  "SOCKS proxy inbound tunnels length variance")
164  			("socksproxy.outbound.lengthVariance", value<std::string>()->default_value("0"), "SOCKS proxy outbound tunnels length variance")
165  			("socksproxy.latency.min", value<std::string>()->default_value("0"),       "SOCKS proxy min latency for tunnels")
166  			("socksproxy.latency.max", value<std::string>()->default_value("0"),       "SOCKS proxy max latency for tunnels")
167  			("socksproxy.outproxy.enabled", value<bool>()->default_value(false),       "Enable or disable SOCKS outproxy")
168  			("socksproxy.outproxy", value<std::string>()->default_value("127.0.0.1"),  "Upstream outproxy address for SOCKS Proxy")
169  			("socksproxy.outproxyport", value<uint16_t>()->default_value(9050),        "Upstream outproxy port for SOCKS Proxy")
170  			("socksproxy.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Local destination's LeaseSet type")
171  #if OPENSSL_PQ
172  			("socksproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("6,4,0"), "Local destination's LeaseSet encryption type")
173  #else
174  			("socksproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("4,0"), "Local destination's LeaseSet encryption type")
175  #endif
176  			("socksproxy.i2cp.leaseSetPrivKey", value<std::string>()->default_value(""), "LeaseSet private key")
177  			("socksproxy.i2p.streaming.maxOutboundSpeed", value<std::string>()->default_value("1730000000"), "Max outbound speed of SOCKS proxy stream in bytes/sec")
178  			("socksproxy.i2p.streaming.maxInboundSpeed", value<std::string>()->default_value("1730000000"), "Max inbound speed of SOCKS proxy stream in bytes/sec")
179  			("socksproxy.i2p.streaming.profile", value<std::string>()->default_value("1"), "SOCKS Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)")
180  			("socksproxy.i2p.streaming.maxWindowSize", value<std::string>()->default_value("512"), "SOCKS Proxy stream max window size. 512 by default")
181  		;
182  
183  		options_description shareddest("Shared local destination options");
184  		shareddest.add_options()
185  			("shareddest.inbound.length", value<std::string>()->default_value("3"),    "Shared local destination inbound tunnel length")
186  			("shareddest.outbound.length", value<std::string>()->default_value("3"),   "Shared local destination outbound tunnel length")
187  			("shareddest.inbound.quantity", value<std::string>()->default_value("3"),  "Shared local destination inbound tunnels quantity")
188  			("shareddest.outbound.quantity", value<std::string>()->default_value("3"), "Shared local destination outbound tunnels quantity")
189  			("shareddest.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Shared local destination's LeaseSet type")
190  #if OPENSSL_PQ
191  			("shareddest.i2cp.leaseSetEncType", value<std::string>()->default_value("6,4,0"), "Shared local destination's LeaseSet encryption type")
192  #else
193  			("shareddest.i2cp.leaseSetEncType", value<std::string>()->default_value("4,0"), "Shared local destination's LeaseSet encryption type")
194  #endif
195  			("shareddest.i2p.streaming.profile", value<std::string>()->default_value("2"), "Shared local destination bandwidth usage profile. 1 - bulk(high), 2- interactive(low)")
196  		;
197  
198  		options_description sam("SAM bridge options");
199  		sam.add_options()
200  			("sam.enabled", value<bool>()->default_value(true),               "Enable or disable SAM Application bridge")
201  			("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address")
202  			("sam.port", value<uint16_t>()->default_value(7656),              "SAM listen TCP port")
203  			("sam.portudp", value<uint16_t>()->default_value(0),              "SAM listen UDP port")
204  			("sam.singlethread", value<bool>()->default_value(true),          "Sessions run in the SAM bridge's thread")
205  		;
206  
207  		options_description bob("BOB options");
208  		bob.add_options()
209  			("bob.enabled", value<bool>()->default_value(false),              "Enable or disable BOB command channel")
210  			("bob.address", value<std::string>()->default_value("127.0.0.1"), "BOB listen address")
211  			("bob.port", value<uint16_t>()->default_value(2827),              "BOB listen port")
212  		;
213  
214  		options_description i2cp("I2CP options");
215  		i2cp.add_options()
216  			("i2cp.enabled", value<bool>()->default_value(false),              "Enable or disable I2CP")
217  			("i2cp.address", value<std::string>()->default_value("127.0.0.1"), "I2CP listen address")
218  			("i2cp.port", value<uint16_t>()->default_value(7654),              "I2CP listen port")
219  			("i2cp.singlethread", value<bool>()->default_value(true),          "Destinations run in the I2CP server's thread")
220  			("i2cp.inboundlimit", value<uint32_t>()->default_value(0),         "Client inbound limit in KBps to return in BandwidthLimitsMessage. Router's bandwidth by default")
221  			("i2cp.outboundlimit", value<uint32_t>()->default_value(0),        "Client outbound limit in KBps to return in BandwidthLimitsMessage. Router's bandwidth by default")
222  		;
223  
224  		options_description i2pcontrol("I2PControl options");
225  		i2pcontrol.add_options()
226  			("i2pcontrol.enabled", value<bool>()->default_value(false),                    "Enable or disable I2P Control Protocol")
227  			("i2pcontrol.address", value<std::string>()->default_value("127.0.0.1"),       "I2PCP listen address")
228  			("i2pcontrol.port", value<uint16_t>()->default_value(7650),                    "I2PCP listen port")
229  			("i2pcontrol.password", value<std::string>()->default_value("itoopie"),        "I2PCP access password")
230  			("i2pcontrol.cert", value<std::string>()->default_value("i2pcontrol.crt.pem"), "I2PCP connection certificate")
231  			("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"),  "I2PCP connection certificate key")
232  		;
233  
234  		bool upnp_default = false;
235  #if (defined(USE_UPNP) && (defined(WIN32_APP) || defined(ANDROID)))
236  		upnp_default = true; // enable UPNP for windows GUI and android by default
237  #endif
238  		options_description upnp("UPnP options");
239  		upnp.add_options()
240  			("upnp.enabled", value<bool>()->default_value(upnp_default), "Enable or disable UPnP: automatic port forwarding")
241  			("upnp.name", value<std::string>()->default_value("I2Pd"),   "Name i2pd appears in UPnP forwarding list")
242  		;
243  
244  		options_description precomputation("Precomputation options");
245  		precomputation.add_options()
246  			("precomputation.elgamal",
247  #if (defined(_M_AMD64) || defined(__x86_64__))
248  				value<bool>()->default_value(false),
249  #else
250  				value<bool>()->default_value(true),
251  #endif
252  				"Enable or disable elgamal precomputation table")
253  		;
254  
255  		options_description reseed("Reseed options");
256  		reseed.add_options()
257  			("reseed.verify", value<bool>()->default_value(false),        "Verify .su3 signature")
258  			("reseed.threshold", value<uint16_t>()->default_value(25),    "Minimum number of known routers before requesting reseed")
259  			("reseed.floodfill", value<std::string>()->default_value(""), "Ignored. Always empty")
260  			("reseed.file", value<std::string>()->default_value(""),      "Path to local .su3 file or HTTPS URL to reseed from")
261  			("reseed.zipfile", value<std::string>()->default_value(""),   "Path to local .zip file to reseed from")
262  			("reseed.proxy", value<std::string>()->default_value(""),     "url for reseed proxy, supports http/socks")
263  			("reseed.urls", value<std::string>()->default_value(
264  				"https://reseed2.i2p.net/,"
265  				"https://reseed.diva.exchange/,"
266  				"https://reseed-fr.i2pd.xyz/,"
267  				"https://reseed.onion.im/,"
268  				"https://i2pseed.creativecowpat.net:8443/,"
269  				"https://reseed.i2pgit.org/,"
270  				"https://coconut.incognet.io/,"
271  				"https://reseed-pl.i2pd.xyz/,"
272  				"https://www2.mk16.de/,"
273  			    "https://i2p.novg.net/,"
274              	"https://reseed.stormycloud.org,"
275              	"https://reseed.sahil.world/,"
276              	"https://i2p.diyarciftci.xyz/"
277  			),                                                            "Reseed URLs, separated by comma")
278  			("reseed.yggurls", value<std::string>()->default_value(
279  				"http://[324:71e:281a:9ed3::ace]:7070/,"
280  				"http://[301:65b9:c7cd:9a36::1]:18801/,"
281  				"http://[320:f09a:f09f:7acd::216]/,"
282  				"http://[316:f9e0:f22e:a74f::216]/"
283  			),                                                            "Reseed URLs through the Yggdrasil, separated by comma")
284  			("reseed.followredirect", value<bool>()->default_value(false),         "Follow redirects when reseeding")
285  		;
286  
287  		options_description addressbook("AddressBook options");
288  		addressbook.add_options()
289  			("addressbook.enabled", value<bool>()->default_value(true), "Enable address book lookups and subscritions (default: enabled)")
290  			("addressbook.defaulturl", value<std::string>()->default_value(
291  				"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt"
292  			),                                                                     "AddressBook subscription URL for initial setup")
293  			("addressbook.subscriptions", value<std::string>()->default_value(
294  				"http://reg.i2p/hosts.txt"
295  			),                                                                     "AddressBook subscriptions URLs, separated by comma")
296  			("addressbook.hostsfile", value<std::string>()->default_value(""),     "File to dump addresses in hosts.txt format");
297  
298  		options_description trust("Trust options");
299  		trust.add_options()
300  			("trust.enabled", value<bool>()->default_value(false),     "Enable explicit trust options")
301  			("trust.family", value<std::string>()->default_value(""),  "Router Family to trust for first hops")
302  			("trust.routers", value<std::string>()->default_value(""), "Only Connect to these routers")
303  			("trust.hidden", value<bool>()->default_value(false),      "Should we hide our router from other routers?")
304  		;
305  
306  		// Save deprecated websocket options for compatibility
307  		options_description websocket("Websocket Options");
308  		websocket.add_options()
309  			("websockets.enabled", value<bool>()->default_value(false),     "Deprecated option")
310  			("websockets.address", value<std::string>()->default_value(""), "Deprecated option")
311  			("websockets.port", value<uint16_t>()->default_value(0),        "Deprecated option")
312  		;
313  
314  		options_description exploratory("Exploratory Options");
315  		exploratory.add_options()
316  			("exploratory.inbound.length", value<int>()->default_value(2),    "Exploratory inbound tunnel length")
317  			("exploratory.outbound.length", value<int>()->default_value(2),   "Exploratory outbound tunnel length")
318  			("exploratory.inbound.quantity", value<int>()->default_value(3),  "Exploratory inbound tunnels quantity")
319  			("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity")
320  		;
321  
322  		options_description ntcp2("NTCP2 Options");
323  		ntcp2.add_options()
324  			("ntcp2.enabled", value<bool>()->default_value(true),          "Enable NTCP2 (default: enabled)")
325  			("ntcp2.published", value<bool>()->default_value(true),        "Publish NTCP2 (default: enabled)")
326  			("ntcp2.port", value<uint16_t>()->default_value(0),            "Port to listen for incoming NTCP2 connections (default: auto)")
327  			("ntcp2.addressv6", value<std::string>()->default_value("::"), "Address to publish NTCP2 with")
328  			("ntcp2.proxy", value<std::string>()->default_value(""),       "Proxy URL for NTCP2 transport")
329  			("ntcp2.version", value<int>()->default_value(2),              "Protocol version. 2 - standard, 3,4,5 - post quantum (default: 2")
330  		;
331  
332  		options_description ssu2("SSU2 Options");
333  		ssu2.add_options()
334  			("ssu2.enabled", value<bool>()->default_value(true),         "Enable SSU2 (default: enabled)")
335  			("ssu2.published", value<bool>()->default_value(true),        "Publish SSU2 (default: enabled)")
336  			("ssu2.port", value<uint16_t>()->default_value(0),            "Port to listen for incoming SSU2 packets (default: auto)")
337  			("ssu2.mtu4", value<uint16_t>()->default_value(0),            "MTU for ipv4 address (default: detect)")
338  			("ssu2.mtu6", value<uint16_t>()->default_value(0),            "MTU for ipv6 address (default: detect)")
339  			("ssu2.proxy", value<std::string>()->default_value(""),       "Socks5 proxy URL for SSU2 transport")
340  			("ssu2.firewalled4", value<bool>()->default_value(false),     "Set ipv4 network status to Firewalled even if OK (default: disabled)")
341  			("ssu2.firewalled6", value<bool>()->default_value(false),     "Set ipv6 network status to Firewalled even if OK (default: disabled)")
342  		;
343  
344  		options_description nettime("Time sync options");
345  		nettime.add_options()
346  			("nettime.enabled", value<bool>()->default_value(false),       "Enable NTP time sync (default: disabled)")
347  			("nettime.ntpservers", value<std::string>()->default_value(
348  				"0.pool.ntp.org,"
349  				"1.pool.ntp.org,"
350  				"2.pool.ntp.org,"
351  				"3.pool.ntp.org"
352  			),                                                             "Comma separated list of NTP servers")
353  			("nettime.ntpsyncinterval", value<int>()->default_value(72),   "NTP sync interval in hours (default: 72)")
354  			("nettime.frompeers", value<bool>()->default_value(true),      "Sync clock from transport peers (default: enabled)")
355  		;
356  
357  		options_description persist("Network information persisting options");
358  		persist.add_options()
359  			("persist.profiles", value<bool>()->default_value(true),       "Persist peer profiles (default: true)")
360  			("persist.addressbook", value<bool>()->default_value(true),    "Persist full addresses (default: true)")
361  		;
362  
363  		options_description cpuext("CPU encryption extensions options. Deprecated");
364  		cpuext.add_options()
365  			("cpuext.aesni", bool_switch()->default_value(true),                     "Deprecated option")
366  			("cpuext.avx", bool_switch()->default_value(false),                      "Deprecated option")
367  			("cpuext.force", bool_switch()->default_value(false),                    "Deprecated option")
368  		;
369  
370  		options_description meshnets("Meshnet transports options");
371  		meshnets.add_options()
372  			("meshnets.yggdrasil", bool_switch()->default_value(false),              "Support transports through the Yggdrasil (default: false)")
373  			("meshnets.yggaddress", value<std::string>()->default_value(""),         "Yggdrasil address to publish")
374  		;
375  
376  #ifdef __linux__
377  		options_description unix_specific("UNIX-specific options");
378  		unix_specific.add_options()
379  			("unix.handle_sigtstp", bool_switch()->default_value(false),             "Handle SIGTSTP and SIGCONT signals (default: disabled)")
380  		;
381  #endif
382  
383  		m_OptionsDesc
384  			.add(general)
385  			.add(limits)
386  			.add(httpserver)
387  			.add(httpproxy)
388  			.add(socksproxy)
389  			.add(shareddest)
390  			.add(sam)
391  			.add(bob)
392  			.add(i2cp)
393  			.add(i2pcontrol)
394  			.add(upnp)
395  			.add(precomputation)
396  			.add(reseed)
397  			.add(addressbook)
398  			.add(trust)
399  			.add(websocket) // deprecated
400  			.add(exploratory)
401  			.add(ntcp2)
402  			.add(ssu2)
403  			.add(nettime)
404  			.add(persist)
405  			.add(cpuext)
406  			.add(meshnets)
407  #ifdef __linux__
408  			.add(unix_specific)
409  #endif
410  		;
411  	}
412  
413  	void ParseCmdline(int argc, char* argv[], bool ignoreUnknown)
414  	{
415  		try
416  		{
417  			auto style = boost::program_options::command_line_style::unix_style
418  			           | boost::program_options::command_line_style::allow_long_disguise;
419  			style &=   ~ boost::program_options::command_line_style::allow_guessing;
420  			if (ignoreUnknown)
421  				store(command_line_parser(argc, argv).options(m_OptionsDesc).style (style).allow_unregistered().run(), m_Options);
422  			else
423  				store(parse_command_line(argc, argv, m_OptionsDesc, style), m_Options);
424  		}
425  		catch (boost::program_options::error& e)
426  		{
427  			ThrowFatal ("Error while parsing arguments: ", e.what());
428  			std::cerr << "args: " << e.what() << std::endl;
429  			exit(EXIT_FAILURE);
430  		}
431  
432  		if (!ignoreUnknown && (m_Options.count("help") || m_Options.count("h")))
433  		{
434  			std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
435  			std::cout << m_OptionsDesc;
436  			exit(EXIT_SUCCESS);
437  		}
438  		else if (m_Options.count("version"))
439  		{
440  			std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
441  			std::cout << "Boost version "
442  					  << BOOST_VERSION / 100000     << "."  // maj. version
443  					  << BOOST_VERSION / 100 % 1000 << "."  // min. version
444  					  << BOOST_VERSION % 100                // patch version
445  					  << std::endl;
446  #if defined(OPENSSL_VERSION_TEXT)
447  			std::cout << OPENSSL_VERSION_TEXT << std::endl;
448  #endif
449  #if defined(LIBRESSL_VERSION_TEXT)
450  			std::cout << LIBRESSL_VERSION_TEXT << std::endl;
451  #endif
452  
453  			exit(EXIT_SUCCESS);
454  		}
455  	}
456  
457  	void ParseConfig(const std::string& path)
458  	{
459  		if (path == "") return;
460  
461  		std::ifstream config(path, std::ios::in);
462  
463  		if (!config.is_open())
464  		{
465  			ThrowFatal ("Missing or unreadable config file: ", path);
466  			std::cerr << "missing/unreadable config file: " << path << std::endl;
467  			exit(EXIT_FAILURE);
468  		}
469  
470  		try
471  		{
472  			store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
473  		}
474  		catch (boost::program_options::error& e)
475  		{
476  			ThrowFatal ("Error while parsing config file: ", e.what());
477  			std::cerr << e.what() << std::endl;
478  			exit(EXIT_FAILURE);
479  		};
480  	}
481  
482  	void Finalize()
483  	{
484  		notify(m_Options);
485  	}
486  
487  	bool IsDefault(const char *name)
488  	{
489  		if (!m_Options.count(name))
490  			throw "try to check non-existent option";
491  
492  		if (m_Options[name].defaulted())
493  			return true;
494  		return false;
495  	}
496  
497  	bool GetOptionAsAny(const char *name, boost::any& value)
498  	{
499  		if (!m_Options.count(name))
500  			return false;
501  		value = m_Options[name];
502  		return true;
503  	}
504  
505  	bool GetOptionAsAny(const std::string& name, boost::any& value)
506  	{
507  		return GetOptionAsAny (name.c_str (), value);
508  	}
509  
510  } // namespace config
511  } // namespace i2p