00001 #include "config.h"
00002 #include "Configuration.h"
00003 #include "net/DiscoveryAnnouncement.h"
00004 #include "net/DiscoveryAnnouncement.h"
00005 #include "core/Node.h"
00006
00007 #include <ibrdtn/utils/Utils.h>
00008 #include <ibrdtn/utils/Clock.h>
00009
00010 #include <ibrcommon/net/vinterface.h>
00011 #include <ibrcommon/Logger.h>
00012
00013 #include <getopt.h>
00014
00015 #ifdef __DEVELOPMENT_ASSERTIONS__
00016 #include <cassert>
00017 #endif
00018
00019 using namespace dtn::net;
00020 using namespace dtn::core;
00021 using namespace dtn::utils;
00022 using namespace ibrcommon;
00023
00024 namespace dtn
00025 {
00026 namespace daemon
00027 {
00028 Configuration::NetConfig::NetConfig(std::string n, NetType t, const std::string &u, bool d)
00029 : name(n), type(t), url(u), port(0), discovery(d)
00030 {
00031 }
00032
00033 Configuration::NetConfig::NetConfig(std::string n, NetType t, const ibrcommon::vinterface &i, int p, bool d)
00034 : name(n), type(t), interface(i), port(p), discovery(d)
00035 {
00036 }
00037
00038 Configuration::NetConfig::NetConfig(std::string n, NetType t, const ibrcommon::vaddress &a, int p, bool d)
00039 : name(n), type(t), interface(), address(a), port(p), discovery(d)
00040 {
00041 }
00042
00043 Configuration::NetConfig::NetConfig(std::string n, NetType t, int p, bool d)
00044 : name(n), type(t), interface(), port(p), discovery(d)
00045 {
00046 }
00047
00048 Configuration::NetConfig::~NetConfig()
00049 {
00050 }
00051
00052 std::string Configuration::version()
00053 {
00054 std::stringstream ss;
00055 ss << PACKAGE_VERSION;
00056 #ifdef SVN_REVISION
00057 ss << " (build " << SVN_REVISION << ")";
00058 #endif
00059
00060 return ss.str();
00061 }
00062
00063 Configuration::Configuration()
00064 : _filename("config.ini"), _doapi(true)
00065 {
00066 }
00067
00068 Configuration::~Configuration()
00069 {}
00070
00071 Configuration::Discovery::Discovery()
00072 : _enabled(true), _timeout(5) {};
00073
00074 Configuration::Statistic::Statistic() {};
00075
00076 Configuration::Debug::Debug()
00077 : _enabled(false), _quiet(false), _level(0) {};
00078
00079 Configuration::Logger::Logger()
00080 : _quiet(false), _options(0), _timestamps(false) {};
00081
00082 Configuration::Network::Network()
00083 : _routing("default"), _forwarding(true), _tcp_nodelay(true), _tcp_chunksize(1024), _default_net("lo"), _use_default_net(false) {};
00084
00085 Configuration::Security::Security()
00086 : _enabled(false)
00087 {};
00088
00089 Configuration::Discovery::~Discovery() {};
00090 Configuration::Statistic::~Statistic() {};
00091 Configuration::Debug::~Debug() {};
00092 Configuration::Logger::~Logger() {};
00093 Configuration::Network::~Network() {};
00094
00095 const Configuration::Discovery& Configuration::getDiscovery() const
00096 {
00097 return _disco;
00098 }
00099
00100 const Configuration::Statistic& Configuration::getStatistic() const
00101 {
00102 return _stats;
00103 }
00104
00105 const Configuration::Debug& Configuration::getDebug() const
00106 {
00107 return _debug;
00108 }
00109
00110 const Configuration::Logger& Configuration::getLogger() const
00111 {
00112 return _logger;
00113 }
00114
00115 const Configuration::Network& Configuration::getNetwork() const
00116 {
00117 return _network;
00118 }
00119
00120 const Configuration::Security& Configuration::getSecurity() const
00121 {
00122 return _security;
00123 }
00124
00125 Configuration& Configuration::getInstance()
00126 {
00127 static Configuration conf;
00128 return conf;
00129 }
00130
00131 void Configuration::params(int argc, char *argv[])
00132 {
00133 int c;
00134 int doapi = _doapi;
00135 int disco = _disco._enabled;
00136 int badclock = dtn::utils::Clock::badclock;
00137 int timestamp = _logger._timestamps;
00138
00139 while (1)
00140 {
00141 static struct option long_options[] =
00142 {
00143
00144 {"noapi", no_argument, &doapi, 0},
00145 {"nodiscovery", no_argument, &disco, 0},
00146 {"badclock", no_argument, &badclock, 1},
00147 {"timestamp", no_argument, ×tamp, 1},
00148
00149
00150 {"help", no_argument, 0, 'h'},
00151 {"quiet", no_argument, 0, 'q'},
00152 {"version", no_argument, 0, 'v'},
00153 {"interface", required_argument, 0, 'i'},
00154 {"configuration", required_argument, 0, 'c'},
00155 {"debug", required_argument, 0, 'd'},
00156 {0, 0, 0, 0}
00157 };
00158
00159
00160 int option_index = 0;
00161
00162 c = getopt_long (argc, argv, "qhvi:c:d:",
00163 long_options, &option_index);
00164
00165
00166 if (c == -1)
00167 break;
00168
00169 switch (c)
00170 {
00171 case 0:
00172
00173 if (long_options[option_index].flag != 0)
00174 break;
00175 printf ("option %s", long_options[option_index].name);
00176 if (optarg)
00177 printf (" with arg %s", optarg);
00178 printf ("\n");
00179 break;
00180
00181 case 'h':
00182 std::cout << "IBR-DTN version: " << version() << std::endl;
00183 std::cout << "Syntax: dtnd [options]" << std::endl;
00184 std::cout << " -h|--help display this text" << std::endl;
00185 std::cout << " -c <file> set a configuration file" << std::endl;
00186 std::cout << " -i <interface> interface to bind on (e.g. eth0)" << std::endl;
00187 std::cout << " -d <level> enable debugging and set a verbose level" << std::endl;
00188 std::cout << " -q enables the quiet mode (no logging to the console)" << std::endl;
00189 std::cout << " --noapi disable API module" << std::endl;
00190 std::cout << " --nodiscovery disable discovery module" << std::endl;
00191 std::cout << " --badclock assume a bad clock on the system (use AgeBlock)" << std::endl;
00192 std::cout << " --timestamp enables timestamps for logging instead of datetime values" << std::endl;
00193 exit(0);
00194 break;
00195
00196 case 'v':
00197 std::cout << "IBR-DTN version: " << version() << std::endl;
00198 exit(0);
00199 break;
00200
00201 case 'q':
00202 _debug._quiet = true;
00203 break;
00204
00205 case 'c':
00206 _filename = optarg;
00207 break;
00208
00209 case 'i':
00210 _network._default_net = ibrcommon::vinterface(optarg);
00211 _network._use_default_net = true;
00212 break;
00213
00214 case 'd':
00215 _debug._enabled = true;
00216 _debug._level = atoi(optarg);
00217 break;
00218
00219 case '?':
00220
00221 break;
00222
00223 default:
00224 abort ();
00225 }
00226 }
00227
00228 _doapi = doapi;
00229 _disco._enabled = disco;
00230 dtn::utils::Clock::badclock = badclock;
00231 _logger._timestamps = timestamp;
00232 }
00233
00234 void Configuration::load()
00235 {
00236 load(_filename);
00237 }
00238
00239 void Configuration::load(string filename)
00240 {
00241 try {
00242
00243 _conf = ibrcommon::ConfigFile(filename);
00244 _filename = filename;
00245
00246 IBRCOMMON_LOGGER(info) << "Configuration: " << filename << IBRCOMMON_LOGGER_ENDL;
00247 } catch (const ibrcommon::ConfigFile::file_not_found&) {
00248 IBRCOMMON_LOGGER(info) << "Using default settings. Call with --help for options." << IBRCOMMON_LOGGER_ENDL;
00249 _conf = ConfigFile();
00250 }
00251
00252
00253 _disco.load(_conf);
00254 _stats.load(_conf);
00255 _debug.load(_conf);
00256 _logger.load(_conf);
00257 _network.load(_conf);
00258 _security.load(_conf);
00259 }
00260
00261 void Configuration::Discovery::load(const ibrcommon::ConfigFile &conf)
00262 {
00263 _timeout = conf.read<unsigned int>("discovery_timeout", 5);
00264 }
00265
00266 void Configuration::Statistic::load(const ibrcommon::ConfigFile&)
00267 {
00268 }
00269
00270 void Configuration::Logger::load(const ibrcommon::ConfigFile&)
00271 {
00272 }
00273
00274 void Configuration::Debug::load(const ibrcommon::ConfigFile&)
00275 {
00276 }
00277
00278 bool Configuration::Debug::quiet() const
00279 {
00280 return _quiet;
00281 }
00282
00283 bool Configuration::Debug::enabled() const
00284 {
00285 return _enabled;
00286 }
00287
00288 int Configuration::Debug::level() const
00289 {
00290 return _level;
00291 }
00292
00293 string Configuration::getNodename()
00294 {
00295 try {
00296 return _conf.read<string>("local_uri");
00297 } catch (const ibrcommon::ConfigFile::key_not_found&) {
00298 char *hostname_array = new char[64];
00299 if ( gethostname(hostname_array, 64) != 0 )
00300 {
00301
00302 delete[] hostname_array;
00303 return "local";
00304 }
00305
00306 string hostname(hostname_array);
00307 delete[] hostname_array;
00308
00309 stringstream ss;
00310 ss << "dtn://" << hostname;
00311 ss >> hostname;
00312
00313 return hostname;
00314 }
00315 }
00316
00317 const std::list<Configuration::NetConfig>& Configuration::Network::getInterfaces() const
00318 {
00319 return _interfaces;
00320 }
00321
00322 const ibrcommon::vaddress Configuration::Discovery::address() const throw (ParameterNotFoundException)
00323 {
00324 try {
00325 return ibrcommon::vaddress( ibrcommon::vaddress::VADDRESS_INET,
00326 Configuration::getInstance()._conf.read<string>("discovery_address"));
00327 } catch (const ConfigFile::key_not_found&) {
00328 throw ParameterNotFoundException();
00329 }
00330 }
00331
00332 int Configuration::Discovery::port() const
00333 {
00334 return Configuration::getInstance()._conf.read<int>("discovery_port", 4551);
00335 }
00336
00337 unsigned int Configuration::Discovery::timeout() const
00338 {
00339 return _timeout;
00340 }
00341
00342 Configuration::NetConfig Configuration::getAPIInterface()
00343 {
00344 return Configuration::NetConfig("local", Configuration::NetConfig::NETWORK_TCP, ibrcommon::vinterface("lo"), 4550);
00345 }
00346
00347 ibrcommon::File Configuration::getAPISocket()
00348 {
00349 try {
00350 return ibrcommon::File(_conf.read<std::string>("api_socket"));
00351 } catch (const ConfigFile::key_not_found&) {
00352 throw ParameterNotSetException();
00353 }
00354 }
00355
00356 std::string Configuration::getStorage() const
00357 {
00358 return _conf.read<std::string>("storage", "default");
00359 }
00360
00361 void Configuration::Network::load(const ibrcommon::ConfigFile &conf)
00362 {
00366 _static_routes.clear();
00367
00368 string key = "route1";
00369 unsigned int keynumber = 1;
00370
00371 while (conf.keyExists( key ))
00372 {
00373 vector<string> route = dtn::utils::Utils::tokenize(" ", conf.read<string>(key, "dtn:none dtn:none"));
00374 _static_routes.push_back( dtn::routing::StaticRoutingExtension::StaticRoute( route.front(), route.back() ) );
00375
00376 keynumber++;
00377 stringstream ss; ss << "route" << keynumber; ss >> key;
00378 }
00379
00383
00384 int count = 1;
00385
00386
00387 std::string prefix = "static1_";
00388
00389 while ( conf.keyExists(prefix + "uri") )
00390 {
00391 Node n(Node::NODE_PERMANENT);
00392
00393 n.setAddress( conf.read<std::string>(prefix + "address", "127.0.0.1") );
00394 n.setPort( conf.read<unsigned int>(prefix + "port", 4556) );
00395 n.setURI( conf.read<std::string>(prefix + "uri", "dtn:none") );
00396 n.setConnectImmediately( conf.read<std::string>(prefix + "immediately", "no") == "yes" );
00397
00398 std::string protocol = conf.read<std::string>(prefix + "proto", "tcp");
00399 if (protocol == "tcp") n.setProtocol(Node::CONN_TCPIP);
00400 if (protocol == "udp") n.setProtocol(Node::CONN_UDPIP);
00401 if (protocol == "zigbee") n.setProtocol(Node::CONN_ZIGBEE);
00402 if (protocol == "bluetooth") n.setProtocol(Node::CONN_BLUETOOTH);
00403 if (protocol == "http") n.setProtocol(Node::CONN_HTTP);
00404
00405 count++;
00406
00407 std::stringstream prefix_stream;
00408 prefix_stream << "static" << count << "_";
00409 prefix = prefix_stream.str();
00410
00411 _nodes.push_back(n);
00412 }
00413
00417 _routing = conf.read<string>("routing", "default");
00418
00422 _forwarding = (conf.read<std::string>("routing_forwarding", "yes") == "yes");
00423
00427 _interfaces.clear();
00428
00429 if (_use_default_net)
00430 {
00431 _interfaces.push_back( Configuration::NetConfig("default", Configuration::NetConfig::NETWORK_TCP, _default_net, 4556) );
00432 }
00433 else try
00434 {
00435 vector<string> nets = dtn::utils::Utils::tokenize(" ", conf.read<string>("net_interfaces") );
00436 for (vector<string>::const_iterator iter = nets.begin(); iter != nets.end(); iter++)
00437 {
00438 std::string netname = (*iter);
00439
00440 std::string key_type = "net_" + netname + "_type";
00441 std::string key_port = "net_" + netname + "_port";
00442 std::string key_interface = "net_" + netname + "_interface";
00443 std::string key_address = "net_" + netname + "_address";
00444 std::string key_discovery = "net_" + netname + "_discovery";
00445
00446 std::string type_name = conf.read<string>(key_type, "tcp");
00447 Configuration::NetConfig::NetType type = Configuration::NetConfig::NETWORK_UNKNOWN;
00448
00449 if (type_name == "tcp") type = Configuration::NetConfig::NETWORK_TCP;
00450 if (type_name == "udp") type = Configuration::NetConfig::NETWORK_UDP;
00451 if (type_name == "http") type = Configuration::NetConfig::NETWORK_HTTP;
00452 if (type_name == "lowpan") type = Configuration::NetConfig::NETWORK_LOWPAN;
00453
00454 switch (type)
00455 {
00456 case Configuration::NetConfig::NETWORK_HTTP:
00457 {
00458 Configuration::NetConfig::NetConfig nc(netname, type,
00459 conf.read<std::string>(key_address, "http://localhost/"),
00460 conf.read<std::string>(key_discovery, "yes") == "no");
00461
00462 _interfaces.push_back(nc);
00463 break;
00464 }
00465
00466 default:
00467 {
00468 int port = conf.read<int>(key_port, 4556);
00469 bool discovery = (conf.read<std::string>(key_discovery, "yes") == "yes");
00470
00471 try {
00472 ibrcommon::vinterface interface(conf.read<std::string>(key_interface));
00473 Configuration::NetConfig::NetConfig nc(netname, type, interface, port, discovery);
00474 _interfaces.push_back(nc);
00475 } catch (const ConfigFile::key_not_found&) {
00476 ibrcommon::vaddress addr;
00477 Configuration::NetConfig::NetConfig nc(netname, type, addr, port, discovery);
00478 _interfaces.push_back(nc);
00479 }
00480
00481 break;
00482 }
00483 }
00484 }
00485 } catch (const ConfigFile::key_not_found&) {
00486
00487 }
00488
00492 _tcp_nodelay = (conf.read<std::string>("tcp_nodelay", "yes") == "yes");
00493 _tcp_chunksize = conf.read<unsigned int>("tcp_chunksize", 1024);
00494 }
00495
00496 const list<dtn::routing::StaticRoutingExtension::StaticRoute>& Configuration::Network::getStaticRoutes() const
00497 {
00498 return _static_routes;
00499 }
00500
00501 const std::list<Node>& Configuration::Network::getStaticNodes() const
00502 {
00503 return _nodes;
00504 }
00505
00506 int Configuration::getTimezone()
00507 {
00508 return _conf.read<int>( "timezone", 0 );
00509 }
00510
00511 ibrcommon::File Configuration::getPath(string name)
00512 {
00513 stringstream ss;
00514 ss << name << "_path";
00515 string key; ss >> key;
00516
00517 try {
00518 return ibrcommon::File(_conf.read<string>(key));
00519 } catch (const ConfigFile::key_not_found&) {
00520 throw ParameterNotSetException();
00521 }
00522 }
00523
00524 unsigned int Configuration::getUID()
00525 {
00526 try {
00527 return _conf.read<unsigned int>("user");
00528 } catch (const ConfigFile::key_not_found&) {
00529 throw ParameterNotSetException();
00530 }
00531 }
00532
00533 unsigned int Configuration::getGID()
00534 {
00535 try {
00536 return _conf.read<unsigned int>("group");
00537 } catch (const ConfigFile::key_not_found&) {
00538 throw ParameterNotSetException();
00539 }
00540 }
00541
00542
00543 bool Configuration::Discovery::enabled() const
00544 {
00545 return _enabled;
00546 }
00547
00548 bool Configuration::Discovery::announce() const
00549 {
00550 return (Configuration::getInstance()._conf.read<int>("discovery_announce", 1) == 1);
00551 }
00552
00553 bool Configuration::Discovery::shortbeacon() const
00554 {
00555 return (Configuration::getInstance()._conf.read<int>("discovery_short", 0) == 1);
00556 }
00557
00558 char Configuration::Discovery::version() const
00559 {
00560 return Configuration::getInstance()._conf.read<int>("discovery_version", 2);
00561 }
00562
00563 bool Configuration::doAPI()
00564 {
00565 return _doapi;
00566 }
00567
00568 string Configuration::getNotifyCommand()
00569 {
00570 try {
00571 return _conf.read<string>("notify_cmd");
00572 } catch (const ConfigFile::key_not_found&) {
00573 throw ParameterNotSetException();
00574 }
00575 }
00576
00577 Configuration::RoutingExtension Configuration::Network::getRoutingExtension() const
00578 {
00579 if ( _routing == "epidemic" ) return EPIDEMIC_ROUTING;
00580 if ( _routing == "flooding" ) return FLOOD_ROUTING;
00581 return DEFAULT_ROUTING;
00582 }
00583
00584
00585 bool Configuration::Network::doForwarding() const
00586 {
00587 return _forwarding;
00588 }
00589
00590 bool Configuration::Network::getTCPOptionNoDelay() const
00591 {
00592 return _tcp_nodelay;
00593 }
00594
00595 size_t Configuration::Network::getTCPChunkSize() const
00596 {
00597 return _tcp_chunksize;
00598 }
00599
00600 bool Configuration::Statistic::enabled() const
00601 {
00602 return Configuration::getInstance()._conf.keyExists("statistic_type");
00603 }
00604
00605 ibrcommon::File Configuration::Statistic::logfile() const throw (ParameterNotSetException)
00606 {
00607 try {
00608 return ibrcommon::File(Configuration::getInstance()._conf.read<std::string>("statistic_file"));
00609 } catch (const ConfigFile::key_not_found&) {
00610 throw ParameterNotSetException();
00611 }
00612 }
00613
00614 std::string Configuration::Statistic::type() const
00615 {
00616 return Configuration::getInstance()._conf.read<std::string>("statistic_type", "stdout");
00617 }
00618
00619 unsigned int Configuration::Statistic::interval() const
00620 {
00621 return Configuration::getInstance()._conf.read<unsigned int>("statistic_interval", 300);
00622 }
00623
00624 std::string Configuration::Statistic::address() const
00625 {
00626 return Configuration::getInstance()._conf.read<std::string>("statistic_address", "127.0.0.1");
00627 }
00628
00629 unsigned int Configuration::Statistic::port() const
00630 {
00631 return Configuration::getInstance()._conf.read<unsigned int>("statistic_port", 1234);
00632 }
00633
00634 size_t Configuration::getLimit(std::string suffix)
00635 {
00636 std::string unparsed = _conf.read<std::string>("limit_" + suffix, "0");
00637
00638 std::stringstream ss(unparsed);
00639
00640 float value; ss >> value;
00641 char multiplier = 0; ss >> multiplier;
00642
00643 switch (multiplier)
00644 {
00645 default:
00646 return (size_t)value;
00647 break;
00648
00649 case 'G':
00650 return (size_t)(value * 1000000000);
00651 break;
00652
00653 case 'M':
00654 return (size_t)(value * 1000000);
00655 break;
00656
00657 case 'K':
00658 return (size_t)(value * 1000);
00659 break;
00660 }
00661
00662 return 0;
00663 }
00664
00665 void Configuration::Security::load(const ibrcommon::ConfigFile &conf)
00666 {
00667 #ifdef WITH_BUNDLE_SECURITY
00668
00669 try {
00670 _path = conf.read<std::string>("security_path");
00671
00672 if (!_path.exists())
00673 {
00674 ibrcommon::File::createDirectory(_path);
00675 }
00676
00677 _enabled = true;
00678 } catch (const ibrcommon::ConfigFile::key_not_found&) {
00679 return;
00680 }
00681
00682
00683 _level = Level(conf.read<int>("security_level", 0));
00684
00685
00686 try {
00687 _ca = conf.read<std::string>("security_ca");
00688
00689 if (!_ca.exists())
00690 {
00691 IBRCOMMON_LOGGER(warning) << "CA file " << _ca.getPath() << " does not exists!" << IBRCOMMON_LOGGER_ENDL;
00692 }
00693 } catch (const ibrcommon::ConfigFile::key_not_found&) {
00694 }
00695
00696
00697 try {
00698 _ca = conf.read<std::string>("security_key");
00699
00700 if (!_ca.exists())
00701 {
00702 IBRCOMMON_LOGGER(warning) << "KEY file " << _ca.getPath() << " does not exists!" << IBRCOMMON_LOGGER_ENDL;
00703 }
00704 } catch (const ibrcommon::ConfigFile::key_not_found&) {
00705 }
00706
00707
00708 try {
00709 _bab_default_key = conf.read<std::string>("security_bab_default_key");
00710
00711 if (!_bab_default_key.exists())
00712 {
00713 IBRCOMMON_LOGGER(warning) << "KEY file " << _bab_default_key.getPath() << " does not exists!" << IBRCOMMON_LOGGER_ENDL;
00714 }
00715 } catch (const ibrcommon::ConfigFile::key_not_found&) {
00716 }
00717 #endif
00718 };
00719
00720 Configuration::Security::~Security() {};
00721
00722 bool Configuration::Security::enabled() const
00723 {
00724 return _enabled;
00725 }
00726
00727 #ifdef WITH_BUNDLE_SECURITY
00728 const ibrcommon::File& Configuration::Security::getPath() const
00729 {
00730 return _path;
00731 }
00732
00733 const ibrcommon::File& Configuration::Security::getCA() const
00734 {
00735 return _ca;
00736 }
00737
00738 const ibrcommon::File& Configuration::Security::getKey() const
00739 {
00740 return _key;
00741 }
00742
00743 Configuration::Security::Level Configuration::Security::getLevel() const
00744 {
00745 return _level;
00746 }
00747
00748 const ibrcommon::File& Configuration::Security::getBABDefaultKey() const
00749 {
00750 return _bab_default_key;
00751 }
00752 #endif
00753
00754 bool Configuration::Logger::quiet() const
00755 {
00756 return _quiet;
00757 }
00758
00759 bool Configuration::Logger::display_timestamps() const
00760 {
00761 return _timestamps;
00762 }
00763
00764 unsigned int Configuration::Logger::options() const
00765 {
00766 return _options;
00767 }
00768
00769 std::ostream& Configuration::Logger::output() const
00770 {
00771 return std::cout;
00772 }
00773 }
00774 }