blob: 2f71a452c6ed25e41d76b5bd1cc459dac0501bff [file] [log] [blame]
Shock Jiangcde28712014-10-19 21:17:20 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yumin Xia2c509c22017-02-09 14:37:36 -08002/*
Alexander Afanasyev60514ec2020-06-03 14:18:53 -04003 * Copyright (c) 2014-2020, Regents of the University of California.
Shock Jiangcde28712014-10-19 21:17:20 -07004 *
5 * This file is part of NDNS (Named Data Networking Domain Name Service).
6 * See AUTHORS.md for complete list of NDNS authors and contributors.
7 *
8 * NDNS is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
Davide Pesavento7debce92019-01-20 16:12:29 -050020#include "logger.hpp"
Shock Jiangcde28712014-10-19 21:17:20 -070021#include "daemon/config-file.hpp"
Davide Pesavento7debce92019-01-20 16:12:29 -050022#include "daemon/name-server.hpp"
Yumin Xia2c509c22017-02-09 14:37:36 -080023#include "util/cert-helper.hpp"
Davide Pesaventod01c1a42019-01-21 21:42:45 -050024#include "util/util.hpp"
Yumin Xia2c509c22017-02-09 14:37:36 -080025
Davide Pesavento7debce92019-01-20 16:12:29 -050026#include <ndn-cxx/face.hpp>
27#include <ndn-cxx/security/key-chain.hpp>
28
29#include <boost/asio/io_service.hpp>
Yumin Xia2c509c22017-02-09 14:37:36 -080030#include <boost/filesystem.hpp>
Davide Pesavento7debce92019-01-20 16:12:29 -050031#include <boost/program_options.hpp>
32
33NDNS_LOG_INIT(NdnsDaemon);
Shock Jiangcde28712014-10-19 21:17:20 -070034
35namespace ndn {
36namespace ndns {
37
Shock Jiangcde28712014-10-19 21:17:20 -070038/**
39 * @brief Name Server Daemon
40 * @note NdnsDaemon allows multiple name servers hosted by the same daemon, and they
41 * share same KeyChain, DbMgr, Validator and Face
42 */
43class NdnsDaemon : noncopyable
44{
Shock Jiange1a81fd2014-11-20 20:25:49 -080045public:
Shock Jiangcde28712014-10-19 21:17:20 -070046 DEFINE_ERROR(Error, std::runtime_error);
47
Shock Jiange1a81fd2014-11-20 20:25:49 -080048 NdnsDaemon(const std::string& configFile, Face& face, Face& validatorFace)
49 : m_face(face)
50 , m_validatorFace(validatorFace)
Shock Jiangcde28712014-10-19 21:17:20 -070051 {
Davide Pesavento7debce92019-01-20 16:12:29 -050052 NDNS_LOG_INFO("ConfigFile = " << configFile);
53 ConfigFile config;
54 config.addSectionHandler("zones", bind(&NdnsDaemon::processZonesSection, this, _1));
55 config.parse(configFile, false);
Shock Jiangcde28712014-10-19 21:17:20 -070056 }
57
58 void
Davide Pesavento7debce92019-01-20 16:12:29 -050059 processZonesSection(const ndn::ndns::ConfigSection& section)
Shock Jiangcde28712014-10-19 21:17:20 -070060 {
Shock Jiangcde28712014-10-19 21:17:20 -070061 if (section.begin() == section.end()) {
Yumin Xia2c509c22017-02-09 14:37:36 -080062 BOOST_THROW_EXCEPTION(Error("zones section is empty"));
Shock Jiangcde28712014-10-19 21:17:20 -070063 }
64
Davide Pesaventod01c1a42019-01-21 21:42:45 -050065 std::string dbFile = getDefaultDatabaseFile();
Davide Pesavento7debce92019-01-20 16:12:29 -050066 auto item = section.find("dbFile");
Shock Jiangcde28712014-10-19 21:17:20 -070067 if (item != section.not_found()) {
Shock Jiange1a81fd2014-11-20 20:25:49 -080068 dbFile = item->second.get_value<std::string>();
Shock Jiangcde28712014-10-19 21:17:20 -070069 }
Shock Jiange1a81fd2014-11-20 20:25:49 -080070 NDNS_LOG_INFO("DbFile = " << dbFile);
Davide Pesavento7debce92019-01-20 16:12:29 -050071 m_dbMgr = make_unique<DbMgr>(dbFile);
Shock Jiangcde28712014-10-19 21:17:20 -070072
Davide Pesaventod01c1a42019-01-21 21:42:45 -050073 std::string validatorConfigFile(NDNS_CONFDIR "/validator.conf");
Shock Jiange1a81fd2014-11-20 20:25:49 -080074 item = section.find("validatorConfigFile");
75 if (item != section.not_found()) {
76 validatorConfigFile = item->second.get_value<std::string>();
77 }
78 NDNS_LOG_INFO("ValidatorConfigFile = " << validatorConfigFile);
Yumin Xiafa2bce72017-04-09 16:20:25 -070079 m_validator = NdnsValidatorBuilder::create(m_validatorFace, 500, 0, validatorConfigFile);
Shock Jiangcde28712014-10-19 21:17:20 -070080
81 for (const auto& option : section) {
82 Name name;
83 Name cert;
84 if (option.first == "zone") {
85 try {
86 name = option.second.get<Name>("name"); // exception leads to exit
87 }
Davide Pesavento7debce92019-01-20 16:12:29 -050088 catch (const std::exception&) {
Shock Jiangcde28712014-10-19 21:17:20 -070089 NDNS_LOG_ERROR("Required `name' attribute missing in `zone' section");
Yumin Xia2c509c22017-02-09 14:37:36 -080090 BOOST_THROW_EXCEPTION(Error("Required `name' attribute missing in `zone' section"));
Shock Jiangcde28712014-10-19 21:17:20 -070091 }
92 try {
93 cert = option.second.get<Name>("cert");
94 }
Yumin Xia2c509c22017-02-09 14:37:36 -080095 catch (const std::exception&) {
Davide Pesavento7debce92019-01-20 16:12:29 -050096 // ignore
Shock Jiangcde28712014-10-19 21:17:20 -070097 }
98
99 if (cert.empty()) {
Shock Jiange1a81fd2014-11-20 20:25:49 -0800100 try {
Davide Pesavento7debce92019-01-20 16:12:29 -0500101 cert = CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain,
102 Name(name)
103 .append(label::NDNS_ITERATIVE_QUERY));
Shock Jiange1a81fd2014-11-20 20:25:49 -0800104 }
Yumin Xia2c509c22017-02-09 14:37:36 -0800105 catch (const std::exception& e) {
Davide Pesavento7debce92019-01-20 16:12:29 -0500106 NDNS_LOG_ERROR("Identity " << name << " does not have a default certificate: " << e.what());
Yumin Xia2c509c22017-02-09 14:37:36 -0800107 BOOST_THROW_EXCEPTION(Error("identity does not have default certificate"));
Shock Jiange1a81fd2014-11-20 20:25:49 -0800108 }
Shock Jiangcde28712014-10-19 21:17:20 -0700109 }
110 else {
Yumin Xia2c509c22017-02-09 14:37:36 -0800111 try {
112 CertHelper::getCertificate(m_keyChain, name, cert);
Davide Pesavento7debce92019-01-20 16:12:29 -0500113 } catch (const std::exception&) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800114 BOOST_THROW_EXCEPTION(Error("Certificate `" + cert.toUri() + "` does not exist in the KeyChain"));
Shock Jiangcde28712014-10-19 21:17:20 -0700115 }
116 }
117 NDNS_LOG_TRACE("name = " << name << " cert = " << cert);
118 m_servers.push_back(make_shared<NameServer>(name, cert, m_face, *m_dbMgr,
Shock Jiange1a81fd2014-11-20 20:25:49 -0800119 m_keyChain, *m_validator));
Shock Jiangcde28712014-10-19 21:17:20 -0700120 }
121 } // for
122 }
123
124private:
Shock Jiangcde28712014-10-19 21:17:20 -0700125 Face& m_face;
Shock Jiange1a81fd2014-11-20 20:25:49 -0800126 Face& m_validatorFace;
Alexander Afanasyev60514ec2020-06-03 14:18:53 -0400127 unique_ptr<security::Validator> m_validator;
Shock Jiange1a81fd2014-11-20 20:25:49 -0800128 unique_ptr<DbMgr> m_dbMgr;
129 std::vector<shared_ptr<NameServer>> m_servers;
Shock Jiangcde28712014-10-19 21:17:20 -0700130 KeyChain m_keyChain;
131};
132
133} // namespace ndns
134} // namespace ndn
135
136int
137main(int argc, char* argv[])
138{
Davide Pesaventod01c1a42019-01-21 21:42:45 -0500139 std::string configFile(NDNS_CONFDIR "/ndns.conf");
Shock Jiangcde28712014-10-19 21:17:20 -0700140
Davide Pesavento7debce92019-01-20 16:12:29 -0500141 namespace po = boost::program_options;
142 po::options_description optsDesc("Options");
143 optsDesc.add_options()
144 ("help,h", "print this help message and exit")
145 ("config-file,c", po::value<std::string>(&configFile)->default_value(configFile),
146 "path to configuration file")
147 ;
Shock Jiangcde28712014-10-19 21:17:20 -0700148
Davide Pesavento7debce92019-01-20 16:12:29 -0500149 po::variables_map vm;
Shock Jiangcde28712014-10-19 21:17:20 -0700150 try {
Davide Pesavento7debce92019-01-20 16:12:29 -0500151 po::store(po::parse_command_line(argc, argv, optsDesc), vm);
Shock Jiangcde28712014-10-19 21:17:20 -0700152 po::notify(vm);
Shock Jiangcde28712014-10-19 21:17:20 -0700153 }
Davide Pesavento7debce92019-01-20 16:12:29 -0500154 catch (const po::error& e) {
155 std::cerr << "ERROR: " << e.what() << std::endl;
156 return 2;
Shock Jiangcde28712014-10-19 21:17:20 -0700157 }
Davide Pesavento7debce92019-01-20 16:12:29 -0500158 catch (const boost::bad_any_cast& e) {
159 std::cerr << "ERROR: " << e.what() << std::endl;
160 return 2;
161 }
162
163 if (vm.count("help") != 0) {
164 std::cout << "Usage: " << argv[0] << " [options]\n"
165 << "\n"
166 << optsDesc;
167 return 0;
Shock Jiangcde28712014-10-19 21:17:20 -0700168 }
169
Shock Jiange1a81fd2014-11-20 20:25:49 -0800170 boost::asio::io_service io;
171 ndn::Face face(io);
172 ndn::Face validatorFace(io);
173
Shock Jiangcde28712014-10-19 21:17:20 -0700174 try {
Shock Jiange1a81fd2014-11-20 20:25:49 -0800175 // NFD does not to forward Interests to the face it was received from.
Davide Pesavento7debce92019-01-20 16:12:29 -0500176 // If the name server and its validator share the same face,
Shock Jiange1a81fd2014-11-20 20:25:49 -0800177 // the validator cannot be forwarded to the name server itself
Davide Pesavento7debce92019-01-20 16:12:29 -0500178 // For now, two faces are used here.
Shock Jiang06cd2142014-11-23 17:36:02 -0800179
Yumin Xia2c509c22017-02-09 14:37:36 -0800180 // refs: https://redmine.named-data.net/issues/2206
Davide Pesavento7debce92019-01-20 16:12:29 -0500181 // @TODO enhance validator to get the certificate from the local db if present
Shock Jiangcde28712014-10-19 21:17:20 -0700182
Davide Pesavento7debce92019-01-20 16:12:29 -0500183 ndn::ndns::NdnsDaemon daemon(configFile, face, validatorFace);
Shock Jiangcde28712014-10-19 21:17:20 -0700184 face.processEvents();
185 }
Yumin Xia2c509c22017-02-09 14:37:36 -0800186 catch (const std::exception& e) {
Davide Pesavento7debce92019-01-20 16:12:29 -0500187 NDNS_LOG_FATAL(e.what());
Shock Jiange1a81fd2014-11-20 20:25:49 -0800188 return 1;
Shock Jiangcde28712014-10-19 21:17:20 -0700189 }
190
191 return 0;
192}