blob: fdf14b5c95d3fd5a720e0fe68e9331945518d10a [file] [log] [blame]
Alexander Afanasyev2aa39622014-01-22 11:51:11 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * 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 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080024
Junxiao Shi09bf7c42014-01-31 11:10:25 -070025#include <getopt.h>
Junxiao Shi98e29f42014-03-31 10:27:26 -070026#include <boost/filesystem.hpp>
27
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070028#include "version.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070029#include "core/logger.hpp"
Junxiao Shi98e29f42014-03-31 10:27:26 -070030#include "core/global-io.hpp"
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060031#include "core/privilege-helper.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070032#include "fw/forwarder.hpp"
33#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070034#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070035#include "mgmt/face-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070036#include "mgmt/strategy-choice-manager.hpp"
Junxiao Shiea48d8b2014-03-16 13:53:47 -070037#include "mgmt/status-server.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070038#include "core/config-file.hpp"
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060039#include "mgmt/general-config-section.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080040
Junxiao Shi09bf7c42014-01-31 11:10:25 -070041namespace nfd {
42
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070043NFD_LOG_INIT("NFD");
Junxiao Shi09bf7c42014-01-31 11:10:25 -070044
45struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080046{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070047 bool showUsage;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070048 bool showVersion;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060049 bool showModules;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070050 std::string config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070051};
52
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070053class Nfd : noncopyable
Junxiao Shi09bf7c42014-01-31 11:10:25 -070054{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070055public:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060056
57 void
58 initialize(const std::string& configFile)
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070059 {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060060 initializeLogging(configFile);
61
62 m_forwarder = make_shared<Forwarder>();
63
64 initializeManagement(configFile);
Steve DiBenedetto24b9a642014-04-07 15:45:39 -060065
66 PrivilegeHelper::drop();
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060067 }
68
69
70 void
71 initializeLogging(const std::string& configFile)
72 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060073 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060074 LoggerFactory::getInstance().setConfigFile(config);
75
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060076 config.parse(configFile, true);
77 config.parse(configFile, false);
78 }
79
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060080 class IgnoreRibAndLogSections
81 {
82 public:
83 void
84 operator()(const std::string& filename,
85 const std::string& sectionName,
86 const ConfigSection& section,
87 bool isDryRun)
88
89 {
90 // Ignore "log" and sections beginning with "rib_" (intended for rib manager),
91 // but raise an error if we're missing a handler for an NFD section.
92
Yingdi Yue5224e92014-04-29 18:04:02 -070093 if (sectionName.find("rib") == 0 || sectionName == "log")
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060094 {
95 // do nothing
96 }
97 else
98 {
99 // missing NFD section
100 ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
101 }
102 }
103 };
104
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600105 void
106 initializeManagement(const std::string& configFile)
107 {
108 m_internalFace = make_shared<InternalFace>();
109
110 m_fibManager = make_shared<FibManager>(boost::ref(m_forwarder->getFib()),
111 bind(&Forwarder::getFace, m_forwarder.get(), _1),
112 m_internalFace);
113
114 m_faceManager = make_shared<FaceManager>(boost::ref(m_forwarder->getFaceTable()),
115 m_internalFace);
116
117 m_strategyChoiceManager =
118 make_shared<StrategyChoiceManager>(boost::ref(m_forwarder->getStrategyChoice()),
119 m_internalFace);
120
121 m_statusServer = make_shared<StatusServer>(m_internalFace,
122 boost::ref(*m_forwarder));
123
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600124 ConfigFile config((IgnoreRibAndLogSections()));
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600125
126 general::setConfigFile(config);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700127 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700128
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600129 m_forwarder->addFace(m_internalFace);
Junxiao Shic041ca32014-02-25 20:01:15 -0700130
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600131 m_faceManager->setConfigFile(config);
132
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700133 // parse config file
134 config.parse(configFile, true);
135 config.parse(configFile, false);
136
137 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600138 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700139 entry->addNextHop(m_internalFace, 0);
140 }
141
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700142 static void
143 printUsage(std::ostream& os, const std::string& programName)
144 {
145 os << "Usage: \n"
146 << " " << programName << " [options]\n"
147 << "\n"
148 << "Run NFD forwarding daemon\n"
149 << "\n"
150 << "Options:\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700151 << " [--help] - print this help message\n"
152 << " [--version] - print version and exit\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600153 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700154 << " [--config /path/to/nfd.conf] - path to configuration file "
155 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
156 ;
157 }
158
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600159 static void
160 printModules(std::ostream& os)
161 {
162 using namespace std;
163
164 os << "Available logging modules: \n";
165
166 list<string> modules(LoggerFactory::getInstance().getModules());
167 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
168 {
169 os << *i << "\n";
170 }
171 }
172
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700173 static bool
174 parseCommandLine(int argc, char** argv, ProgramOptions& options)
175 {
176 options.showUsage = false;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700177 options.showVersion = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600178 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700179 options.config = DEFAULT_CONFIG_FILE;
180
181 while (true) {
182 int optionIndex = 0;
183 static ::option longOptions[] = {
184 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600185 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700186 { "config" , required_argument, 0, 0 },
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700187 { "version", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700188 { 0 , 0 , 0, 0 }
189 };
190 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
191 if (c == -1)
192 break;
193
194 switch (c) {
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700195 case 0:
196 switch (optionIndex) {
197 case 0: // help
198 options.showUsage = true;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700199 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700200 case 1: // modules
201 options.showModules = true;
202 break;
203 case 2: // config
204 options.config = ::optarg;
205 break;
206 case 3: // version
207 options.showVersion = true;
208 break;
209 default:
210 return false;
211 }
212 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700213 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700214 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700215 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700216 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700217
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700218 void
219 terminate(const boost::system::error_code& error,
220 int signalNo,
221 boost::asio::signal_set& signalSet)
222 {
223 if (error)
224 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700225
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700226 if (signalNo == SIGINT ||
227 signalNo == SIGTERM)
228 {
229 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700230 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700231 }
232 else
233 {
234 /// \todo May be try to reload config file (at least security section)
235 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2,
236 boost::ref(signalSet)));
237 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700238 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600239
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700240private:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600241 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600242
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600243 shared_ptr<InternalFace> m_internalFace;
244 shared_ptr<FibManager> m_fibManager;
245 shared_ptr<FaceManager> m_faceManager;
246 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
247 shared_ptr<StatusServer> m_statusServer;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700248};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700249
250} // namespace nfd
251
252int
253main(int argc, char** argv)
254{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700255 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700256
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700257 ProgramOptions options;
258 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
259 if (!isCommandLineValid) {
260 Nfd::printUsage(std::cerr, argv[0]);
261 return 1;
262 }
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700263
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700264 if (options.showUsage) {
265 Nfd::printUsage(std::cout, argv[0]);
266 return 0;
267 }
268
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700269 if (options.showVersion) {
270 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
271 return 0;
272 }
273
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600274 if (options.showModules) {
275 Nfd::printModules(std::cout);
276 return 0;
277 }
278
279 Nfd nfdInstance;
280
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700281 try {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600282 nfdInstance.initialize(options.config);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700283 }
284 catch (boost::filesystem::filesystem_error& e) {
285 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600286 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
287 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700288 }
289 else {
290 NFD_LOG_FATAL(e.what());
291 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600292 return 1;
293 }
294 catch (const std::exception& e) {
295 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700296 return 2;
297 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600298 catch (const PrivilegeHelper::Error& e) {
299 // PrivilegeHelper::Errors do not inherit from std::exception
300 // and represent seteuid/gid failures
301
302 NFD_LOG_FATAL(e.what());
303 return 3;
304 }
305
306
307
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600308
309 boost::asio::signal_set signalSet(getGlobalIoService());
310 signalSet.add(SIGINT);
311 signalSet.add(SIGTERM);
312 signalSet.add(SIGHUP);
313 signalSet.add(SIGUSR1);
314 signalSet.add(SIGUSR2);
315 signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
316 boost::ref(signalSet)));
317
318 try {
319 getGlobalIoService().run();
320 }
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600321 catch (const std::exception& e) {
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700322 NFD_LOG_FATAL(e.what());
Steve DiBenedetto24b9a642014-04-07 15:45:39 -0600323 return 4;
324 }
325 catch (const PrivilegeHelper::Error& e) {
326 NFD_LOG_FATAL(e.what());
327 return 5;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700328 }
329
330 return 0;
331}