blob: e27566804b66ae3a72bf7ed4748588245361d447 [file] [log] [blame]
Alexander Afanasyev2aa39622014-01-22 11:51:11 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -06003 * Copyright (c) 2014, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -060024 */
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080025
Junxiao Shi09bf7c42014-01-31 11:10:25 -070026#include <getopt.h>
Junxiao Shi98e29f42014-03-31 10:27:26 -070027#include <boost/filesystem.hpp>
28
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070029#include "version.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070030#include "core/logger.hpp"
Junxiao Shi98e29f42014-03-31 10:27:26 -070031#include "core/global-io.hpp"
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060032#include "core/privilege-helper.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070033#include "fw/forwarder.hpp"
Junxiao Shi7b984c62014-07-17 22:18:34 -070034#include "face/null-face.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070035#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070036#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070037#include "mgmt/face-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070038#include "mgmt/strategy-choice-manager.hpp"
Junxiao Shiea48d8b2014-03-16 13:53:47 -070039#include "mgmt/status-server.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070040#include "core/config-file.hpp"
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060041#include "mgmt/general-config-section.hpp"
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -060042#include "mgmt/tables-config-section.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080043
Junxiao Shi09bf7c42014-01-31 11:10:25 -070044namespace nfd {
45
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070046NFD_LOG_INIT("NFD");
Junxiao Shi09bf7c42014-01-31 11:10:25 -070047
48struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080049{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070050 bool showUsage;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070051 bool showVersion;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060052 bool showModules;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070053 std::string config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070054};
55
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070056class Nfd : noncopyable
Junxiao Shi09bf7c42014-01-31 11:10:25 -070057{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070058public:
Alexander Afanasyev5959b012014-06-02 19:18:12 +030059 explicit
60 Nfd(const std::string& configFile)
61 : m_configFile(configFile)
62 , m_originalStreamBuf(0)
63 {
64 }
65
66 ~Nfd()
67 {
68 if (static_cast<bool>(m_originalStreamBuf)) {
69 std::clog.rdbuf(m_originalStreamBuf);
70 }
71 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060072
73 void
Alexander Afanasyev5959b012014-06-02 19:18:12 +030074 initialize()
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070075 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +030076 initializeLogging();
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060077
78 m_forwarder = make_shared<Forwarder>();
79
Alexander Afanasyev5959b012014-06-02 19:18:12 +030080 initializeManagement();
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060081
Junxiao Shi7b984c62014-07-17 22:18:34 -070082 m_forwarder->getFaceTable().addReserved(make_shared<NullFace>(), FACEID_NULL);
83 m_forwarder->getFaceTable().addReserved(
84 make_shared<NullFace>(FaceUri("contentstore://")), FACEID_CONTENT_STORE);
85
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060086 PrivilegeHelper::drop();
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060087 }
88
89
90 void
Alexander Afanasyev5959b012014-06-02 19:18:12 +030091 initializeLogging()
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060092 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060093 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060094 LoggerFactory::getInstance().setConfigFile(config);
95
Alexander Afanasyev5959b012014-06-02 19:18:12 +030096 config.parse(m_configFile, true);
97 config.parse(m_configFile, false);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060098 }
99
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600100 class IgnoreRibAndLogSections
101 {
102 public:
103 void
104 operator()(const std::string& filename,
105 const std::string& sectionName,
106 const ConfigSection& section,
107 bool isDryRun)
108
109 {
110 // Ignore "log" and sections beginning with "rib_" (intended for rib manager),
111 // but raise an error if we're missing a handler for an NFD section.
112
Yingdi Yue5224e92014-04-29 18:04:02 -0700113 if (sectionName.find("rib") == 0 || sectionName == "log")
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600114 {
115 // do nothing
116 }
117 else
118 {
119 // missing NFD section
120 ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
121 }
122 }
123 };
124
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600125 void
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300126 initializeManagement()
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600127 {
128 m_internalFace = make_shared<InternalFace>();
129
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700130 m_fibManager = make_shared<FibManager>(ref(m_forwarder->getFib()),
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600131 bind(&Forwarder::getFace, m_forwarder.get(), _1),
Vince Lehman5144f822014-07-23 15:12:56 -0700132 m_internalFace,
133 ndn::ref(m_keyChain));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600134
Vince Lehman5144f822014-07-23 15:12:56 -0700135 m_faceManager = make_shared<FaceManager>(ref(m_forwarder->getFaceTable()),
136 m_internalFace,
137 ndn::ref(m_keyChain));
138
139 m_strategyChoiceManager =
140 make_shared<StrategyChoiceManager>(ref(m_forwarder->getStrategyChoice()),
141 m_internalFace,
142 ndn::ref(m_keyChain));
143
144 m_statusServer = make_shared<StatusServer>(m_internalFace,
145 ref(*m_forwarder),
146 ndn::ref(m_keyChain));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600147
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600148 ConfigFile config((IgnoreRibAndLogSections()));
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600149 general::setConfigFile(config);
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -0600150
151 TablesConfigSection tablesConfig(m_forwarder->getCs(),
152 m_forwarder->getPit(),
153 m_forwarder->getFib(),
154 m_forwarder->getStrategyChoice(),
155 m_forwarder->getMeasurements());
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -0600156 tablesConfig.setConfigFile(config);
157
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700158 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700159
Junxiao Shi7b984c62014-07-17 22:18:34 -0700160 m_forwarder->getFaceTable().addReserved(m_internalFace, FACEID_INTERNAL_FACE);
Junxiao Shic041ca32014-02-25 20:01:15 -0700161
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600162 m_faceManager->setConfigFile(config);
163
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700164 // parse config file
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300165 config.parse(m_configFile, true);
166 config.parse(m_configFile, false);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700167
Steve DiBenedetto9bcc88f2014-07-08 09:52:13 -0600168 tablesConfig.ensureTablesAreConfigured();
169
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700170 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600171 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700172 entry->addNextHop(m_internalFace, 0);
173 }
174
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700175 static void
176 printUsage(std::ostream& os, const std::string& programName)
177 {
178 os << "Usage: \n"
179 << " " << programName << " [options]\n"
180 << "\n"
181 << "Run NFD forwarding daemon\n"
182 << "\n"
183 << "Options:\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700184 << " [--help] - print this help message\n"
185 << " [--version] - print version and exit\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600186 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700187 << " [--config /path/to/nfd.conf] - path to configuration file "
188 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
189 ;
190 }
191
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600192 static void
193 printModules(std::ostream& os)
194 {
195 using namespace std;
196
197 os << "Available logging modules: \n";
198
199 list<string> modules(LoggerFactory::getInstance().getModules());
200 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
201 {
202 os << *i << "\n";
203 }
204 }
205
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700206 static bool
207 parseCommandLine(int argc, char** argv, ProgramOptions& options)
208 {
209 options.showUsage = false;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700210 options.showVersion = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600211 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700212 options.config = DEFAULT_CONFIG_FILE;
213
214 while (true) {
215 int optionIndex = 0;
216 static ::option longOptions[] = {
217 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600218 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700219 { "config" , required_argument, 0, 0 },
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700220 { "version", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700221 { 0 , 0 , 0, 0 }
222 };
223 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
224 if (c == -1)
225 break;
226
227 switch (c) {
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700228 case 0:
229 switch (optionIndex) {
230 case 0: // help
231 options.showUsage = true;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700232 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700233 case 1: // modules
234 options.showModules = true;
235 break;
236 case 2: // config
237 options.config = ::optarg;
238 break;
239 case 3: // version
240 options.showVersion = true;
241 break;
242 default:
243 return false;
244 }
245 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700246 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700247 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700248 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700249 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700250
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700251 void
252 terminate(const boost::system::error_code& error,
253 int signalNo,
254 boost::asio::signal_set& signalSet)
255 {
256 if (error)
257 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700258
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700259 if (signalNo == SIGINT ||
260 signalNo == SIGTERM)
261 {
262 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700263 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700264 }
265 else
266 {
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700267 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2, ref(signalSet)));
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700268 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700269 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600270
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300271 void
272 reload(const boost::system::error_code& error,
273 int signalNo,
274 boost::asio::signal_set& signalSet)
275 {
276 if (error)
277 return;
278
279 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo));
280
281 ////////////////////////
282 // Reload config file //
283 ////////////////////////
284
285 // Logging
286 initializeLogging();
287 /// \todo Reopen log file
288
289 // Other stuff
290 ConfigFile config((IgnoreRibAndLogSections()));
291
292 general::setConfigFile(config);
293
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -0600294 TablesConfigSection tablesConfig(m_forwarder->getCs(),
295 m_forwarder->getPit(),
296 m_forwarder->getFib(),
297 m_forwarder->getStrategyChoice(),
298 m_forwarder->getMeasurements());
299
300 tablesConfig.setConfigFile(config);
301
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300302 m_internalFace->getValidator().setConfigFile(config);
303 m_faceManager->setConfigFile(config);
304
305 config.parse(m_configFile, false);
306
307 ////////////////////////
308
309 signalSet.async_wait(bind(&Nfd::reload, this, _1, _2, ref(signalSet)));
310 }
311
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700312private:
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300313 std::string m_configFile;
314
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600315 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600316
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600317 shared_ptr<InternalFace> m_internalFace;
318 shared_ptr<FibManager> m_fibManager;
319 shared_ptr<FaceManager> m_faceManager;
320 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
321 shared_ptr<StatusServer> m_statusServer;
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300322
323 shared_ptr<std::ofstream> m_logFile;
324 std::basic_streambuf<char>* m_originalStreamBuf;
Vince Lehman5144f822014-07-23 15:12:56 -0700325 ndn::KeyChain m_keyChain;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700326};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700327
328} // namespace nfd
329
330int
331main(int argc, char** argv)
332{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700333 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700334
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700335 ProgramOptions options;
336 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
337 if (!isCommandLineValid) {
338 Nfd::printUsage(std::cerr, argv[0]);
339 return 1;
340 }
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700341
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700342 if (options.showUsage) {
343 Nfd::printUsage(std::cout, argv[0]);
344 return 0;
345 }
346
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700347 if (options.showVersion) {
348 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
349 return 0;
350 }
351
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600352 if (options.showModules) {
353 Nfd::printModules(std::cout);
354 return 0;
355 }
356
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300357 Nfd nfdInstance(options.config);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600358
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700359 try {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300360 nfdInstance.initialize();
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700361 }
362 catch (boost::filesystem::filesystem_error& e) {
363 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600364 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
365 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700366 }
367 else {
368 NFD_LOG_FATAL(e.what());
369 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600370 return 1;
371 }
372 catch (const std::exception& e) {
373 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700374 return 2;
375 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600376 catch (const PrivilegeHelper::Error& e) {
377 // PrivilegeHelper::Errors do not inherit from std::exception
378 // and represent seteuid/gid failures
379
380 NFD_LOG_FATAL(e.what());
381 return 3;
382 }
383
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300384 boost::asio::signal_set terminationSignalSet(getGlobalIoService());
385 terminationSignalSet.add(SIGINT);
386 terminationSignalSet.add(SIGTERM);
387 terminationSignalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
388 ref(terminationSignalSet)));
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600389
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300390 boost::asio::signal_set reloadSignalSet(getGlobalIoService());
391 reloadSignalSet.add(SIGHUP);
392 reloadSignalSet.async_wait(bind(&Nfd::reload, &nfdInstance, _1, _2,
393 ref(reloadSignalSet)));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600394
395 try {
396 getGlobalIoService().run();
397 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600398 catch (const std::exception& e) {
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700399 NFD_LOG_FATAL(e.what());
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600400 return 4;
401 }
402 catch (const PrivilegeHelper::Error& e) {
403 NFD_LOG_FATAL(e.what());
404 return 5;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700405 }
406
407 return 0;
408}