blob: 70717c6336f01d4f122a3271a382e55fac27f383 [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"
34#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070035#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070036#include "mgmt/face-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070037#include "mgmt/strategy-choice-manager.hpp"
Junxiao Shiea48d8b2014-03-16 13:53:47 -070038#include "mgmt/status-server.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070039#include "core/config-file.hpp"
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060040#include "mgmt/general-config-section.hpp"
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -060041#include "mgmt/tables-config-section.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080042
Junxiao Shi09bf7c42014-01-31 11:10:25 -070043namespace nfd {
44
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070045NFD_LOG_INIT("NFD");
Junxiao Shi09bf7c42014-01-31 11:10:25 -070046
47struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080048{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070049 bool showUsage;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070050 bool showVersion;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060051 bool showModules;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070052 std::string config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070053};
54
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070055class Nfd : noncopyable
Junxiao Shi09bf7c42014-01-31 11:10:25 -070056{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070057public:
Alexander Afanasyev5959b012014-06-02 19:18:12 +030058 explicit
59 Nfd(const std::string& configFile)
60 : m_configFile(configFile)
61 , m_originalStreamBuf(0)
62 {
63 }
64
65 ~Nfd()
66 {
67 if (static_cast<bool>(m_originalStreamBuf)) {
68 std::clog.rdbuf(m_originalStreamBuf);
69 }
70 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060071
72 void
Alexander Afanasyev5959b012014-06-02 19:18:12 +030073 initialize()
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070074 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +030075 initializeLogging();
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060076
77 m_forwarder = make_shared<Forwarder>();
78
Alexander Afanasyev5959b012014-06-02 19:18:12 +030079 initializeManagement();
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060080
81 PrivilegeHelper::drop();
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060082 }
83
84
85 void
Alexander Afanasyev5959b012014-06-02 19:18:12 +030086 initializeLogging()
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060087 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060088 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060089 LoggerFactory::getInstance().setConfigFile(config);
90
Alexander Afanasyev5959b012014-06-02 19:18:12 +030091 config.parse(m_configFile, true);
92 config.parse(m_configFile, false);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060093 }
94
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060095 class IgnoreRibAndLogSections
96 {
97 public:
98 void
99 operator()(const std::string& filename,
100 const std::string& sectionName,
101 const ConfigSection& section,
102 bool isDryRun)
103
104 {
105 // Ignore "log" and sections beginning with "rib_" (intended for rib manager),
106 // but raise an error if we're missing a handler for an NFD section.
107
Yingdi Yue5224e92014-04-29 18:04:02 -0700108 if (sectionName.find("rib") == 0 || sectionName == "log")
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600109 {
110 // do nothing
111 }
112 else
113 {
114 // missing NFD section
115 ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
116 }
117 }
118 };
119
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600120 void
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300121 initializeManagement()
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600122 {
123 m_internalFace = make_shared<InternalFace>();
124
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700125 m_fibManager = make_shared<FibManager>(ref(m_forwarder->getFib()),
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600126 bind(&Forwarder::getFace, m_forwarder.get(), _1),
127 m_internalFace);
128
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700129 m_faceManager = make_shared<FaceManager>(ref(m_forwarder->getFaceTable()),
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600130 m_internalFace);
131
132 m_strategyChoiceManager =
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700133 make_shared<StrategyChoiceManager>(ref(m_forwarder->getStrategyChoice()),
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600134 m_internalFace);
135
136 m_statusServer = make_shared<StatusServer>(m_internalFace,
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700137 ref(*m_forwarder));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600138
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600139 ConfigFile config((IgnoreRibAndLogSections()));
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600140
141 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());
148
149 tablesConfig.setConfigFile(config);
150
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700151 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700152
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600153 m_forwarder->addFace(m_internalFace);
Junxiao Shic041ca32014-02-25 20:01:15 -0700154
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600155 m_faceManager->setConfigFile(config);
156
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700157 // parse config file
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300158 config.parse(m_configFile, true);
159 config.parse(m_configFile, false);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700160
Steve DiBenedetto9bcc88f2014-07-08 09:52:13 -0600161 tablesConfig.ensureTablesAreConfigured();
162
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700163 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600164 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700165 entry->addNextHop(m_internalFace, 0);
166 }
167
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700168 static void
169 printUsage(std::ostream& os, const std::string& programName)
170 {
171 os << "Usage: \n"
172 << " " << programName << " [options]\n"
173 << "\n"
174 << "Run NFD forwarding daemon\n"
175 << "\n"
176 << "Options:\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700177 << " [--help] - print this help message\n"
178 << " [--version] - print version and exit\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600179 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700180 << " [--config /path/to/nfd.conf] - path to configuration file "
181 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
182 ;
183 }
184
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600185 static void
186 printModules(std::ostream& os)
187 {
188 using namespace std;
189
190 os << "Available logging modules: \n";
191
192 list<string> modules(LoggerFactory::getInstance().getModules());
193 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
194 {
195 os << *i << "\n";
196 }
197 }
198
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700199 static bool
200 parseCommandLine(int argc, char** argv, ProgramOptions& options)
201 {
202 options.showUsage = false;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700203 options.showVersion = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600204 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700205 options.config = DEFAULT_CONFIG_FILE;
206
207 while (true) {
208 int optionIndex = 0;
209 static ::option longOptions[] = {
210 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600211 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700212 { "config" , required_argument, 0, 0 },
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700213 { "version", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700214 { 0 , 0 , 0, 0 }
215 };
216 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
217 if (c == -1)
218 break;
219
220 switch (c) {
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700221 case 0:
222 switch (optionIndex) {
223 case 0: // help
224 options.showUsage = true;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700225 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700226 case 1: // modules
227 options.showModules = true;
228 break;
229 case 2: // config
230 options.config = ::optarg;
231 break;
232 case 3: // version
233 options.showVersion = true;
234 break;
235 default:
236 return false;
237 }
238 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700239 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700240 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700241 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700242 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700243
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700244 void
245 terminate(const boost::system::error_code& error,
246 int signalNo,
247 boost::asio::signal_set& signalSet)
248 {
249 if (error)
250 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700251
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700252 if (signalNo == SIGINT ||
253 signalNo == SIGTERM)
254 {
255 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700256 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700257 }
258 else
259 {
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700260 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2, ref(signalSet)));
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700261 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700262 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600263
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300264 void
265 reload(const boost::system::error_code& error,
266 int signalNo,
267 boost::asio::signal_set& signalSet)
268 {
269 if (error)
270 return;
271
272 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo));
273
274 ////////////////////////
275 // Reload config file //
276 ////////////////////////
277
278 // Logging
279 initializeLogging();
280 /// \todo Reopen log file
281
282 // Other stuff
283 ConfigFile config((IgnoreRibAndLogSections()));
284
285 general::setConfigFile(config);
286
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -0600287 TablesConfigSection tablesConfig(m_forwarder->getCs(),
288 m_forwarder->getPit(),
289 m_forwarder->getFib(),
290 m_forwarder->getStrategyChoice(),
291 m_forwarder->getMeasurements());
292
293 tablesConfig.setConfigFile(config);
294
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300295 m_internalFace->getValidator().setConfigFile(config);
296 m_faceManager->setConfigFile(config);
297
298 config.parse(m_configFile, false);
299
300 ////////////////////////
301
302 signalSet.async_wait(bind(&Nfd::reload, this, _1, _2, ref(signalSet)));
303 }
304
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700305private:
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300306 std::string m_configFile;
307
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600308 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600309
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600310 shared_ptr<InternalFace> m_internalFace;
311 shared_ptr<FibManager> m_fibManager;
312 shared_ptr<FaceManager> m_faceManager;
313 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
314 shared_ptr<StatusServer> m_statusServer;
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300315
316 shared_ptr<std::ofstream> m_logFile;
317 std::basic_streambuf<char>* m_originalStreamBuf;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700318};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700319
320} // namespace nfd
321
322int
323main(int argc, char** argv)
324{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700325 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700326
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700327 ProgramOptions options;
328 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
329 if (!isCommandLineValid) {
330 Nfd::printUsage(std::cerr, argv[0]);
331 return 1;
332 }
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700333
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700334 if (options.showUsage) {
335 Nfd::printUsage(std::cout, argv[0]);
336 return 0;
337 }
338
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700339 if (options.showVersion) {
340 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
341 return 0;
342 }
343
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600344 if (options.showModules) {
345 Nfd::printModules(std::cout);
346 return 0;
347 }
348
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300349 Nfd nfdInstance(options.config);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600350
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700351 try {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300352 nfdInstance.initialize();
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700353 }
354 catch (boost::filesystem::filesystem_error& e) {
355 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600356 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
357 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700358 }
359 else {
360 NFD_LOG_FATAL(e.what());
361 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600362 return 1;
363 }
364 catch (const std::exception& e) {
365 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700366 return 2;
367 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600368 catch (const PrivilegeHelper::Error& e) {
369 // PrivilegeHelper::Errors do not inherit from std::exception
370 // and represent seteuid/gid failures
371
372 NFD_LOG_FATAL(e.what());
373 return 3;
374 }
375
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300376 boost::asio::signal_set terminationSignalSet(getGlobalIoService());
377 terminationSignalSet.add(SIGINT);
378 terminationSignalSet.add(SIGTERM);
379 terminationSignalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
380 ref(terminationSignalSet)));
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600381
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300382 boost::asio::signal_set reloadSignalSet(getGlobalIoService());
383 reloadSignalSet.add(SIGHUP);
384 reloadSignalSet.async_wait(bind(&Nfd::reload, &nfdInstance, _1, _2,
385 ref(reloadSignalSet)));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600386
387 try {
388 getGlobalIoService().run();
389 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600390 catch (const std::exception& e) {
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700391 NFD_LOG_FATAL(e.what());
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600392 return 4;
393 }
394 catch (const PrivilegeHelper::Error& e) {
395 NFD_LOG_FATAL(e.what());
396 return 5;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700397 }
398
399 return 0;
400}