blob: 9fd191eff8fb74d5a5f412c7e71e71a67239f217 [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
161 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600162 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700163 entry->addNextHop(m_internalFace, 0);
164 }
165
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700166 static void
167 printUsage(std::ostream& os, const std::string& programName)
168 {
169 os << "Usage: \n"
170 << " " << programName << " [options]\n"
171 << "\n"
172 << "Run NFD forwarding daemon\n"
173 << "\n"
174 << "Options:\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700175 << " [--help] - print this help message\n"
176 << " [--version] - print version and exit\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600177 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700178 << " [--config /path/to/nfd.conf] - path to configuration file "
179 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
180 ;
181 }
182
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600183 static void
184 printModules(std::ostream& os)
185 {
186 using namespace std;
187
188 os << "Available logging modules: \n";
189
190 list<string> modules(LoggerFactory::getInstance().getModules());
191 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
192 {
193 os << *i << "\n";
194 }
195 }
196
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700197 static bool
198 parseCommandLine(int argc, char** argv, ProgramOptions& options)
199 {
200 options.showUsage = false;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700201 options.showVersion = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600202 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700203 options.config = DEFAULT_CONFIG_FILE;
204
205 while (true) {
206 int optionIndex = 0;
207 static ::option longOptions[] = {
208 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600209 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700210 { "config" , required_argument, 0, 0 },
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700211 { "version", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700212 { 0 , 0 , 0, 0 }
213 };
214 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
215 if (c == -1)
216 break;
217
218 switch (c) {
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700219 case 0:
220 switch (optionIndex) {
221 case 0: // help
222 options.showUsage = true;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700223 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700224 case 1: // modules
225 options.showModules = true;
226 break;
227 case 2: // config
228 options.config = ::optarg;
229 break;
230 case 3: // version
231 options.showVersion = true;
232 break;
233 default:
234 return false;
235 }
236 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700237 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700238 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700239 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700240 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700241
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700242 void
243 terminate(const boost::system::error_code& error,
244 int signalNo,
245 boost::asio::signal_set& signalSet)
246 {
247 if (error)
248 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700249
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700250 if (signalNo == SIGINT ||
251 signalNo == SIGTERM)
252 {
253 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700254 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700255 }
256 else
257 {
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700258 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2, ref(signalSet)));
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700259 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700260 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600261
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300262 void
263 reload(const boost::system::error_code& error,
264 int signalNo,
265 boost::asio::signal_set& signalSet)
266 {
267 if (error)
268 return;
269
270 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo));
271
272 ////////////////////////
273 // Reload config file //
274 ////////////////////////
275
276 // Logging
277 initializeLogging();
278 /// \todo Reopen log file
279
280 // Other stuff
281 ConfigFile config((IgnoreRibAndLogSections()));
282
283 general::setConfigFile(config);
284
Steve DiBenedetto3a4f83d2014-06-02 14:58:54 -0600285 TablesConfigSection tablesConfig(m_forwarder->getCs(),
286 m_forwarder->getPit(),
287 m_forwarder->getFib(),
288 m_forwarder->getStrategyChoice(),
289 m_forwarder->getMeasurements());
290
291 tablesConfig.setConfigFile(config);
292
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300293 m_internalFace->getValidator().setConfigFile(config);
294 m_faceManager->setConfigFile(config);
295
296 config.parse(m_configFile, false);
297
298 ////////////////////////
299
300 signalSet.async_wait(bind(&Nfd::reload, this, _1, _2, ref(signalSet)));
301 }
302
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700303private:
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300304 std::string m_configFile;
305
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600306 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600307
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600308 shared_ptr<InternalFace> m_internalFace;
309 shared_ptr<FibManager> m_fibManager;
310 shared_ptr<FaceManager> m_faceManager;
311 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
312 shared_ptr<StatusServer> m_statusServer;
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300313
314 shared_ptr<std::ofstream> m_logFile;
315 std::basic_streambuf<char>* m_originalStreamBuf;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700316};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700317
318} // namespace nfd
319
320int
321main(int argc, char** argv)
322{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700323 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700324
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700325 ProgramOptions options;
326 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
327 if (!isCommandLineValid) {
328 Nfd::printUsage(std::cerr, argv[0]);
329 return 1;
330 }
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700331
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700332 if (options.showUsage) {
333 Nfd::printUsage(std::cout, argv[0]);
334 return 0;
335 }
336
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700337 if (options.showVersion) {
338 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
339 return 0;
340 }
341
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600342 if (options.showModules) {
343 Nfd::printModules(std::cout);
344 return 0;
345 }
346
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300347 Nfd nfdInstance(options.config);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600348
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700349 try {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300350 nfdInstance.initialize();
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700351 }
352 catch (boost::filesystem::filesystem_error& e) {
353 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600354 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
355 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700356 }
357 else {
358 NFD_LOG_FATAL(e.what());
359 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600360 return 1;
361 }
362 catch (const std::exception& e) {
363 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700364 return 2;
365 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600366 catch (const PrivilegeHelper::Error& e) {
367 // PrivilegeHelper::Errors do not inherit from std::exception
368 // and represent seteuid/gid failures
369
370 NFD_LOG_FATAL(e.what());
371 return 3;
372 }
373
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300374 boost::asio::signal_set terminationSignalSet(getGlobalIoService());
375 terminationSignalSet.add(SIGINT);
376 terminationSignalSet.add(SIGTERM);
377 terminationSignalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
378 ref(terminationSignalSet)));
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600379
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300380 boost::asio::signal_set reloadSignalSet(getGlobalIoService());
381 reloadSignalSet.add(SIGHUP);
382 reloadSignalSet.async_wait(bind(&Nfd::reload, &nfdInstance, _1, _2,
383 ref(reloadSignalSet)));
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600384
385 try {
386 getGlobalIoService().run();
387 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600388 catch (const std::exception& e) {
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700389 NFD_LOG_FATAL(e.what());
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600390 return 4;
391 }
392 catch (const PrivilegeHelper::Error& e) {
393 NFD_LOG_FATAL(e.what());
394 return 5;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700395 }
396
397 return 0;
398}