blob: 0497315ad412e054a733ea39f311de8d37af954f [file] [log] [blame]
Shock Jiang698e6ed2014-11-09 11:22:24 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev984ca9d2016-12-19 13:09:14 -08003 * Copyright (c) 2014-2016, Regents of the University of California.
Shock Jiang698e6ed2014-11-09 11:22:24 -08004 *
5 * This file is part of NDNS (Named Data Networking Domain Name Service).
6 * See AUTHORS.md for complete list of NDNS authors and contributors.
7 *
8 * NDNS is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "ndns-label.hpp"
21#include "logger.hpp"
22#include "clients/response.hpp"
23#include "clients/query.hpp"
24#include "clients/iterative-query-controller.hpp"
25#include "validator.hpp"
Shock Jiang06cd2142014-11-23 17:36:02 -080026#include "util/util.hpp"
Shock Jiang698e6ed2014-11-09 11:22:24 -080027
28#include <ndn-cxx/security/key-chain.hpp>
29#include <ndn-cxx/face.hpp>
30#include <boost/program_options.hpp>
31#include <boost/asio.hpp>
32#include <boost/filesystem.hpp>
33#include <boost/noncopyable.hpp>
34
35#include <memory>
36#include <string>
37
Alexander Afanasyevc7c99002015-10-09 17:27:30 -070038NDNS_LOG_INIT("NdnsDig")
Shock Jiang5d5928c2014-12-03 13:41:22 -080039
Shock Jiang698e6ed2014-11-09 11:22:24 -080040namespace ndn {
41namespace ndns {
Shock Jiang698e6ed2014-11-09 11:22:24 -080042
43class NdnsDig
44{
45public:
Yumin Xia6343c5b2016-10-20 15:45:50 -070046 NdnsDig(const Name& dstLabel,
Shock Jiang5d5928c2014-12-03 13:41:22 -080047 const name::Component& rrType, bool shouldValidateIntermediate)
Shock Jiang698e6ed2014-11-09 11:22:24 -080048 : m_dstLabel(dstLabel)
49 , m_rrType(rrType)
Shock Jiang698e6ed2014-11-09 11:22:24 -080050 , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
51 , m_validator(m_face)
Shock Jiang5d5928c2014-12-03 13:41:22 -080052 , m_shouldValidateIntermediate(shouldValidateIntermediate)
Shock Jiang698e6ed2014-11-09 11:22:24 -080053 , m_hasError(false)
54 {
Shock Jiang5d5928c2014-12-03 13:41:22 -080055 if (m_shouldValidateIntermediate)
56 m_ctr = std::unique_ptr<IterativeQueryController>
57 (new IterativeQueryController(m_dstLabel, m_rrType, m_interestLifetime,
58 bind(&NdnsDig::onSucceed, this, _1, _2),
59 bind(&NdnsDig::onFail, this, _1, _2),
60 m_face, &m_validator));
61 else
62 m_ctr = std::unique_ptr<IterativeQueryController>
63 (new IterativeQueryController(m_dstLabel, m_rrType, m_interestLifetime,
64 bind(&NdnsDig::onSucceed, this, _1, _2),
65 bind(&NdnsDig::onFail, this, _1, _2),
66 m_face, nullptr));
Shock Jiang698e6ed2014-11-09 11:22:24 -080067 }
68
69 void
70 run()
71 {
72 NDNS_LOG_INFO(" =================================== "
73 << "start to dig label = " << this->m_dstLabel
74 << " for type = " << this->m_rrType
75 << " =================================== ");
76
77 try {
78 m_ctr->start(); // non-block, may throw exception
79 m_face.processEvents();
80 }
81 catch (std::exception& e) {
Shock Jiang5d5928c2014-12-03 13:41:22 -080082 std::cerr << "Error: " << e.what();
Shock Jiang698e6ed2014-11-09 11:22:24 -080083 m_hasError = true;
84 }
85 }
86
87 void
88 stop()
89 {
90 m_face.getIoService().stop();
91 NDNS_LOG_TRACE("application stops.");
92 }
93
Shock Jiang5d5928c2014-12-03 13:41:22 -080094 void
95 setStartZone(const Name& start)
96 {
97 m_ctr->setStartComponentIndex(start.size());
98 }
99
Shock Jiang698e6ed2014-11-09 11:22:24 -0800100private:
101 void
102 onSucceed(const Data& data, const Response& response)
103 {
Shock Jiang06cd2142014-11-23 17:36:02 -0800104 NDNS_LOG_INFO("Dig get following Response (need verification):");
105 Name name = Name().append(response.getZone()).append(response.getRrLabel());
106 if (name == m_dstLabel && m_rrType == response.getRrType()) {
107 NDNS_LOG_INFO("This is the final response returned by zone=" << response.getZone()
Yumin Xiaa484ba72016-11-10 20:40:12 -0800108 << " and NdnsType=" << response.getContentType()
Shock Jiang06cd2142014-11-23 17:36:02 -0800109 << ". It contains " << response.getRrs().size() << " RR(s)");
110
111 std::string msg;
112 size_t i = 0;
113 for (const auto& rr : response.getRrs()) {
114 try {
115 msg = std::string(reinterpret_cast<const char*>(rr.value()), rr.value_size());
116 NDNS_LOG_INFO("succeed to get the info from RR[" << i << "]"
117 "type=" << rr.type() << " content=" << msg);
118 }
119 catch (std::exception& e) {
120 NDNS_LOG_INFO("error to get the info from RR[" << i << "]"
121 "type=" << rr.type());
122 }
123 ++i;
124 }
125 }
126 else {
127 NDNS_LOG_INFO("[* !! *] This is not final response.The target Label: "
128 << m_dstLabel << " may not exist");
129 }
130
131 if (m_dstFile.empty()) {
132 ;
133 }
134 else if (m_dstFile == "-") {
135 output(data, std::cout, true);
136 }
137 else {
138 NDNS_LOG_INFO("output Data packet to " << m_dstFile << " with BASE64 encoding format");
139 std::filebuf fb;
140 fb.open(m_dstFile, std::ios::out);
141 std::ostream os(&fb);
142 output(data, os, false);
143 }
144
Shock Jiang698e6ed2014-11-09 11:22:24 -0800145 NDNS_LOG_INFO(response);
Shock Jiang06cd2142014-11-23 17:36:02 -0800146
Shock Jiang698e6ed2014-11-09 11:22:24 -0800147 NDNS_LOG_TRACE("to verify the response");
148 m_validator.validate(data,
149 bind(&NdnsDig::onDataValidated, this, _1),
150 bind(&NdnsDig::onDataValidationFailed, this, _1, _2)
151 );
152 }
153
Shock Jiang06cd2142014-11-23 17:36:02 -0800154
Shock Jiang698e6ed2014-11-09 11:22:24 -0800155 void
156 onFail(uint32_t errCode, const std::string& errMsg)
157 {
158 NDNS_LOG_INFO("fail to get response: errCode=" << errCode << " msg=" << errMsg);
159 m_hasError = true;
160 this->stop();
161 }
162
163 void
164 onDataValidated(const shared_ptr<const Data>& data)
165 {
166 NDNS_LOG_INFO("final data pass verification");
167 this->stop();
168 }
169
170 void
171 onDataValidationFailed(const shared_ptr<const Data>& data, const std::string& str)
172 {
173 NDNS_LOG_INFO("final data does not pass verification");
174 m_hasError = true;
175 this->stop();
176 }
177
178public:
179 void
180 setInterestLifetime(const time::milliseconds& lifetime)
181 {
182 m_interestLifetime = lifetime;
183 }
184
Alexander Afanasyev984ca9d2016-12-19 13:09:14 -0800185 bool
Shock Jiang698e6ed2014-11-09 11:22:24 -0800186 hasError() const
187 {
188 return m_hasError;
189 }
190
Shock Jiang06cd2142014-11-23 17:36:02 -0800191 void
192 setDstFile(const std::string& dstFile)
193 {
194 m_dstFile = dstFile;
195 }
196
Shock Jiang698e6ed2014-11-09 11:22:24 -0800197private:
198 Name m_dstLabel;
199 name::Component m_rrType;
200
Shock Jiang698e6ed2014-11-09 11:22:24 -0800201 Name m_certName;
202 time::milliseconds m_interestLifetime;
203
204 Face m_face;
205
206 Validator m_validator;
Shock Jiang5d5928c2014-12-03 13:41:22 -0800207 bool m_shouldValidateIntermediate;
Shock Jiang698e6ed2014-11-09 11:22:24 -0800208 std::unique_ptr<QueryController> m_ctr;
209
210 bool m_hasError;
Shock Jiang06cd2142014-11-23 17:36:02 -0800211 std::string m_dstFile;
Shock Jiang698e6ed2014-11-09 11:22:24 -0800212};
213
214} // namespace ndns
215} // namespace ndn
216
217
218int
219main(int argc, char* argv[])
220{
221 ndn::ndns::log::init();
222 using std::string;
223 using namespace ndn;
224
225 Name dstLabel;
226 int ttl = 4;
227 string rrType = "TXT";
Shock Jiang06cd2142014-11-23 17:36:02 -0800228 string dstFile;
Shock Jiang5d5928c2014-12-03 13:41:22 -0800229 bool shouldValidateIntermediate = true;
230 Name start("/ndn");
231
Shock Jiang698e6ed2014-11-09 11:22:24 -0800232 try {
233 namespace po = boost::program_options;
234 po::variables_map vm;
235
236 po::options_description generic("Generic Options");
237 generic.add_options()("help,h", "print help message");
238
239 po::options_description config("Configuration");
240 config.add_options()
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800241 ("timeout,T", po::value<int>(&ttl), "query timeout. default: 4 sec")
Shock Jiang698e6ed2014-11-09 11:22:24 -0800242 ("rrtype,t", po::value<std::string>(&rrType), "set request RR Type. default: TXT")
Shock Jiang06cd2142014-11-23 17:36:02 -0800243 ("dstFile,d", po::value<std::string>(&dstFile), "set output file of the received Data. "
244 "if omitted, not print; if set to be -, print to stdout; else print to file")
Shock Jiang5d5928c2014-12-03 13:41:22 -0800245 ("start,s", po::value<Name>(&start)->default_value("/ndn"), "set first zone to query")
246 ("not-validate,n", "trigger not validate intermediate results")
Shock Jiang698e6ed2014-11-09 11:22:24 -0800247 ;
248
249 po::options_description hidden("Hidden Options");
250 hidden.add_options()
251 ("name", po::value<Name>(&dstLabel), "name to be resolved")
252 ;
253 po::positional_options_description postion;
254 postion.add("name", 1);
255
256 po::options_description cmdline_options;
257 cmdline_options.add(generic).add(config).add(hidden);
258
259 po::options_description config_file_options;
260 config_file_options.add(config).add(hidden);
261
Shock Jiang06cd2142014-11-23 17:36:02 -0800262 po::options_description visible("Usage: ndns-dig /name/to/be/resolved [-t rrType] [-T ttl]"
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800263 "[-d dstFile] [-s startZone] [-n]\n"
Shock Jiang06cd2142014-11-23 17:36:02 -0800264 "Allowed options");
265
Shock Jiang698e6ed2014-11-09 11:22:24 -0800266 visible.add(generic).add(config);
267
268 po::parsed_options parsed =
269 po::command_line_parser(argc, argv).options(cmdline_options).positional(postion).run();
270
271 po::store(parsed, vm);
272 po::notify(vm);
273
274 if (vm.count("help")) {
Shock Jiang698e6ed2014-11-09 11:22:24 -0800275 std::cout << visible << std::endl;
276 return 0;
277 }
Shock Jiang5d5928c2014-12-03 13:41:22 -0800278
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800279 if (!vm.count("name")) {
280 std::cerr << "must contain a target label parameter." << std::endl;
281 std::cerr << visible << std::endl;
282 return 1;
283 }
284
Shock Jiang5d5928c2014-12-03 13:41:22 -0800285 if (!start.isPrefixOf(dstLabel)) {
286 std::cerr << "Error: start zone " << start << " is not prefix of the target label "
287 << dstLabel << std::endl;
288 return 1;
289 }
290
291 if (vm.count("not-validate")) {
292 shouldValidateIntermediate = false;
293 }
294
295 if (ttl < 0) {
296 std::cerr << "Error: ttl parameter cannot be negative" << std::endl;
297 return 1;
298 }
Shock Jiang698e6ed2014-11-09 11:22:24 -0800299 }
300 catch (const std::exception& ex) {
301 std::cerr << "Parameter Error: " << ex.what() << std::endl;
Shock Jiang5d5928c2014-12-03 13:41:22 -0800302 return 1;
Shock Jiang698e6ed2014-11-09 11:22:24 -0800303 }
304
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800305 try {
Yumin Xia6343c5b2016-10-20 15:45:50 -0700306 ndn::ndns::NdnsDig dig(dstLabel, ndn::name::Component(rrType), shouldValidateIntermediate);
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800307 dig.setInterestLifetime(ndn::time::seconds(ttl));
308 dig.setDstFile(dstFile);
Shock Jiang5d5928c2014-12-03 13:41:22 -0800309
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800310 // Due to ndn testbed does not contain the root zone
311 // dig here starts from the TLD (Top-level Domain)
312 // precondition is that TLD : 1) only contains one component in its name; 2) its name is routable
313 dig.setStartZone(start);
Shock Jiang698e6ed2014-11-09 11:22:24 -0800314
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800315 dig.run();
Shock Jiang5d5928c2014-12-03 13:41:22 -0800316
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800317 if (dig.hasError())
318 return 1;
319 else
320 return 0;
321 }
322 catch (const ndn::ValidatorConfig::Error& e) {
323 std::cerr << "Fail to create the validator: " << e.what() << std::endl;
Shock Jiang698e6ed2014-11-09 11:22:24 -0800324 return 1;
Shock Jiangbb4e15b2014-12-05 09:48:02 -0800325 }
326 catch (const std::exception& e) {
327 std::cerr << "Error: " << e.what() << std::endl;
328 return 1;
329 }
330
Shock Jiang698e6ed2014-11-09 11:22:24 -0800331}