blob: efb24a0c80791ab5635deda8e567328b67bbef45 [file] [log] [blame]
alvy297f4162015-03-03 17:15:33 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Nick Gordonfeae5572017-01-13 12:06:26 -06003 * Copyright (c) 2014-2017, The University of Memphis,
alvy297f4162015-03-03 17:15:33 -06004 * 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/>.
20 **/
21
22#include "update/prefix-update-processor.hpp"
23
24#include "../control-commands.hpp"
25#include "../test-common.hpp"
26#include "nlsr.hpp"
27
28#include <ndn-cxx/interest.hpp>
Junxiao Shi3e5120c2016-09-10 16:58:34 +000029#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
30#include <ndn-cxx/mgmt/nfd/control-response.hpp>
alvy297f4162015-03-03 17:15:33 -060031#include <ndn-cxx/security/key-chain.hpp>
32#include <ndn-cxx/util/dummy-client-face.hpp>
33
34#include <boost/filesystem.hpp>
35
36using namespace ndn;
37
38namespace nlsr {
39namespace update {
40namespace test {
41
Ashlesh Gawande415676b2016-12-22 00:26:23 -060042class PrefixUpdateFixture : public nlsr::test::UnitTestTimeFixture
alvy297f4162015-03-03 17:15:33 -060043{
44public:
45 PrefixUpdateFixture()
Ashlesh Gawande415676b2016-12-22 00:26:23 -060046 : face(g_ioService, keyChain, {true, true})
alvy297f4162015-03-03 17:15:33 -060047 , siteIdentity(ndn::Name("/ndn/edu/test-site").appendVersion())
48 , opIdentity(ndn::Name(siteIdentity).append(ndn::Name("%C1.Operator")).appendVersion())
Ashlesh Gawande415676b2016-12-22 00:26:23 -060049 , nlsr(g_ioService, g_scheduler, face, g_keyChain)
alvy297f4162015-03-03 17:15:33 -060050 , keyPrefix(("/ndn/broadcast"))
51 , updateProcessor(nlsr.getPrefixUpdateProcessor())
52 , SITE_CERT_PATH(boost::filesystem::current_path() / std::string("site.cert"))
53 {
54 createSiteCert();
55 BOOST_REQUIRE(siteCert != nullptr);
56
57 createOperatorCert();
58 BOOST_REQUIRE(opCert != nullptr);
59
60 const std::string CONFIG =
61 "rule\n"
62 "{\n"
63 " id \"NLSR ControlCommand Rule\"\n"
64 " for interest\n"
65 " filter\n"
66 " {\n"
67 " type name\n"
68 " regex ^<localhost><nlsr><prefix-update>[<advertise><withdraw>]<>$\n"
69 " }\n"
70 " checker\n"
71 " {\n"
72 " type customized\n"
73 " sig-type rsa-sha256\n"
74 " key-locator\n"
75 " {\n"
76 " type name\n"
77 " regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$\n"
78 " }\n"
79 " }\n"
80 "}\n"
81 "rule\n"
82 "{\n"
83 " id \"NLSR Hierarchy Rule\"\n"
84 " for data\n"
85 " filter\n"
86 " {\n"
87 " type name\n"
88 " regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$\n"
89 " }\n"
90 " checker\n"
91 " {\n"
92 " type hierarchical\n"
93 " sig-type rsa-sha256\n"
94 " }\n"
95 "}\n"
96 "trust-anchor\n"
97 "{\n"
98 " type file\n"
99 " file-name \"site.cert\"\n"
100 "}\n";
101
102 const boost::filesystem::path CONFIG_PATH =
103 (boost::filesystem::current_path() / std::string("unit-test.conf"));
104
105 updateProcessor.getValidator().load(CONFIG, CONFIG_PATH.native());
106
107 // Insert certs after the validator is loaded since ValidatorConfig::load() clears
108 // the certificate cache
109 nlsr.addCertificateToCache(opCert);
110
111 // Set the network so the LSA prefix is constructed
112 nlsr.getConfParameter().setNetwork("/ndn");
113
114 // Initialize NLSR so a sync socket is created
115 nlsr.initialize();
116
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600117 // Saving clock::now before any advanceClocks so that it will
118 // be the same value as what ChronoSync uses in setting the sessionName
119 sessionTime.appendNumber(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count());
alvy297f4162015-03-03 17:15:33 -0600120
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600121 this->advanceClocks(ndn::time::milliseconds(10));
122 face.sentInterests.clear();
alvy297f4162015-03-03 17:15:33 -0600123 }
124
125 void
126 createSiteCert()
127 {
128 // Site cert
129 keyChain.createIdentity(siteIdentity);
130 siteCertName = keyChain.getDefaultCertificateNameForIdentity(siteIdentity);
131 siteCert = keyChain.getCertificate(siteCertName);
132
133 ndn::io::save(*siteCert, SITE_CERT_PATH.string());
134 }
135
136 void
137 createOperatorCert()
138 {
139 // Operator cert
140 ndn::Name keyName = keyChain.generateRsaKeyPairAsDefault(opIdentity, true);
141
dmcoomes9f936662017-03-02 10:33:09 -0600142 opCert = std::make_shared<ndn::IdentityCertificate>();
143 std::shared_ptr<ndn::PublicKey> pubKey = keyChain.getPublicKey(keyName);
alvy297f4162015-03-03 17:15:33 -0600144 opCertName = keyName.getPrefix(-1);
145 opCertName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
146 opCert->setName(opCertName);
147 opCert->setNotBefore(time::system_clock::now() - time::days(1));
148 opCert->setNotAfter(time::system_clock::now() + time::days(1));
149 opCert->setPublicKeyInfo(*pubKey);
Alexander Afanasyev4c2bb362017-03-14 12:29:19 -0700150 opCert->addSubjectDescription(ndn::security::v1::CertificateSubjectDescription(ndn::oid::ATTRIBUTE_NAME,
151 keyName.toUri()));
alvy297f4162015-03-03 17:15:33 -0600152 opCert->encode();
153
154 keyChain.signByIdentity(*opCert, siteIdentity);
155
156 keyChain.addCertificateAsIdentityDefault(*opCert);
157 }
158
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600159 void sendInterestForPublishedData() {
160 // Need to send an interest now since ChronoSync
161 // no longer does face->put(*data) in publishData.
162 // Instead it does it in onInterest
163 ndn::Name lsaInterestName("/localhop/ndn/NLSR/LSA");
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500164 lsaInterestName.append(NameLsa::TYPE_STRING);
165
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600166 // The part after LSA is Chronosync getSession
167 lsaInterestName.append(sessionTime);
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500168 lsaInterestName.appendNumber(nlsr.getLsdb().getSequencingManager().getNameLsaSeq());
169
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600170 shared_ptr<Interest> lsaInterest = make_shared<Interest>(lsaInterestName);
171
172 face.receive(*lsaInterest);
173 this->advanceClocks(ndn::time::milliseconds(10));
174 }
175
alvy297f4162015-03-03 17:15:33 -0600176 bool
177 wasRoutingUpdatePublished()
178 {
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600179 sendInterestForPublishedData();
180
alvy297f4162015-03-03 17:15:33 -0600181 const ndn::Name& lsaPrefix = nlsr.getConfParameter().getLsaPrefix();
182
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600183 const auto& it = std::find_if(face.sentData.begin(), face.sentData.end(),
alvy297f4162015-03-03 17:15:33 -0600184 [lsaPrefix] (const ndn::Data& data) {
185 return lsaPrefix.isPrefixOf(data.getName());
186 });
187
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600188 return (it != face.sentData.end());
alvy297f4162015-03-03 17:15:33 -0600189 }
190
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500191 void
192 checkResponseCode(const Name& commandPrefix, uint64_t expectedCode)
193 {
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600194 std::vector<Data>::iterator it = std::find_if(face.sentData.begin(),
195 face.sentData.end(),
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500196 [commandPrefix] (const Data& data) {
197 return commandPrefix.isPrefixOf(data.getName());
198 });
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600199 BOOST_REQUIRE(it != face.sentData.end());
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500200
201 ndn::nfd::ControlResponse response(it->getContent().blockFromValue());
202 BOOST_CHECK_EQUAL(response.getCode(), expectedCode);
203 }
204
alvy297f4162015-03-03 17:15:33 -0600205 ~PrefixUpdateFixture()
206 {
207 keyChain.deleteIdentity(siteIdentity);
208 keyChain.deleteIdentity(opIdentity);
209
210 boost::filesystem::remove(SITE_CERT_PATH);
211 }
212
213public:
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600214 ndn::util::DummyClientFace face;
alvy297f4162015-03-03 17:15:33 -0600215 ndn::KeyChain keyChain;
216
217 ndn::Name siteIdentity;
218 ndn::Name siteCertName;
dmcoomes9f936662017-03-02 10:33:09 -0600219 std::shared_ptr<IdentityCertificate> siteCert;
alvy297f4162015-03-03 17:15:33 -0600220
221 ndn::Name opIdentity;
222 ndn::Name opCertName;
dmcoomes9f936662017-03-02 10:33:09 -0600223 std::shared_ptr<IdentityCertificate> opCert;
alvy297f4162015-03-03 17:15:33 -0600224
225 Nlsr nlsr;
226 ndn::Name keyPrefix;
227 PrefixUpdateProcessor& updateProcessor;
228
229 const boost::filesystem::path SITE_CERT_PATH;
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600230 ndn::Name sessionTime;
alvy297f4162015-03-03 17:15:33 -0600231};
232
233BOOST_FIXTURE_TEST_SUITE(TestPrefixUpdateProcessor, PrefixUpdateFixture)
234
235BOOST_AUTO_TEST_CASE(Basic)
236{
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500237 uint64_t nameLsaSeqNoBeforeInterest = nlsr.getLsdb().getSequencingManager().getNameLsaSeq();
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500238 updateProcessor.enable();
239
alvy297f4162015-03-03 17:15:33 -0600240 // Advertise
241 ndn::nfd::ControlParameters parameters;
242 parameters.setName("/prefix/to/advertise/");
243
244 ndn::Name advertiseCommand("/localhost/nlsr/prefix-update/advertise");
245 advertiseCommand.append(parameters.wireEncode());
246
dmcoomes9f936662017-03-02 10:33:09 -0600247 std::shared_ptr<Interest> advertiseInterest = std::make_shared<Interest>(advertiseCommand);
alvy297f4162015-03-03 17:15:33 -0600248 keyChain.signByIdentity(*advertiseInterest, opIdentity);
249
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600250 face.receive(*advertiseInterest);
251 this->advanceClocks(ndn::time::milliseconds(10));
alvy297f4162015-03-03 17:15:33 -0600252
253 NamePrefixList& namePrefixList = nlsr.getNamePrefixList();
254
255 BOOST_REQUIRE_EQUAL(namePrefixList.getSize(), 1);
256 BOOST_CHECK_EQUAL(namePrefixList.getNameList().front(), parameters.getName());
257
258 BOOST_CHECK(wasRoutingUpdatePublished());
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500259 BOOST_CHECK(nameLsaSeqNoBeforeInterest < nlsr.getLsdb().getSequencingManager().getNameLsaSeq());
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600260
261 face.sentData.clear();
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500262 nameLsaSeqNoBeforeInterest = nlsr.getLsdb().getSequencingManager().getNameLsaSeq();
alvy297f4162015-03-03 17:15:33 -0600263
264 // Withdraw
265 ndn::Name withdrawCommand("/localhost/nlsr/prefix-update/withdraw");
266 withdrawCommand.append(parameters.wireEncode());
267
dmcoomes9f936662017-03-02 10:33:09 -0600268 std::shared_ptr<Interest> withdrawInterest = std::make_shared<Interest>(withdrawCommand);
alvy297f4162015-03-03 17:15:33 -0600269 keyChain.signByIdentity(*withdrawInterest, opIdentity);
270
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600271 face.receive(*withdrawInterest);
272 this->advanceClocks(ndn::time::milliseconds(10));
alvy297f4162015-03-03 17:15:33 -0600273
274 BOOST_CHECK_EQUAL(namePrefixList.getSize(), 0);
275
276 BOOST_CHECK(wasRoutingUpdatePublished());
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500277 BOOST_CHECK(nameLsaSeqNoBeforeInterest < nlsr.getLsdb().getSequencingManager().getNameLsaSeq());
alvy297f4162015-03-03 17:15:33 -0600278}
279
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500280BOOST_AUTO_TEST_CASE(DisabledAndEnabled)
281{
282 ndn::nfd::ControlParameters parameters;
283 parameters.setName("/prefix/to/advertise/");
284
285 ndn::Name advertiseCommand("/localhost/nlsr/prefix-update/advertise");
286 advertiseCommand.append(parameters.wireEncode());
287
dmcoomes9f936662017-03-02 10:33:09 -0600288 std::shared_ptr<Interest> advertiseInterest = std::make_shared<Interest>(advertiseCommand);
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500289 keyChain.signByIdentity(*advertiseInterest, opIdentity);
290
291 // Command should be rejected
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600292 face.receive(*advertiseInterest);
293 this->advanceClocks(ndn::time::milliseconds(10));
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500294
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600295 BOOST_REQUIRE(!face.sentData.empty());
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500296
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600297 const ndn::MetaInfo& metaInfo = face.sentData.front().getMetaInfo();
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500298 BOOST_CHECK_EQUAL(metaInfo.getType(), ndn::tlv::ContentType_Nack);
299
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600300 face.sentData.clear();
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500301
302 // Enable PrefixUpdateProcessor so commands will be processed
303 updateProcessor.enable();
304
305 // Command should be accepted
Ashlesh Gawande415676b2016-12-22 00:26:23 -0600306 face.receive(*advertiseInterest);
307 this->advanceClocks(ndn::time::milliseconds(10));
Vince Lehmand33e5bc2015-06-22 15:27:50 -0500308
309 checkResponseCode(advertiseCommand, 200);
310}
311
alvy297f4162015-03-03 17:15:33 -0600312BOOST_AUTO_TEST_SUITE_END()
313
314} // namespace test
315} // namespace update
316} // namespace nlsr