blob: 2509307c8f781c4c4dc7f736f1b9eb300e9fcf62 [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),
132 m_internalFace);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700133 m_faceManager = make_shared<FaceManager>(ref(m_forwarder->getFaceTable()),
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600134 m_internalFace);
Junxiao Shi7b984c62014-07-17 22:18:34 -0700135 m_strategyChoiceManager = make_shared<StrategyChoiceManager>(
136 ref(m_forwarder->getStrategyChoice()), m_internalFace);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600137
Junxiao Shi7b984c62014-07-17 22:18:34 -0700138 m_statusServer = make_shared<StatusServer>(m_internalFace, ref(*m_forwarder));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600139
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600140 ConfigFile config((IgnoreRibAndLogSections()));
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600141 general::setConfigFile(config);
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -0600142
143 TablesConfigSection tablesConfig(m_forwarder->getCs(),
144 m_forwarder->getPit(),
145 m_forwarder->getFib(),
146 m_forwarder->getStrategyChoice(),
147 m_forwarder->getMeasurements());
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -0600148 tablesConfig.setConfigFile(config);
149
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700150 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700151
Junxiao Shi7b984c62014-07-17 22:18:34 -0700152 m_forwarder->getFaceTable().addReserved(m_internalFace, FACEID_INTERNAL_FACE);
Junxiao Shic041ca32014-02-25 20:01:15 -0700153
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600154 m_faceManager->setConfigFile(config);
155
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700156 // parse config file
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300157 config.parse(m_configFile, true);
158 config.parse(m_configFile, false);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700159
Steve DiBenedetto9bcc88f2014-07-08 09:52:13 -0600160 tablesConfig.ensureTablesAreConfigured();
161
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700162 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600163 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700164 entry->addNextHop(m_internalFace, 0);
165 }
166
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700167 static void
168 printUsage(std::ostream& os, const std::string& programName)
169 {
170 os << "Usage: \n"
171 << " " << programName << " [options]\n"
172 << "\n"
173 << "Run NFD forwarding daemon\n"
174 << "\n"
175 << "Options:\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700176 << " [--help] - print this help message\n"
177 << " [--version] - print version and exit\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600178 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700179 << " [--config /path/to/nfd.conf] - path to configuration file "
180 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
181 ;
182 }
183
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600184 static void
185 printModules(std::ostream& os)
186 {
187 using namespace std;
188
189 os << "Available logging modules: \n";
190
191 list<string> modules(LoggerFactory::getInstance().getModules());
192 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
193 {
194 os << *i << "\n";
195 }
196 }
197
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700198 static bool
199 parseCommandLine(int argc, char** argv, ProgramOptions& options)
200 {
201 options.showUsage = false;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700202 options.showVersion = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600203 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700204 options.config = DEFAULT_CONFIG_FILE;
205
206 while (true) {
207 int optionIndex = 0;
208 static ::option longOptions[] = {
209 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600210 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700211 { "config" , required_argument, 0, 0 },
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700212 { "version", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700213 { 0 , 0 , 0, 0 }
214 };
215 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
216 if (c == -1)
217 break;
218
219 switch (c) {
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700220 case 0:
221 switch (optionIndex) {
222 case 0: // help
223 options.showUsage = true;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700224 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700225 case 1: // modules
226 options.showModules = true;
227 break;
228 case 2: // config
229 options.config = ::optarg;
230 break;
231 case 3: // version
232 options.showVersion = true;
233 break;
234 default:
235 return false;
236 }
237 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700238 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700239 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700240 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700241 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700242
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700243 void
244 terminate(const boost::system::error_code& error,
245 int signalNo,
246 boost::asio::signal_set& signalSet)
247 {
248 if (error)
249 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700250
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700251 if (signalNo == SIGINT ||
252 signalNo == SIGTERM)
253 {
254 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700255 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700256 }
257 else
258 {
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700259 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2, ref(signalSet)));
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700260 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700261 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600262
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300263 void
264 reload(const boost::system::error_code& error,
265 int signalNo,
266 boost::asio::signal_set& signalSet)
267 {
268 if (error)
269 return;
270
271 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo));
272
273 ////////////////////////
274 // Reload config file //
275 ////////////////////////
276
277 // Logging
278 initializeLogging();
279 /// \todo Reopen log file
280
281 // Other stuff
282 ConfigFile config((IgnoreRibAndLogSections()));
283
284 general::setConfigFile(config);
285
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -0600286 TablesConfigSection tablesConfig(m_forwarder->getCs(),
287 m_forwarder->getPit(),
288 m_forwarder->getFib(),
289 m_forwarder->getStrategyChoice(),
290 m_forwarder->getMeasurements());
291
292 tablesConfig.setConfigFile(config);
293
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300294 m_internalFace->getValidator().setConfigFile(config);
295 m_faceManager->setConfigFile(config);
296
297 config.parse(m_configFile, false);
298
299 ////////////////////////
300
301 signalSet.async_wait(bind(&Nfd::reload, this, _1, _2, ref(signalSet)));
302 }
303
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700304private:
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300305 std::string m_configFile;
306
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600307 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600308
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600309 shared_ptr<InternalFace> m_internalFace;
310 shared_ptr<FibManager> m_fibManager;
311 shared_ptr<FaceManager> m_faceManager;
312 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
313 shared_ptr<StatusServer> m_statusServer;
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300314
315 shared_ptr<std::ofstream> m_logFile;
316 std::basic_streambuf<char>* m_originalStreamBuf;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700317};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700318
319} // namespace nfd
320
321int
322main(int argc, char** argv)
323{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700324 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700325
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700326 ProgramOptions options;
327 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
328 if (!isCommandLineValid) {
329 Nfd::printUsage(std::cerr, argv[0]);
330 return 1;
331 }
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700332
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700333 if (options.showUsage) {
334 Nfd::printUsage(std::cout, argv[0]);
335 return 0;
336 }
337
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700338 if (options.showVersion) {
339 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
340 return 0;
341 }
342
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600343 if (options.showModules) {
344 Nfd::printModules(std::cout);
345 return 0;
346 }
347
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300348 Nfd nfdInstance(options.config);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600349
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700350 try {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300351 nfdInstance.initialize();
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700352 }
353 catch (boost::filesystem::filesystem_error& e) {
354 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600355 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
356 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700357 }
358 else {
359 NFD_LOG_FATAL(e.what());
360 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600361 return 1;
362 }
363 catch (const std::exception& e) {
364 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700365 return 2;
366 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600367 catch (const PrivilegeHelper::Error& e) {
368 // PrivilegeHelper::Errors do not inherit from std::exception
369 // and represent seteuid/gid failures
370
371 NFD_LOG_FATAL(e.what());
372 return 3;
373 }
374
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300375 boost::asio::signal_set terminationSignalSet(getGlobalIoService());
376 terminationSignalSet.add(SIGINT);
377 terminationSignalSet.add(SIGTERM);
378 terminationSignalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
379 ref(terminationSignalSet)));
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600380
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300381 boost::asio::signal_set reloadSignalSet(getGlobalIoService());
382 reloadSignalSet.add(SIGHUP);
383 reloadSignalSet.async_wait(bind(&Nfd::reload, &nfdInstance, _1, _2,
384 ref(reloadSignalSet)));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600385
386 try {
387 getGlobalIoService().run();
388 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600389 catch (const std::exception& e) {
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700390 NFD_LOG_FATAL(e.what());
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600391 return 4;
392 }
393 catch (const PrivilegeHelper::Error& e) {
394 NFD_LOG_FATAL(e.what());
395 return 5;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700396 }
397
398 return 0;
399}