blob: 40751b384383ef6715f77e045d0d1a1af6a7bf8c [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento4b9d30f2020-05-01 02:48:34 -04002/*
awlane879afac2025-04-28 17:59:36 -05003 * Copyright (c) 2014-2025, The University of Memphis,
Vince Lehmanc2e51f62015-01-20 15:03:11 -06004 * Regents of the University of California,
5 * Arizona Board of Regents.
akmhoque3d06e792014-05-27 16:23:20 -05006 *
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/>.
Alexander Afanasyev0ad01f32020-06-03 14:12:58 -040020 */
Vince Lehmanc2e51f62015-01-20 15:03:11 -060021
Ashlesh Gawande3909aa12017-07-28 16:01:35 -050022#include "conf-file-processor.hpp"
23#include "adjacent.hpp"
Ashlesh Gawande3909aa12017-07-28 16:01:35 -050024#include "update/prefix-update-processor.hpp"
Davide Pesavento7bc3d432021-10-25 21:08:04 -040025#include "utility/name-helper.hpp"
Ashlesh Gawande3909aa12017-07-28 16:01:35 -050026
Alexander Afanasyevb669f9c2014-11-14 12:41:54 -080027#include <ndn-cxx/name.hpp>
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050028#include <ndn-cxx/net/face-uri.hpp>
Davide Pesavento7bc3d432021-10-25 21:08:04 -040029#include <ndn-cxx/util/io.hpp>
Alexander Afanasyevb669f9c2014-11-14 12:41:54 -080030
Davide Pesavento5849ee72023-11-12 20:00:21 -050031#include <boost/algorithm/string.hpp>
Davide Pesavento22520e62021-06-08 22:16:52 -040032#include <boost/property_tree/info_parser.hpp>
awlane879afac2025-04-28 17:59:36 -050033#include <boost/property_tree/exceptions.hpp>
Davide Pesavento22520e62021-06-08 22:16:52 -040034
Davide Pesaventob0716542024-12-16 19:12:11 -050035#include <filesystem>
Nick Gordone98480b2017-05-24 11:23:03 -050036#include <fstream>
Davide Pesavento22520e62021-06-08 22:16:52 -040037#include <iostream>
38
akmhoque53353462014-04-22 08:43:45 -050039namespace nlsr {
40
Davide Pesaventob0716542024-12-16 19:12:11 -050041namespace fs = std::filesystem;
42
Vince Lehman7b616582014-10-17 16:25:39 -050043template <class T>
44class ConfigurationVariable
45{
46public:
dmcoomes9f936662017-03-02 10:33:09 -060047 typedef std::function<void(T)> ConfParameterCallback;
Vince Lehman7b616582014-10-17 16:25:39 -050048
49 ConfigurationVariable(const std::string& key, const ConfParameterCallback& setter)
50 : m_key(key)
51 , m_setterCallback(setter)
52 , m_minValue(0)
53 , m_maxValue(0)
54 , m_shouldCheckRange(false)
55 , m_isRequired(true)
56 {
57 }
58
59 bool
60 parseFromConfigSection(const ConfigSection& section)
61 {
62 try {
63 T value = section.get<T>(m_key);
64
65 if (!isValidValue(value)) {
66 return false;
67 }
68
69 m_setterCallback(value);
70 return true;
71 }
72 catch (const std::exception& ex) {
73
74 if (m_isRequired) {
75 std::cerr << ex.what() << std::endl;
76 std::cerr << "Missing required configuration variable" << std::endl;
77 return false;
78 }
79 else {
80 m_setterCallback(m_defaultValue);
81 return true;
82 }
83 }
84
85 return false;
86 }
87
88 void
89 setMinAndMaxValue(T min, T max)
90 {
91 m_minValue = min;
92 m_maxValue = max;
93 m_shouldCheckRange = true;
94 }
95
96 void
97 setOptional(T defaultValue)
98 {
99 m_isRequired = false;
100 m_defaultValue = defaultValue;
101 }
102
103private:
104 void
105 printOutOfRangeError(T value)
106 {
107 std::cerr << "Invalid value for " << m_key << ": "
108 << value << ". "
109 << "Valid values: "
110 << m_minValue << " - "
111 << m_maxValue << std::endl;
112 }
113
114 bool
115 isValidValue(T value)
116 {
117 if (!m_shouldCheckRange) {
118 return true;
119 }
120 else if (value < m_minValue || value > m_maxValue)
121 {
122 printOutOfRangeError(value);
123 return false;
124 }
125
126 return true;
127 }
128
129private:
130 const std::string m_key;
131 const ConfParameterCallback m_setterCallback;
Vince Lehman7b616582014-10-17 16:25:39 -0500132
Davide Pesavento5849ee72023-11-12 20:00:21 -0500133 T m_defaultValue;
Vince Lehman7b616582014-10-17 16:25:39 -0500134 T m_minValue;
135 T m_maxValue;
136
137 bool m_shouldCheckRange;
138 bool m_isRequired;
139};
140
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600141ConfFileProcessor::ConfFileProcessor(ConfParameter& confParam)
142 : m_confFileName(confParam.getConfFileName())
143 , m_confParam(confParam)
144{
145}
146
akmhoque157b0a42014-05-13 00:26:37 -0500147bool
akmhoqueb6450b12014-04-24 00:01:03 -0500148ConfFileProcessor::processConfFile()
akmhoque53353462014-04-22 08:43:45 -0500149{
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400150 std::ifstream inputFile(m_confFileName);
akmhoque157b0a42014-05-13 00:26:37 -0500151 if (!inputFile.is_open()) {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400152 std::cerr << "Failed to read configuration file: " << m_confFileName << std::endl;
akmhoquead5fe952014-06-26 13:34:12 -0500153 return false;
akmhoque157b0a42014-05-13 00:26:37 -0500154 }
Saurab Dulal427e0122019-11-28 11:58:02 -0600155
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400156 if (!load(inputFile)) {
157 return false;
Saurab Dulal427e0122019-11-28 11:58:02 -0600158 }
159
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400160 m_confParam.buildRouterAndSyncUserPrefix();
161 m_confParam.writeLog();
162 return true;
akmhoque157b0a42014-05-13 00:26:37 -0500163}
164
165bool
Nick Gordone98480b2017-05-24 11:23:03 -0500166ConfFileProcessor::load(std::istream& input)
akmhoque157b0a42014-05-13 00:26:37 -0500167{
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700168 ConfigSection pt;
akmhoque157b0a42014-05-13 00:26:37 -0500169 try {
170 boost::property_tree::read_info(input, pt);
171 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400172 catch (const boost::property_tree::ptree_error& e) {
173 std::cerr << "Failed to parse configuration file '" << m_confFileName
174 << "': " << e.what() << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500175 return false;
176 }
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700177
Ashlesh Gawande328fc112019-12-12 17:06:44 -0600178 for (const auto& tn : pt) {
179 if (!processSection(tn.first, tn.second)) {
180 return false;
akmhoque157b0a42014-05-13 00:26:37 -0500181 }
182 }
Ashlesh Gawande328fc112019-12-12 17:06:44 -0600183 return true;
akmhoque157b0a42014-05-13 00:26:37 -0500184}
185
186bool
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700187ConfFileProcessor::processSection(const std::string& sectionName, const ConfigSection& section)
akmhoque157b0a42014-05-13 00:26:37 -0500188{
189 bool ret = true;
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400190 if (sectionName == "general") {
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700191 ret = processConfSectionGeneral(section);
akmhoque157b0a42014-05-13 00:26:37 -0500192 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400193 else if (sectionName == "neighbors") {
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700194 ret = processConfSectionNeighbors(section);
akmhoque157b0a42014-05-13 00:26:37 -0500195 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400196 else if (sectionName == "hyperbolic") {
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700197 ret = processConfSectionHyperbolic(section);
akmhoque157b0a42014-05-13 00:26:37 -0500198 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400199 else if (sectionName == "fib") {
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700200 ret = processConfSectionFib(section);
akmhoque157b0a42014-05-13 00:26:37 -0500201 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400202 else if (sectionName == "advertising") {
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700203 ret = processConfSectionAdvertising(section);
akmhoque157b0a42014-05-13 00:26:37 -0500204 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400205 else if (sectionName == "security") {
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700206 ret = processConfSectionSecurity(section);
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700207 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400208 else {
209 std::cerr << "Unknown configuration section: " << sectionName << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500210 }
211 return ret;
212}
213
214bool
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700215ConfFileProcessor::processConfSectionGeneral(const ConfigSection& section)
akmhoque157b0a42014-05-13 00:26:37 -0500216{
Varun Patila2599da2023-07-12 16:37:15 -0700217 // sync-protocol
218 std::string syncProtocol = section.get<std::string>("sync-protocol", "psync");
219 if (syncProtocol == "chronosync") {
220#ifdef HAVE_CHRONOSYNC
221 m_confParam.setSyncProtocol(SyncProtocol::CHRONOSYNC);
222#else
223 std::cerr << "NLSR was compiled without ChronoSync support!\n";
224 return false;
225#endif
226 }
227 else if (syncProtocol == "psync") {
228#ifdef HAVE_PSYNC
229 m_confParam.setSyncProtocol(SyncProtocol::PSYNC);
230#else
231 std::cerr << "NLSR was compiled without PSync support!\n";
232 return false;
233#endif
234 }
235 else if (syncProtocol == "svs") {
236#ifdef HAVE_SVS
237 m_confParam.setSyncProtocol(SyncProtocol::SVS);
238#else
239 std::cerr << "NLSR was compiled without SVS support!\n";
240 return false;
241#endif
242 }
243 else {
244 std::cerr << "Sync protocol '" << syncProtocol << "' is not supported!\n"
245 << "Use 'chronosync' or 'psync' or 'svs'\n";
246 return false;
247 }
248
akmhoque157b0a42014-05-13 00:26:37 -0500249 try {
Nick Gordone98480b2017-05-24 11:23:03 -0500250 std::string network = section.get<std::string>("network");
251 std::string site = section.get<std::string>("site");
252 std::string router = section.get<std::string>("router");
akmhoque157b0a42014-05-13 00:26:37 -0500253 ndn::Name networkName(network);
254 if (!networkName.empty()) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600255 m_confParam.setNetwork(networkName);
akmhoque157b0a42014-05-13 00:26:37 -0500256 }
257 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400258 std::cerr << "Network can not be null or empty or in bad URI format" << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500259 return false;
260 }
261 ndn::Name siteName(site);
262 if (!siteName.empty()) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600263 m_confParam.setSiteName(siteName);
akmhoque157b0a42014-05-13 00:26:37 -0500264 }
265 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400266 std::cerr << "Site can not be null or empty or in bad URI format" << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500267 return false;
268 }
269 ndn::Name routerName(router);
270 if (!routerName.empty()) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600271 m_confParam.setRouterName(routerName);
akmhoque157b0a42014-05-13 00:26:37 -0500272 }
273 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400274 std::cerr << "Router name can not be null or empty or in bad URI format" << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500275 return false;
276 }
277 }
278 catch (const std::exception& ex) {
Nick Gordone98480b2017-05-24 11:23:03 -0500279 std::cerr << ex.what() << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500280 return false;
281 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700282
alvya2228c62014-12-09 10:25:11 -0600283 // lsa-refresh-time
alvy5a454952014-12-15 12:49:54 -0600284 uint32_t lsaRefreshTime = section.get<uint32_t>("lsa-refresh-time", LSA_REFRESH_TIME_DEFAULT);
alvya2228c62014-12-09 10:25:11 -0600285
286 if (lsaRefreshTime >= LSA_REFRESH_TIME_MIN && lsaRefreshTime <= LSA_REFRESH_TIME_MAX) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600287 m_confParam.setLsaRefreshTime(lsaRefreshTime);
akmhoque157b0a42014-05-13 00:26:37 -0500288 }
alvya2228c62014-12-09 10:25:11 -0600289 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400290 std::cerr << "Invalid value for lsa-refresh-time. "
291 << "Allowed range: " << LSA_REFRESH_TIME_MIN
292 << "-" << LSA_REFRESH_TIME_MAX << std::endl;
alvya2228c62014-12-09 10:25:11 -0600293 return false;
294 }
295
296 // router-dead-interval
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400297 uint32_t routerDeadInterval = section.get<uint32_t>("router-dead-interval", 2 * lsaRefreshTime);
alvya2228c62014-12-09 10:25:11 -0600298
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600299 if (routerDeadInterval > m_confParam.getLsaRefreshTime()) {
300 m_confParam.setRouterDeadInterval(routerDeadInterval);
alvya2228c62014-12-09 10:25:11 -0600301 }
302 else {
303 std::cerr << "Value of router-dead-interval must be larger than lsa-refresh-time" << std::endl;
304 return false;
305 }
306
307 // lsa-interest-lifetime
308 int lifetime = section.get<int>("lsa-interest-lifetime", LSA_INTEREST_LIFETIME_DEFAULT);
309
310 if (lifetime >= LSA_INTEREST_LIFETIME_MIN && lifetime <= LSA_INTEREST_LIFETIME_MAX) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600311 m_confParam.setLsaInterestLifetime(ndn::time::seconds(lifetime));
alvya2228c62014-12-09 10:25:11 -0600312 }
313 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400314 std::cerr << "Invalid value for lsa-interest-timeout. "
315 << "Allowed range: " << LSA_INTEREST_LIFETIME_MIN
316 << "-" << LSA_INTEREST_LIFETIME_MAX << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500317 return false;
318 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700319
Ashlesh Gawande32ec3fd2018-07-18 13:42:32 -0500320 // sync-interest-lifetime
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600321 uint32_t syncInterestLifetime = section.get<uint32_t>("sync-interest-lifetime",
322 SYNC_INTEREST_LIFETIME_DEFAULT);
Ashlesh Gawandef7da9c52018-02-06 17:36:46 -0600323 if (syncInterestLifetime >= SYNC_INTEREST_LIFETIME_MIN &&
324 syncInterestLifetime <= SYNC_INTEREST_LIFETIME_MAX) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600325 m_confParam.setSyncInterestLifetime(syncInterestLifetime);
Ashlesh Gawandef7da9c52018-02-06 17:36:46 -0600326 }
327 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400328 std::cerr << "Invalid value for sync-interest-lifetime. "
329 << "Allowed range: " << SYNC_INTEREST_LIFETIME_MIN
330 << "-" << SYNC_INTEREST_LIFETIME_MAX << std::endl;
Ashlesh Gawandef7da9c52018-02-06 17:36:46 -0600331 return false;
332 }
333
Davide Pesaventob0716542024-12-16 19:12:11 -0500334 // state-dir
akmhoque674b0b12014-05-20 14:33:28 -0500335 try {
Davide Pesaventob0716542024-12-16 19:12:11 -0500336 fs::path stateDir(section.get<std::string>("state-dir"));
337 if (fs::exists(stateDir)) {
338 if (fs::is_directory(stateDir)) {
Davide Pesavento22520e62021-06-08 22:16:52 -0400339 // copying nlsr.conf file to a user-defined directory for possible modification
Davide Pesaventob0716542024-12-16 19:12:11 -0500340 auto conFileDynamic = stateDir / "nlsr.conf";
341 if (m_confFileName == conFileDynamic.string()) {
Ashlesh Gawande328fc112019-12-12 17:06:44 -0600342 std::cerr << "Please use nlsr.conf stored at another location "
343 << "or change the state-dir in the configuration." << std::endl;
344 std::cerr << "The file at " << conFileDynamic <<
345 " is used as dynamic file for saving NLSR runtime changes." << std::endl;
346 std::cerr << "The dynamic file can be used for next run "
347 << "after copying to another location." << std::endl;
348 return false;
349 }
350
Davide Pesaventob0716542024-12-16 19:12:11 -0500351 m_confParam.setConfFileNameDynamic(conFileDynamic.string());
dulalsaurab82a34c22019-02-04 17:31:21 +0000352 try {
Davide Pesaventob0716542024-12-16 19:12:11 -0500353 fs::copy_file(m_confFileName, conFileDynamic, fs::copy_options::overwrite_existing);
dulalsaurab82a34c22019-02-04 17:31:21 +0000354 }
Davide Pesaventob0716542024-12-16 19:12:11 -0500355 catch (const fs::filesystem_error& e) {
356 std::cerr << "Error copying conf file to state-dir: " << e.what() << std::endl;
Davide Pesavento22520e62021-06-08 22:16:52 -0400357 return false;
dulalsaurab82a34c22019-02-04 17:31:21 +0000358 }
Ashlesh Gawande328fc112019-12-12 17:06:44 -0600359
Davide Pesaventob0716542024-12-16 19:12:11 -0500360 auto testFilePath = stateDir / "test.seq";
361 std::ofstream testFile(testFilePath);
362 if (testFile) {
363 m_confParam.setStateFileDir(stateDir.string());
akmhoque674b0b12014-05-20 14:33:28 -0500364 }
365 else {
Davide Pesaventob0716542024-12-16 19:12:11 -0500366 std::cerr << "NLSR does not have read/write permission on state-dir" << std::endl;
akmhoque674b0b12014-05-20 14:33:28 -0500367 return false;
368 }
Davide Pesaventob0716542024-12-16 19:12:11 -0500369 testFile.close();
370 fs::remove(testFilePath);
akmhoque674b0b12014-05-20 14:33:28 -0500371 }
372 else {
Davide Pesaventob0716542024-12-16 19:12:11 -0500373 std::cerr << "Provided state-dir " << stateDir << " is not a directory" << std::endl;
akmhoque674b0b12014-05-20 14:33:28 -0500374 return false;
375 }
376 }
377 else {
Davide Pesaventob0716542024-12-16 19:12:11 -0500378 std::cerr << "Provided state-dir " << stateDir << " does not exist" << std::endl;
akmhoque674b0b12014-05-20 14:33:28 -0500379 return false;
380 }
381 }
382 catch (const std::exception& ex) {
Davide Pesaventob0716542024-12-16 19:12:11 -0500383 std::cerr << "You must configure state-dir" << std::endl;
akmhoque674b0b12014-05-20 14:33:28 -0500384 std::cerr << ex.what() << std::endl;
385 return false;
386 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700387
akmhoque157b0a42014-05-13 00:26:37 -0500388 return true;
389}
390
391bool
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700392ConfFileProcessor::processConfSectionNeighbors(const ConfigSection& section)
akmhoque157b0a42014-05-13 00:26:37 -0500393{
alvya2228c62014-12-09 10:25:11 -0600394 // hello-retries
395 int retrials = section.get<int>("hello-retries", HELLO_RETRIES_DEFAULT);
396
397 if (retrials >= HELLO_RETRIES_MIN && retrials <= HELLO_RETRIES_MAX) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600398 m_confParam.setInterestRetryNumber(retrials);
akmhoque157b0a42014-05-13 00:26:37 -0500399 }
alvya2228c62014-12-09 10:25:11 -0600400 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400401 std::cerr << "Invalid value for hello-retries. "
402 << "Allowed range: " << HELLO_RETRIES_MIN << "-" << HELLO_RETRIES_MAX << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500403 return false;
404 }
alvya2228c62014-12-09 10:25:11 -0600405
406 // hello-timeout
alvy5a454952014-12-15 12:49:54 -0600407 uint32_t timeOut = section.get<uint32_t>("hello-timeout", HELLO_TIMEOUT_DEFAULT);
alvya2228c62014-12-09 10:25:11 -0600408
409 if (timeOut >= HELLO_TIMEOUT_MIN && timeOut <= HELLO_TIMEOUT_MAX) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600410 m_confParam.setInterestResendTime(timeOut);
akmhoque157b0a42014-05-13 00:26:37 -0500411 }
alvya2228c62014-12-09 10:25:11 -0600412 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400413 std::cerr << "Invalid value for hello-timeout. "
414 << "Allowed range: " << HELLO_TIMEOUT_MIN << "-" << HELLO_TIMEOUT_MAX << std::endl;
alvya2228c62014-12-09 10:25:11 -0600415 return false;
akmhoque157b0a42014-05-13 00:26:37 -0500416 }
alvya2228c62014-12-09 10:25:11 -0600417
418 // hello-interval
alvy5a454952014-12-15 12:49:54 -0600419 uint32_t interval = section.get<uint32_t>("hello-interval", HELLO_INTERVAL_DEFAULT);
alvya2228c62014-12-09 10:25:11 -0600420
421 if (interval >= HELLO_INTERVAL_MIN && interval <= HELLO_INTERVAL_MAX) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600422 m_confParam.setInfoInterestInterval(interval);
akmhoque157b0a42014-05-13 00:26:37 -0500423 }
alvya2228c62014-12-09 10:25:11 -0600424 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400425 std::cerr << "Invalid value for hello-interval. "
426 << "Allowed range: " << HELLO_INTERVAL_MIN << "-" << HELLO_INTERVAL_MAX << std::endl;
alvya2228c62014-12-09 10:25:11 -0600427 return false;
akmhoque157b0a42014-05-13 00:26:37 -0500428 }
Vince Lehman7b616582014-10-17 16:25:39 -0500429
430 // Event intervals
431 // adj-lsa-build-interval
432 ConfigurationVariable<uint32_t> adjLsaBuildInterval("adj-lsa-build-interval",
dmcoomes9f936662017-03-02 10:33:09 -0600433 std::bind(&ConfParameter::setAdjLsaBuildInterval,
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600434 &m_confParam, _1));
Vince Lehman7b616582014-10-17 16:25:39 -0500435 adjLsaBuildInterval.setMinAndMaxValue(ADJ_LSA_BUILD_INTERVAL_MIN, ADJ_LSA_BUILD_INTERVAL_MAX);
436 adjLsaBuildInterval.setOptional(ADJ_LSA_BUILD_INTERVAL_DEFAULT);
437
438 if (!adjLsaBuildInterval.parseFromConfigSection(section)) {
439 return false;
440 }
Nick Gordond5c1a372016-10-31 13:56:23 -0500441 // Set the retry count for fetching the FaceStatus dataset
442 ConfigurationVariable<uint32_t> faceDatasetFetchTries("face-dataset-fetch-tries",
443 std::bind(&ConfParameter::setFaceDatasetFetchTries,
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400444 &m_confParam, _1));
Nick Gordond5c1a372016-10-31 13:56:23 -0500445
446 faceDatasetFetchTries.setMinAndMaxValue(FACE_DATASET_FETCH_TRIES_MIN,
447 FACE_DATASET_FETCH_TRIES_MAX);
448 faceDatasetFetchTries.setOptional(FACE_DATASET_FETCH_TRIES_DEFAULT);
449
450 if (!faceDatasetFetchTries.parseFromConfigSection(section)) {
451 return false;
452 }
453
454 // Set the interval between FaceStatus dataset fetch attempts.
Ashlesh Gawande3909aa12017-07-28 16:01:35 -0500455 ConfigurationVariable<uint32_t> faceDatasetFetchInterval("face-dataset-fetch-interval",
Davide Pesaventod90338d2021-01-07 17:50:05 -0500456 std::bind(&ConfParameter::setFaceDatasetFetchInterval,
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400457 &m_confParam, _1));
Nick Gordond5c1a372016-10-31 13:56:23 -0500458
Ashlesh Gawande3909aa12017-07-28 16:01:35 -0500459 faceDatasetFetchInterval.setMinAndMaxValue(FACE_DATASET_FETCH_INTERVAL_MIN,
460 FACE_DATASET_FETCH_INTERVAL_MAX);
461 faceDatasetFetchInterval.setOptional(FACE_DATASET_FETCH_INTERVAL_DEFAULT);
Nick Gordond5c1a372016-10-31 13:56:23 -0500462
463 if (!faceDatasetFetchInterval.parseFromConfigSection(section)) {
464 return false;
465 }
Vince Lehman7b616582014-10-17 16:25:39 -0500466
Ashlesh Gawande328fc112019-12-12 17:06:44 -0600467 for (const auto& tn : section) {
468 if (tn.first == "neighbor") {
akmhoque157b0a42014-05-13 00:26:37 -0500469 try {
Ashlesh Gawande328fc112019-12-12 17:06:44 -0600470 ConfigSection CommandAttriTree = tn.second;
akmhoque157b0a42014-05-13 00:26:37 -0500471 std::string name = CommandAttriTree.get<std::string>("name");
Nick Gordone9733ed2017-04-26 10:48:39 -0500472 std::string uriString = CommandAttriTree.get<std::string>("face-uri");
alvy2fe12872014-11-25 10:32:23 -0600473
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500474 ndn::FaceUri faceUri;
Davide Pesavento4b9d30f2020-05-01 02:48:34 -0400475 if (!faceUri.parse(uriString)) {
476 std::cerr << "face-uri parsing failed" << std::endl;
Ashlesh Gawande7e3f6d72019-01-25 13:13:43 -0600477 return false;
478 }
479
480 bool failedToCanonize = false;
Davide Pesavento4b9d30f2020-05-01 02:48:34 -0400481 faceUri.canonize([&faceUri] (const auto& canonicalUri) {
Ashlesh Gawande7e3f6d72019-01-25 13:13:43 -0600482 faceUri = canonicalUri;
483 },
Davide Pesavento4b9d30f2020-05-01 02:48:34 -0400484 [&faceUri, &failedToCanonize] (const auto& reason) {
Ashlesh Gawande7e3f6d72019-01-25 13:13:43 -0600485 failedToCanonize = true;
Davide Pesavento4b9d30f2020-05-01 02:48:34 -0400486 std::cerr << "Could not canonize URI: '" << faceUri
487 << "' because: " << reason << std::endl;
Ashlesh Gawande7e3f6d72019-01-25 13:13:43 -0600488 },
489 m_io,
490 TIME_ALLOWED_FOR_CANONIZATION);
491 m_io.run();
Davide Pesavento5849ee72023-11-12 20:00:21 -0500492 m_io.restart();
Ashlesh Gawande7e3f6d72019-01-25 13:13:43 -0600493
494 if (failedToCanonize) {
alvy2fe12872014-11-25 10:32:23 -0600495 return false;
496 }
497
Davide Pesavento4b9d30f2020-05-01 02:48:34 -0400498 double linkCost = CommandAttriTree.get<double>("link-cost", Adjacent::DEFAULT_LINK_COST);
akmhoque157b0a42014-05-13 00:26:37 -0500499 ndn::Name neighborName(name);
500 if (!neighborName.empty()) {
Vince Lehmancb76ade2014-08-28 21:24:41 -0500501 Adjacent adj(name, faceUri, linkCost, Adjacent::STATUS_INACTIVE, 0, 0);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600502 m_confParam.getAdjacencyList().insert(adj);
akmhoque157b0a42014-05-13 00:26:37 -0500503 }
504 else {
awlane879afac2025-04-28 17:59:36 -0500505 std::cerr << "No neighbor name found or bad URI format! Expected:\n"
506 << " name [neighbor router name]\n face-uri [face uri]\n link-cost [link cost] OPTIONAL" << std::endl;
akmhoque53353462014-04-22 08:43:45 -0500507 }
508 }
akmhoque157b0a42014-05-13 00:26:37 -0500509 catch (const std::exception& ex) {
510 std::cerr << ex.what() << std::endl;
511 return false;
512 }
akmhoque53353462014-04-22 08:43:45 -0500513 }
514 }
akmhoque157b0a42014-05-13 00:26:37 -0500515 return true;
akmhoque53353462014-04-22 08:43:45 -0500516}
517
akmhoque157b0a42014-05-13 00:26:37 -0500518bool
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700519ConfFileProcessor::processConfSectionHyperbolic(const ConfigSection& section)
akmhoque53353462014-04-22 08:43:45 -0500520{
alvya2228c62014-12-09 10:25:11 -0600521 // state
Nick Gordone98480b2017-05-24 11:23:03 -0500522 std::string state = section.get<std::string>("state", "off");
alvya2228c62014-12-09 10:25:11 -0600523
524 if (boost::iequals(state, "off")) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600525 m_confParam.setHyperbolicState(HYPERBOLIC_STATE_OFF);
akmhoque53353462014-04-22 08:43:45 -0500526 }
alvya2228c62014-12-09 10:25:11 -0600527 else if (boost::iequals(state, "on")) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600528 m_confParam.setHyperbolicState(HYPERBOLIC_STATE_ON);
alvya2228c62014-12-09 10:25:11 -0600529 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400530 else if (boost::iequals(state, "dry-run")) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600531 m_confParam.setHyperbolicState(HYPERBOLIC_STATE_DRY_RUN);
alvya2228c62014-12-09 10:25:11 -0600532 }
533 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400534 std::cerr << "Invalid setting for hyperbolic state. "
535 << "Allowed values: off, on, dry-run" << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500536 return false;
akmhoque53353462014-04-22 08:43:45 -0500537 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700538
akmhoque157b0a42014-05-13 00:26:37 -0500539 try {
Laqin Fan54a43f02017-03-08 12:31:30 -0600540 // Radius and angle(s) are mandatory configuration parameters in hyperbolic section.
541 // Even if router can have hyperbolic routing calculation off but other router
542 // in the network may use hyperbolic routing calculation for FIB generation.
543 // So each router need to advertise its hyperbolic coordinates in the network
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700544 double radius = section.get<double>("radius");
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600545 std::string angleString = section.get<std::string>("angle");
546
547 std::stringstream ss(angleString);
548 std::vector<double> angles;
549
550 double angle;
551
Laqin Fan54a43f02017-03-08 12:31:30 -0600552 while (ss >> angle) {
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600553 angles.push_back(angle);
Laqin Fan54a43f02017-03-08 12:31:30 -0600554 if (ss.peek() == ',' || ss.peek() == ' ') {
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600555 ss.ignore();
556 }
557 }
558
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600559 if (!m_confParam.setCorR(radius)) {
akmhoque157b0a42014-05-13 00:26:37 -0500560 return false;
561 }
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600562 m_confParam.setCorTheta(angles);
akmhoque53353462014-04-22 08:43:45 -0500563 }
akmhoque157b0a42014-05-13 00:26:37 -0500564 catch (const std::exception& ex) {
565 std::cerr << ex.what() << std::endl;
566 if (state == "on" || state == "dry-run") {
567 return false;
568 }
akmhoque53353462014-04-22 08:43:45 -0500569 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700570
akmhoque157b0a42014-05-13 00:26:37 -0500571 return true;
akmhoque53353462014-04-22 08:43:45 -0500572}
573
akmhoque157b0a42014-05-13 00:26:37 -0500574bool
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700575ConfFileProcessor::processConfSectionFib(const ConfigSection& section)
akmhoque53353462014-04-22 08:43:45 -0500576{
alvya2228c62014-12-09 10:25:11 -0600577 // max-faces-per-prefix
578 int maxFacesPerPrefix = section.get<int>("max-faces-per-prefix", MAX_FACES_PER_PREFIX_DEFAULT);
579
580 if (maxFacesPerPrefix >= MAX_FACES_PER_PREFIX_MIN &&
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400581 maxFacesPerPrefix <= MAX_FACES_PER_PREFIX_MAX) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600582 m_confParam.setMaxFacesPerPrefix(maxFacesPerPrefix);
akmhoque53353462014-04-22 08:43:45 -0500583 }
alvya2228c62014-12-09 10:25:11 -0600584 else {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400585 std::cerr << "Invalid value for max-faces-per-prefix. "
586 << "Allowed range: " << MAX_FACES_PER_PREFIX_MIN
587 << "-" << MAX_FACES_PER_PREFIX_MAX << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500588 return false;
589 }
Vince Lehman7b616582014-10-17 16:25:39 -0500590
591 // routing-calc-interval
592 ConfigurationVariable<uint32_t> routingCalcInterval("routing-calc-interval",
dmcoomes9f936662017-03-02 10:33:09 -0600593 std::bind(&ConfParameter::setRoutingCalcInterval,
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600594 &m_confParam, _1));
Vince Lehman7b616582014-10-17 16:25:39 -0500595 routingCalcInterval.setMinAndMaxValue(ROUTING_CALC_INTERVAL_MIN, ROUTING_CALC_INTERVAL_MAX);
596 routingCalcInterval.setOptional(ROUTING_CALC_INTERVAL_DEFAULT);
597
598 if (!routingCalcInterval.parseFromConfigSection(section)) {
599 return false;
600 }
601
akmhoque157b0a42014-05-13 00:26:37 -0500602 return true;
akmhoque53353462014-04-22 08:43:45 -0500603}
604
akmhoque157b0a42014-05-13 00:26:37 -0500605bool
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700606ConfFileProcessor::processConfSectionAdvertising(const ConfigSection& section)
akmhoque53353462014-04-22 08:43:45 -0500607{
Ashlesh Gawande328fc112019-12-12 17:06:44 -0600608 for (const auto& tn : section) {
akmhoque157b0a42014-05-13 00:26:37 -0500609 try {
awlane879afac2025-04-28 17:59:36 -0500610 ndn::Name namePrefix(tn.first.data());
akmhoque157b0a42014-05-13 00:26:37 -0500611 if (!namePrefix.empty()) {
awlane879afac2025-04-28 17:59:36 -0500612 m_confParam.getNamePrefixList().insert(namePrefix, "", tn.second.get_value<uint64_t>());
akmhoque157b0a42014-05-13 00:26:37 -0500613 }
614 else {
awlane879afac2025-04-28 17:59:36 -0500615 std::cerr << " Wrong format or bad URI!\nExpected [name in ndn URI format] [cost],"
616 << " got prefix: " << tn.first.data() << " cost:" << tn.second.data() << std::endl;
akmhoque157b0a42014-05-13 00:26:37 -0500617 return false;
618 }
619 }
awlane879afac2025-04-28 17:59:36 -0500620 catch (const boost::property_tree::ptree_bad_data& ex) {
621 //Catches errors from get_value above
622 std::cerr << "Invalid cost format; only integers are allowed" << std::endl;
623 return false;
624 }
akmhoque157b0a42014-05-13 00:26:37 -0500625 catch (const std::exception& ex) {
626 std::cerr << ex.what() << std::endl;
627 return false;
628 }
akmhoque53353462014-04-22 08:43:45 -0500629 }
akmhoque157b0a42014-05-13 00:26:37 -0500630 return true;
akmhoque53353462014-04-22 08:43:45 -0500631}
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700632
633bool
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700634ConfFileProcessor::processConfSectionSecurity(const ConfigSection& section)
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700635{
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400636 auto it = section.begin();
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700637
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500638 if (it == section.end() || it->first != "validator") {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400639 std::cerr << "Error: Expected validator section!" << std::endl;
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500640 return false;
641 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700642
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600643 m_confParam.getValidator().load(it->second, m_confFileName);
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500644
akmhoqued57f3672014-06-10 10:41:32 -0500645 it++;
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500646 if (it != section.end() && it->first == "prefix-update-validator") {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600647 m_confParam.getPrefixUpdateValidator().load(it->second, m_confFileName);
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700648
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500649 it++;
650 for (; it != section.end(); it++) {
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500651 if (it->first != "cert-to-publish") {
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400652 std::cerr << "Error: Expected cert-to-publish!" << std::endl;
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500653 return false;
654 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700655
Davide Pesaventob0716542024-12-16 19:12:11 -0500656 fs::path certPath = fs::canonical(fs::path(m_confFileName).parent_path() / it->second.data());
657 std::ifstream ifs(certPath);
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700658
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400659 ndn::security::Certificate idCert;
660 try {
661 idCert = ndn::io::loadTlv<ndn::security::Certificate>(ifs);
662 }
663 catch (const std::exception& e) {
Davide Pesaventob0716542024-12-16 19:12:11 -0500664 std::cerr << "Error: Cannot load cert-to-publish " << certPath << ": " << e.what() << std::endl;
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500665 return false;
666 }
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400667
Davide Pesaventob0716542024-12-16 19:12:11 -0500668 m_confParam.addCertPath(certPath.string());
Davide Pesavento7bc3d432021-10-25 21:08:04 -0400669 m_confParam.loadCertToValidator(idCert);
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700670 }
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500671 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700672
673 return true;
674}
675
alvy2fe12872014-11-25 10:32:23 -0600676} // namespace nlsr