blob: 9b804315272068f3bee6b0df3591a858fb79785c [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2017, Regents of the University of California.
*
* This file is part of NDNS (Named Data Networking Domain Name Service).
* See AUTHORS.md for complete list of NDNS authors and contributors.
*
* NDNS is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "daemon/name-server.hpp"
#include "logger.hpp"
#include "config.hpp"
#include "daemon/config-file.hpp"
#include "ndn-cxx/security/key-chain.hpp"
#include "util/cert-helper.hpp"
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
namespace ndn {
namespace ndns {
NDNS_LOG_INIT("NdnsDaemon")
/**
* @brief Name Server Daemon
* @note NdnsDaemon allows multiple name servers hosted by the same daemon, and they
* share same KeyChain, DbMgr, Validator and Face
*/
class NdnsDaemon : noncopyable
{
public:
DEFINE_ERROR(Error, std::runtime_error);
explicit
NdnsDaemon(const std::string& configFile, Face& face, Face& validatorFace)
: m_face(face)
, m_validatorFace(validatorFace)
{
try {
ConfigFile config;
NDNS_LOG_INFO("NnsnDaemon ConfigFile = " << configFile);
config.addSectionHandler("zones",
bind(&NdnsDaemon::processZonesSection, this, _1, _3));
config.parse(configFile, false);
}
catch (const boost::filesystem::filesystem_error& e) {
if (e.code() == boost::system::errc::permission_denied) {
NDNS_LOG_FATAL("Permissions denied for " << e.path1());
}
else {
NDNS_LOG_FATAL(e.what());
}
}
catch (const std::exception& e) {
NDNS_LOG_FATAL(e.what());
}
}
void
processZonesSection(const ndn::ndns::ConfigSection& section, const std::string& filename)
{
using namespace boost::filesystem;
using namespace ndn::ndns;
using ndn::ndns::ConfigSection;
if (section.begin() == section.end()) {
BOOST_THROW_EXCEPTION(Error("zones section is empty"));
}
std::string dbFile = DEFAULT_DATABASE_PATH "/" "ndns.db";
ConfigSection::const_assoc_iterator item = section.find("dbFile");
if (item != section.not_found()) {
dbFile = item->second.get_value<std::string>();
}
NDNS_LOG_INFO("DbFile = " << dbFile);
m_dbMgr = unique_ptr<DbMgr>(new DbMgr(dbFile));
std::string validatorConfigFile = DEFAULT_CONFIG_PATH "/" "validator.conf";
item = section.find("validatorConfigFile");
if (item != section.not_found()) {
validatorConfigFile = item->second.get_value<std::string>();
}
NDNS_LOG_INFO("ValidatorConfigFile = " << validatorConfigFile);
m_validator = NdnsValidatorBuilder::create(m_validatorFace, 500, 0, validatorConfigFile);
for (const auto& option : section) {
Name name;
Name cert;
if (option.first == "zone") {
try {
name = option.second.get<Name>("name"); // exception leads to exit
}
catch (const std::exception& e) {
NDNS_LOG_ERROR("Required `name' attribute missing in `zone' section");
BOOST_THROW_EXCEPTION(Error("Required `name' attribute missing in `zone' section"));
}
try {
cert = option.second.get<Name>("cert");
}
catch (const std::exception&) {
;
}
if (cert.empty()) {
try {
cert = CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, Name(name).append(label::NDNS_ITERATIVE_QUERY));
}
catch (const std::exception& e) {
NDNS_LOG_FATAL("Identity: " << name << " does not have default certificate. "
<< e.what());
BOOST_THROW_EXCEPTION(Error("identity does not have default certificate"));
}
}
else {
try {
CertHelper::getCertificate(m_keyChain, name, cert);
} catch (const std::exception& e) {
BOOST_THROW_EXCEPTION(Error("Certificate `" + cert.toUri() + "` does not exist in the KeyChain"));
}
}
NDNS_LOG_TRACE("name = " << name << " cert = " << cert);
m_servers.push_back(make_shared<NameServer>(name, cert, m_face, *m_dbMgr,
m_keyChain, *m_validator));
}
} // for
}
private:
Face& m_face;
Face& m_validatorFace;
unique_ptr<security::v2::Validator> m_validator;
unique_ptr<DbMgr> m_dbMgr;
std::vector<shared_ptr<NameServer>> m_servers;
KeyChain m_keyChain;
};
} // namespace ndns
} // namespace ndn
int
main(int argc, char* argv[])
{
using std::string;
using ndn::ndns::ConfigFile;
using namespace ndn::ndns;
ndn::ndns::log::init();
string configFile = DEFAULT_CONFIG_PATH "/" "ndns.conf";
try {
namespace po = boost::program_options;
po::variables_map vm;
po::options_description generic("Generic Options");
generic.add_options()("help,h", "print help message");
po::options_description config("Configuration");
config.add_options()
("config,c", po::value<string>(&configFile), "set the path of configuration file")
;
po::options_description cmdline_options;
cmdline_options.add(generic).add(config);
po::parsed_options parsed =
po::command_line_parser(argc, argv).options(cmdline_options).run();
po::store(parsed, vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << "Usage:\n"
<< " ndns-daemon [-c configFile]\n"
<< std::endl;
std::cout << generic << config << std::endl;
return 0;
}
}
catch (const std::exception& ex) {
std::cerr << "Parameter Error: " << ex.what() << std::endl;
return 1;
}
catch (...) {
std::cerr << "Parameter Unknown error" << std::endl;
return 1;
}
boost::asio::io_service io;
ndn::Face face(io);
ndn::Face validatorFace(io);
try {
// NFD does not to forward Interests to the face it was received from.
// If the name server and its validator share same face,
// the validator cannot be forwarded to the name server itself
// For current, two faces are used here.
// refs: https://redmine.named-data.net/issues/2206
// @TODO enhance validator to get the certificate from the local db if it has
NdnsDaemon daemon(configFile, face, validatorFace);
face.processEvents();
}
catch (const std::exception& e) {
NDNS_LOG_FATAL("ERROR: " << e.what());
return 1;
}
return 0;
}