blob: c8bd76c798804c5155530baeb5e400a4ecdfabb4 [file] [log] [blame]
Vince Lehmanc439d662015-04-27 10:56:00 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Ashlesh Gawande0421bc62020-05-08 20:42:19 -07002/*
awlane879afac2025-04-28 17:59:36 -05003 * Copyright (c) 2014-2025, The University of Memphis,
Vince Lehmanc439d662015-04-27 10:56:00 -05004 * Regents of the University of California,
5 * Arizona Board of Regents.
6 *
7 * This file is part of NLSR (Named-data Link State Routing).
8 * See AUTHORS.md for complete list of NLSR authors and contributors.
9 *
10 * NLSR is free software: you can redistribute it and/or modify it under the terms
11 * of the GNU General Public License as published by the Free Software Foundation,
12 * either version 3 of the License, or (at your option) any later version.
13 *
14 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Ashlesh Gawande0421bc62020-05-08 20:42:19 -070020 */
Vince Lehmanc439d662015-04-27 10:56:00 -050021
22#include "nlsrc.hpp"
23
Junxiao Shia3a63972022-01-24 02:03:41 +000024#include "config.hpp"
Vince Lehmanc439d662015-04-27 10:56:00 -050025#include "version.hpp"
laqinfan35731852017-08-08 06:17:39 -050026#include "src/publisher/dataset-interest-handler.hpp"
Vince Lehmanc439d662015-04-27 10:56:00 -050027
Vince Lehmanc439d662015-04-27 10:56:00 -050028#include <ndn-cxx/data.hpp>
Vince Lehmanc439d662015-04-27 10:56:00 -050029#include <ndn-cxx/encoding/block.hpp>
Ashlesh Gawande30d96e42021-03-21 19:15:33 -070030#include <ndn-cxx/face.hpp>
31#include <ndn-cxx/interest.hpp>
Junxiao Shi3e5120c2016-09-10 16:58:34 +000032#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
33#include <ndn-cxx/mgmt/nfd/control-response.hpp>
Davide Pesavento6184c202021-05-17 02:28:03 -040034#include <ndn-cxx/security/interest-signer.hpp>
Ashlesh Gawande30d96e42021-03-21 19:15:33 -070035#include <ndn-cxx/security/key-chain.hpp>
36#include <ndn-cxx/security/signing-helpers.hpp>
Junxiao Shia3a63972022-01-24 02:03:41 +000037#include <ndn-cxx/security/validator-config.hpp>
38#include <ndn-cxx/security/validator-null.hpp>
Ashlesh Gawande30d96e42021-03-21 19:15:33 -070039#include <ndn-cxx/util/segment-fetcher.hpp>
Vince Lehmanc439d662015-04-27 10:56:00 -050040
Junxiao Shia3a63972022-01-24 02:03:41 +000041#include <boost/algorithm/string/replace.hpp>
42#include <boost/property_tree/info_parser.hpp>
43
Vince Lehmanc439d662015-04-27 10:56:00 -050044#include <iostream>
45
46namespace nlsrc {
47
Junxiao Shia3a63972022-01-24 02:03:41 +000048const ndn::Name LOCALHOST_PREFIX("/localhost");
49const ndn::PartialName LSDB_SUFFIX("nlsr/lsdb");
50const ndn::PartialName NAME_UPDATE_SUFFIX("nlsr/prefix-update");
51const ndn::PartialName RT_SUFFIX("nlsr/routing-table");
Vince Lehmanc439d662015-04-27 10:56:00 -050052
Junxiao Shia3a63972022-01-24 02:03:41 +000053const uint32_t ERROR_CODE_TIMEOUT = 10060;
54const uint32_t RESPONSE_CODE_SUCCESS = 200;
Junxiao Shif7ea1502023-06-23 04:30:19 +000055const uint32_t RESPONSE_CODE_NO_EFFECT = 204;
Junxiao Shia3a63972022-01-24 02:03:41 +000056const uint32_t RESPONSE_CODE_SAVE_OR_DELETE = 205;
laqinfan35731852017-08-08 06:17:39 -050057
Junxiao Shia3a63972022-01-24 02:03:41 +000058Nlsrc::Nlsrc(std::string programName, ndn::Face& face)
59 : m_programName(std::move(programName))
60 , m_routerPrefix(LOCALHOST_PREFIX)
61 , m_face(face)
Vince Lehmanc439d662015-04-27 10:56:00 -050062{
Junxiao Shia3a63972022-01-24 02:03:41 +000063 disableValidator();
Vince Lehmanc439d662015-04-27 10:56:00 -050064}
65
66void
Junxiao Shia3a63972022-01-24 02:03:41 +000067Nlsrc::printUsage() const
Vince Lehmanc439d662015-04-27 10:56:00 -050068{
Junxiao Shif7ea1502023-06-23 04:30:19 +000069 const std::string help(R"EOT(Usage:
Junxiao Shia3a63972022-01-24 02:03:41 +000070@NLSRC@ [-h | -V]
71@NLSRC@ [-R <router prefix> [-c <nlsr.conf path> | -k]] COMMAND [<Command Options>]
72 -h print usage and exit
73 -V print version and exit
74 -R target a remote NLSR instance
75 -c verify response with nlsr.conf security.validator policy
76 -k do not verify response (insecure)
77
78 COMMAND can be one of the following:
79 lsdb
80 display NLSR lsdb status
81 routing
82 display routing table status
83 status
84 display all NLSR status (lsdb & routingtable)
awlane879afac2025-04-28 17:59:36 -050085 advertise <name> [cost <cost>]
86 advertise a name prefix with optionally set cost through NLSR
87 advertise <name> [cost <cost>] save
88 advertise and save the name prefix and cost to the stateful conf file
Junxiao Shia3a63972022-01-24 02:03:41 +000089 withdraw <name>
90 remove a name prefix advertised through NLSR
91 withdraw <name> delete
awlane879afac2025-04-28 17:59:36 -050092 withdraw and delete the name prefix from the stateful conf file
Junxiao Shia3a63972022-01-24 02:03:41 +000093)EOT");
Junxiao Shif7ea1502023-06-23 04:30:19 +000094 boost::algorithm::replace_all_copy(std::ostream_iterator<char>(std::cout),
95 help, "@NLSRC@", m_programName);
Junxiao Shia3a63972022-01-24 02:03:41 +000096}
97
98void
99Nlsrc::setRouterPrefix(ndn::Name prefix)
100{
101 m_routerPrefix = std::move(prefix);
102}
103
104void
105Nlsrc::disableValidator()
106{
107 m_validator.reset(new ndn::security::ValidatorNull());
108}
109
110bool
111Nlsrc::enableValidator(const std::string& filename)
112{
113 using namespace boost::property_tree;
114 ptree validatorConfig;
115 try {
116 ptree config;
117 read_info(filename, config);
118 validatorConfig = config.get_child("security.validator");
119 }
120 catch (const ptree_error& e) {
121 std::cerr << "Failed to parse configuration file '" << filename
122 << "': " << e.what() << std::endl;
123 return false;
124 }
125
126 auto validator = std::make_unique<ndn::security::ValidatorConfig>(m_face);
127 try {
128 validator->load(validatorConfig, filename);
129 }
130 catch (const ndn::security::validator_config::Error& e) {
131 std::cerr << "Failed to load validator config from '" << filename
132 << "' security.validator section: " << e.what() << std::endl;
133 return false;
134 }
135
136 m_validator = std::move(validator);
137 return true;
Vince Lehmanc439d662015-04-27 10:56:00 -0500138}
139
140void
laqinfan35731852017-08-08 06:17:39 -0500141Nlsrc::getStatus(const std::string& command)
Vince Lehmanc439d662015-04-27 10:56:00 -0500142{
laqinfan35731852017-08-08 06:17:39 -0500143 if (command == "lsdb") {
144 m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
145 m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
146 m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
147 m_fetchSteps.push_back(std::bind(&Nlsrc::printLsdb, this));
148 }
149 else if (command == "routing") {
150 m_fetchSteps.push_back(std::bind(&Nlsrc::fetchRtables, this));
151 m_fetchSteps.push_back(std::bind(&Nlsrc::printRT, this));
152 }
Junxiao Shia3a63972022-01-24 02:03:41 +0000153 else if (command == "status") {
laqinfan35731852017-08-08 06:17:39 -0500154 m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
155 m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
156 m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
157 m_fetchSteps.push_back(std::bind(&Nlsrc::fetchRtables, this));
158 m_fetchSteps.push_back(std::bind(&Nlsrc::printAll, this));
159 }
Vince Lehmanc439d662015-04-27 10:56:00 -0500160 runNextStep();
161}
162
163bool
Junxiao Shia3a63972022-01-24 02:03:41 +0000164Nlsrc::dispatch(ndn::span<std::string> subcommand)
Vince Lehmanc439d662015-04-27 10:56:00 -0500165{
Junxiao Shia3a63972022-01-24 02:03:41 +0000166 if (subcommand.size() == 0) {
167 return false;
Vince Lehmanc439d662015-04-27 10:56:00 -0500168 }
awlane879afac2025-04-28 17:59:36 -0500169 bool saveValue = false;
Junxiao Shia3a63972022-01-24 02:03:41 +0000170 if (subcommand[0] == "advertise") {
171 switch (subcommand.size()) {
172 case 2:
awlane879afac2025-04-28 17:59:36 -0500173 advertiseName(subcommand[1], false, 0);
Junxiao Shia3a63972022-01-24 02:03:41 +0000174 return true;
175 case 3:
176 if (subcommand[2] != "save") {
177 return false;
178 }
awlane879afac2025-04-28 17:59:36 -0500179 saveValue = true;
180 advertiseName(subcommand[1], saveValue, 0);
181 return true;
182 case 5:
183 if (subcommand[4] != "save") {
184 return false;
185 }
186 saveValue = true;
187 [[fallthrough]];
188 case 4:
189 if (subcommand[2] != "cost") {
190 return false;
191 }
192 uint64_t costValue = 0;
193 try {
194 costValue = std::stoi(subcommand[3]);
195 }
196 catch (const std::exception& e) {
197 std::cerr << "ERROR: Invalid cost given to advertise command" << std::endl;
198 m_exitCode = 1;
199 return false;
200 }
201 advertiseName(subcommand[1], saveValue, costValue);
Junxiao Shia3a63972022-01-24 02:03:41 +0000202 return true;
203 }
204 return false;
205 }
206
207 if (subcommand[0] == "withdraw") {
208 switch (subcommand.size()) {
209 case 2:
210 withdrawName(subcommand[1], false);
211 return true;
212 case 3:
213 if (subcommand[2] != "delete") {
214 return false;
215 }
216 withdrawName(subcommand[1], true);
217 return true;
218 }
219 return false;
220 }
221
222 if (subcommand[0] == "lsdb" || subcommand[0] == "routing" || subcommand[0] == "status") {
223 if (subcommand.size() != 1) {
224 return false;
225 }
226 getStatus(subcommand[0]);
227 return true;
228 }
Vince Lehmanc439d662015-04-27 10:56:00 -0500229 return false;
230}
231
232void
233Nlsrc::runNextStep()
234{
235 if (m_fetchSteps.empty()) {
236 return;
237 }
238
239 std::function<void()> nextStep = m_fetchSteps.front();
240 m_fetchSteps.pop_front();
241
242 nextStep();
243}
244
245void
awlane879afac2025-04-28 17:59:36 -0500246Nlsrc::advertiseName(ndn::Name name, bool wantSave, uint64_t cost)
Vince Lehmanc439d662015-04-27 10:56:00 -0500247{
Junxiao Shia3a63972022-01-24 02:03:41 +0000248 std::string info = (wantSave ? "(Save: " : "(Advertise: ") + name.toUri() + ")";
Saurab Dulal7526cee2018-01-31 18:14:10 +0000249 ndn::Name::Component verb("advertise");
awlane879afac2025-04-28 17:59:36 -0500250 sendNamePrefixUpdate(name, verb, info, wantSave, cost);
Vince Lehmanc439d662015-04-27 10:56:00 -0500251}
252
253void
Junxiao Shia3a63972022-01-24 02:03:41 +0000254Nlsrc::withdrawName(ndn::Name name, bool wantDelete)
Vince Lehmanc439d662015-04-27 10:56:00 -0500255{
Junxiao Shia3a63972022-01-24 02:03:41 +0000256 std::string info = (wantDelete ? "(Delete: " : "(Withdraw: ") + name.toUri() + ")";
Saurab Dulal7526cee2018-01-31 18:14:10 +0000257 ndn::Name::Component verb("withdraw");
Junxiao Shia3a63972022-01-24 02:03:41 +0000258 sendNamePrefixUpdate(name, verb, info, wantDelete);
Vince Lehmanc439d662015-04-27 10:56:00 -0500259}
260
261void
262Nlsrc::sendNamePrefixUpdate(const ndn::Name& name,
263 const ndn::Name::Component& verb,
Saurab Dulal7526cee2018-01-31 18:14:10 +0000264 const std::string& info,
awlane879afac2025-04-28 17:59:36 -0500265 bool flag,
266 uint64_t cost)
Vince Lehmanc439d662015-04-27 10:56:00 -0500267{
268 ndn::nfd::ControlParameters parameters;
269 parameters.setName(name);
Saurab Dulal7526cee2018-01-31 18:14:10 +0000270 if (flag) {
271 parameters.setFlags(1);
272 }
Vince Lehmanc439d662015-04-27 10:56:00 -0500273
awlane879afac2025-04-28 17:59:36 -0500274 if (verb.toUri() == "advertise" and cost > 0) {
275 parameters.setCost(cost);
276 }
277
Junxiao Shia3a63972022-01-24 02:03:41 +0000278 auto paramWire = parameters.wireEncode();
279 ndn::Name commandName = m_routerPrefix;
280 commandName.append(NAME_UPDATE_SUFFIX);
Vince Lehmanc439d662015-04-27 10:56:00 -0500281 commandName.append(verb);
Junxiao Shia3a63972022-01-24 02:03:41 +0000282 commandName.append(paramWire.begin(), paramWire.end());
Vince Lehmanc439d662015-04-27 10:56:00 -0500283
Davide Pesavento6184c202021-05-17 02:28:03 -0400284 ndn::security::InterestSigner signer(m_keyChain);
285 auto commandInterest = signer.makeCommandInterest(commandName,
286 ndn::security::signingByIdentity(m_keyChain.getPib().getDefaultIdentity()));
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500287 commandInterest.setMustBeFresh(true);
288
289 m_face.expressInterest(commandInterest,
Vince Lehmanc439d662015-04-27 10:56:00 -0500290 std::bind(&Nlsrc::onControlResponse, this, info, _2),
Alexander Afanasyev1de901f2017-03-09 12:43:57 -0800291 std::bind(&Nlsrc::onTimeout, this, ERROR_CODE_TIMEOUT, "Nack"),
Vince Lehmanc439d662015-04-27 10:56:00 -0500292 std::bind(&Nlsrc::onTimeout, this, ERROR_CODE_TIMEOUT, "Timeout"));
293}
294
295void
296Nlsrc::onControlResponse(const std::string& info, const ndn::Data& data)
297{
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500298 if (data.getMetaInfo().getType() == ndn::tlv::ContentType_Nack) {
299 std::cerr << "ERROR: Run-time advertise/withdraw disabled" << std::endl;
300 return;
301 }
302
Vince Lehmanc439d662015-04-27 10:56:00 -0500303 ndn::nfd::ControlResponse response;
304
305 try {
306 response.wireDecode(data.getContent().blockFromValue());
307 }
308 catch (const std::exception& e) {
309 std::cerr << "ERROR: Control response decoding error" << std::endl;
Junxiao Shif7ea1502023-06-23 04:30:19 +0000310 m_exitCode = 1;
Vince Lehmanc439d662015-04-27 10:56:00 -0500311 return;
312 }
313
314 uint32_t code = response.getCode();
315
Saurab Dulal7526cee2018-01-31 18:14:10 +0000316 if (code != RESPONSE_CODE_SUCCESS && code != RESPONSE_CODE_SAVE_OR_DELETE) {
Saurab Dulal7526cee2018-01-31 18:14:10 +0000317 std::cerr << response.getText() << std::endl;
Vince Lehmanc439d662015-04-27 10:56:00 -0500318 std::cerr << "Name prefix update error (code: " << code << ")" << std::endl;
Junxiao Shif7ea1502023-06-23 04:30:19 +0000319 m_exitCode = code == RESPONSE_CODE_NO_EFFECT ? 0 : 1;
Vince Lehmanc439d662015-04-27 10:56:00 -0500320 return;
321 }
322
323 std::cout << "Applied Name prefix update successfully: " << info << std::endl;
Junxiao Shif7ea1502023-06-23 04:30:19 +0000324 m_exitCode = 0;
Vince Lehmanc439d662015-04-27 10:56:00 -0500325}
326
327void
328Nlsrc::fetchAdjacencyLsas()
329{
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800330 fetchFromLsdb<nlsr::AdjLsa>(nlsr::dataset::ADJACENCY_COMPONENT,
331 std::bind(&Nlsrc::recordLsa, this, _1));
Vince Lehmanc439d662015-04-27 10:56:00 -0500332}
333
334void
335Nlsrc::fetchCoordinateLsas()
336{
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800337 fetchFromLsdb<nlsr::CoordinateLsa>(nlsr::dataset::COORDINATE_COMPONENT,
338 std::bind(&Nlsrc::recordLsa, this, _1));
Vince Lehmanc439d662015-04-27 10:56:00 -0500339}
340
341void
342Nlsrc::fetchNameLsas()
343{
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800344 fetchFromLsdb<nlsr::NameLsa>(nlsr::dataset::NAME_COMPONENT,
345 std::bind(&Nlsrc::recordLsa, this, _1));
Vince Lehmanc439d662015-04-27 10:56:00 -0500346}
347
laqinfan35731852017-08-08 06:17:39 -0500348void
349Nlsrc::fetchRtables()
350{
Ashlesh Gawande0af46272020-12-12 16:45:13 -0500351 fetchFromRt<nlsr::RoutingTableStatus>([this] (const auto& rts) { this->recordRtable(rts); });
laqinfan35731852017-08-08 06:17:39 -0500352}
353
Junxiao Shia3a63972022-01-24 02:03:41 +0000354template<class T>
Vince Lehmanc439d662015-04-27 10:56:00 -0500355void
356Nlsrc::fetchFromLsdb(const ndn::Name::Component& datasetType,
357 const std::function<void(const T&)>& recordLsa)
358{
Junxiao Shia3a63972022-01-24 02:03:41 +0000359 auto name = m_routerPrefix;
360 name.append(LSDB_SUFFIX);
361 name.append(datasetType);
362 ndn::Interest interest(name);
Vince Lehmanc439d662015-04-27 10:56:00 -0500363
Junxiao Shi43f37a02023-08-09 00:09:00 +0000364 auto fetcher = ndn::SegmentFetcher::start(m_face, interest, *m_validator);
Ashlesh Gawande05cb7282018-08-30 14:39:41 -0500365 fetcher->onComplete.connect(std::bind(&Nlsrc::onFetchSuccess<T>, this, _1, recordLsa));
366 fetcher->onError.connect(std::bind(&Nlsrc::onTimeout, this, _1, _2));
Vince Lehmanc439d662015-04-27 10:56:00 -0500367}
368
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700369void
370Nlsrc::recordLsa(const nlsr::Lsa& lsa)
371{
372 Router& router = m_routers.emplace(lsa.getOriginRouter(), Router()).first->second;
Junxiao Shi153fbc12024-01-09 23:37:23 +0000373 auto lsaString = boost::lexical_cast<std::string>(lsa);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700374
375 if (lsa.getType() == nlsr::Lsa::Type::ADJACENCY) {
Junxiao Shi153fbc12024-01-09 23:37:23 +0000376 router.adjacencyLsaString = lsaString;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700377 }
378 else if (lsa.getType() == nlsr::Lsa::Type::COORDINATE) {
Junxiao Shi153fbc12024-01-09 23:37:23 +0000379 router.coordinateLsaString = lsaString;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700380 }
381 else if (lsa.getType() == nlsr::Lsa::Type::NAME) {
Junxiao Shi153fbc12024-01-09 23:37:23 +0000382 router.nameLsaString = lsaString;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700383 }
384}
385
Junxiao Shia3a63972022-01-24 02:03:41 +0000386template<class T>
Vince Lehmanc439d662015-04-27 10:56:00 -0500387void
laqinfan35731852017-08-08 06:17:39 -0500388Nlsrc::fetchFromRt(const std::function<void(const T&)>& recordDataset)
389{
Junxiao Shia3a63972022-01-24 02:03:41 +0000390 auto name = m_routerPrefix;
391 name.append(RT_SUFFIX);
392 ndn::Interest interest(name);
laqinfan35731852017-08-08 06:17:39 -0500393
Junxiao Shi43f37a02023-08-09 00:09:00 +0000394 auto fetcher = ndn::SegmentFetcher::start(m_face, interest, *m_validator);
Ashlesh Gawande05cb7282018-08-30 14:39:41 -0500395 fetcher->onComplete.connect(std::bind(&Nlsrc::onFetchSuccess<T>, this, _1, recordDataset));
396 fetcher->onError.connect(std::bind(&Nlsrc::onTimeout, this, _1, _2));
laqinfan35731852017-08-08 06:17:39 -0500397}
398
Junxiao Shia3a63972022-01-24 02:03:41 +0000399template<class T>
laqinfan35731852017-08-08 06:17:39 -0500400void
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400401Nlsrc::onFetchSuccess(const ndn::ConstBufferPtr& buf,
laqinfan35731852017-08-08 06:17:39 -0500402 const std::function<void(const T&)>& recordDataset)
Vince Lehmanc439d662015-04-27 10:56:00 -0500403{
Vince Lehmanc439d662015-04-27 10:56:00 -0500404 size_t offset = 0;
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400405 while (offset < buf->size()) {
406 auto [isOk, block] = ndn::Block::fromBuffer(buf, offset);
Vince Lehmanc439d662015-04-27 10:56:00 -0500407
408 if (!isOk) {
409 std::cerr << "ERROR: cannot decode LSA TLV" << std::endl;
410 break;
411 }
412
413 offset += block.size();
414
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400415 T dataset(block);
416 recordDataset(dataset);
Vince Lehmanc439d662015-04-27 10:56:00 -0500417 }
418
419 runNextStep();
420}
421
422void
423Nlsrc::onTimeout(uint32_t errorCode, const std::string& error)
424{
425 std::cerr << "Request timed out (code: " << errorCode
426 << ", error: " << error << ")" << std::endl;
Junxiao Shif7ea1502023-06-23 04:30:19 +0000427 m_exitCode = 1;
Vince Lehmanc439d662015-04-27 10:56:00 -0500428}
429
Vince Lehmanc439d662015-04-27 10:56:00 -0500430void
Ashlesh Gawande0421bc62020-05-08 20:42:19 -0700431Nlsrc::recordRtable(const nlsr::RoutingTableStatus& rts)
laqinfan35731852017-08-08 06:17:39 -0500432{
laqinfan35731852017-08-08 06:17:39 -0500433 std::ostringstream os;
Ashlesh Gawande0421bc62020-05-08 20:42:19 -0700434 os << rts;
laqinfana073e2e2018-01-15 21:17:24 +0000435 m_rtString = os.str();
laqinfan35731852017-08-08 06:17:39 -0500436}
437
438void
Vince Lehmanc439d662015-04-27 10:56:00 -0500439Nlsrc::printLsdb()
440{
Vince Lehmanc439d662015-04-27 10:56:00 -0500441 std::cout << "LSDB:" << std::endl;
442
443 for (const auto& item : m_routers) {
444 std::cout << " OriginRouter: " << item.first << std::endl;
445 std::cout << std::endl;
446
447 const Router& router = item.second;
448
449 if (!router.adjacencyLsaString.empty()) {
450 std::cout << router.adjacencyLsaString << std::endl;
451 }
452
453 if (!router.coordinateLsaString.empty()) {
454 std::cout << router.coordinateLsaString << std::endl;
455 }
456
457 if (!router.nameLsaString.empty()) {
458 std::cout << router.nameLsaString << std::endl;
459 }
460 }
461}
462
laqinfan35731852017-08-08 06:17:39 -0500463void
464Nlsrc::printRT()
465{
laqinfana073e2e2018-01-15 21:17:24 +0000466 if (!m_rtString.empty()) {
Ashlesh Gawande0421bc62020-05-08 20:42:19 -0700467 std::cout << m_rtString;
laqinfana073e2e2018-01-15 21:17:24 +0000468 }
469 else {
470 std::cout << "Routing Table is not calculated yet" << std::endl;
laqinfan35731852017-08-08 06:17:39 -0500471 }
472}
473
474void
475Nlsrc::printAll()
476{
477 std::cout << "NLSR Status" << std::endl;
478 printLsdb();
479 printRT();
480}
481
Vince Lehmanc439d662015-04-27 10:56:00 -0500482} // namespace nlsrc
483
484////////////////////////////////////////////////////////////////////////////////
485////////////////////////////////////////////////////////////////////////////////
486
487int
488main(int argc, char** argv)
489{
490 ndn::Face face;
Junxiao Shia3a63972022-01-24 02:03:41 +0000491 nlsrc::Nlsrc nlsrc(argv[0], face);
Vince Lehmanc439d662015-04-27 10:56:00 -0500492
493 if (argc < 2) {
494 nlsrc.printUsage();
Junxiao Shif7ea1502023-06-23 04:30:19 +0000495 return 2;
Vince Lehmanc439d662015-04-27 10:56:00 -0500496 }
497
498 int opt;
Junxiao Shia3a63972022-01-24 02:03:41 +0000499 const char* confFile = DEFAULT_CONFIG_FILE;
500 bool disableValidator = false;
501 while ((opt = ::getopt(argc, argv, "hVR:c:k")) != -1) {
Vince Lehmanc439d662015-04-27 10:56:00 -0500502 switch (opt) {
503 case 'h':
504 nlsrc.printUsage();
505 return 0;
506 case 'V':
507 std::cout << NLSR_VERSION_BUILD_STRING << std::endl;
508 return 0;
Junxiao Shia3a63972022-01-24 02:03:41 +0000509 case 'R':
510 nlsrc.setRouterPrefix(::optarg);
511 break;
512 case 'c':
513 confFile = ::optarg;
514 break;
515 case 'k':
516 disableValidator = true;
517 break;
Vince Lehmanc439d662015-04-27 10:56:00 -0500518 default:
519 nlsrc.printUsage();
Junxiao Shif7ea1502023-06-23 04:30:19 +0000520 return 2;
Vince Lehmanc439d662015-04-27 10:56:00 -0500521 }
522 }
523
524 if (argc == ::optind) {
525 nlsrc.printUsage();
Junxiao Shif7ea1502023-06-23 04:30:19 +0000526 return 2;
Vince Lehmanc439d662015-04-27 10:56:00 -0500527 }
528
Junxiao Shia3a63972022-01-24 02:03:41 +0000529 if (nlsrc.getRouterPrefix() != nlsrc::LOCALHOST_PREFIX && !disableValidator) {
530 if (!nlsrc.enableValidator(confFile)) {
531 return 1;
532 }
533 }
534
Junxiao Shif7ea1502023-06-23 04:30:19 +0000535 std::vector<std::string> subcommand(&argv[::optind], &argv[argc]);
Vince Lehmanc439d662015-04-27 10:56:00 -0500536 try {
Junxiao Shif7ea1502023-06-23 04:30:19 +0000537 bool isValidSyntax = nlsrc.dispatch(subcommand);
538 if (!isValidSyntax) {
Vince Lehmanc439d662015-04-27 10:56:00 -0500539 nlsrc.printUsage();
Junxiao Shif7ea1502023-06-23 04:30:19 +0000540 return 2;
Vince Lehmanc439d662015-04-27 10:56:00 -0500541 }
542
543 face.processEvents();
544 }
545 catch (const std::exception& e) {
546 std::cerr << "ERROR: " << e.what() << std::endl;
Junxiao Shif7ea1502023-06-23 04:30:19 +0000547 return 1;
Vince Lehmanc439d662015-04-27 10:56:00 -0500548 }
Junxiao Shif7ea1502023-06-23 04:30:19 +0000549 return nlsrc.getExitCode();
Alexander Afanasyevf9f39102015-12-01 17:43:40 -0800550}