tools: improve user experience by choosing best certificate
automatically and print final response in a pretty way
ndns-update
- pick the best certificate to sign the Update automatically
- support multiple token for content option
ndns-dig
- enhance output option
- change behavior of iterative query controller when NS query is NACKed
logger
- set default logger output to std::cerr
Change-Id: Ib06981c224ccad2a122a4505c84a60977184a55b
diff --git a/tools/ndns-daemon.cpp b/tools/ndns-daemon.cpp
index 5937562..b40f6f0 100644
--- a/tools/ndns-daemon.cpp
+++ b/tools/ndns-daemon.cpp
@@ -218,11 +218,12 @@
// NFD does not to forward Interests to the face it was received from.
// If the name server and its validator share same face,
// the validator cannot be forwarded to the name server itself
+ // For current, two faces are used here.
+
// refs: http://redmine.named-data.net/issues/2206
// @TODO enhance validator to get the certificate from the local db if it has
NdnsDaemon daemon(configFile, face, validatorFace);
-
face.processEvents();
}
catch (std::exception& e) {
diff --git a/tools/ndns-dig.cpp b/tools/ndns-dig.cpp
index 06d7397..18142a0 100644
--- a/tools/ndns-dig.cpp
+++ b/tools/ndns-dig.cpp
@@ -23,6 +23,7 @@
#include "clients/query.hpp"
#include "clients/iterative-query-controller.hpp"
#include "validator.hpp"
+#include "util/util.hpp"
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/face.hpp>
@@ -34,7 +35,6 @@
#include <memory>
#include <string>
-
namespace ndn {
namespace ndns {
NDNS_LOG_INIT("NdnsDig");
@@ -86,8 +86,49 @@
void
onSucceed(const Data& data, const Response& response)
{
- NDNS_LOG_INFO("Dig get following final Response (need verification):");
+ NDNS_LOG_INFO("Dig get following Response (need verification):");
+ Name name = Name().append(response.getZone()).append(response.getRrLabel());
+ if (name == m_dstLabel && m_rrType == response.getRrType()) {
+ NDNS_LOG_INFO("This is the final response returned by zone=" << response.getZone()
+ << " and NdnsType=" << response.getNdnsType()
+ << ". It contains " << response.getRrs().size() << " RR(s)");
+
+ std::string msg;
+ size_t i = 0;
+ for (const auto& rr : response.getRrs()) {
+ try {
+ msg = std::string(reinterpret_cast<const char*>(rr.value()), rr.value_size());
+ NDNS_LOG_INFO("succeed to get the info from RR[" << i << "]"
+ "type=" << rr.type() << " content=" << msg);
+ }
+ catch (std::exception& e) {
+ NDNS_LOG_INFO("error to get the info from RR[" << i << "]"
+ "type=" << rr.type());
+ }
+ ++i;
+ }
+ }
+ else {
+ NDNS_LOG_INFO("[* !! *] This is not final response.The target Label: "
+ << m_dstLabel << " may not exist");
+ }
+
+ if (m_dstFile.empty()) {
+ ;
+ }
+ else if (m_dstFile == "-") {
+ output(data, std::cout, true);
+ }
+ else {
+ NDNS_LOG_INFO("output Data packet to " << m_dstFile << " with BASE64 encoding format");
+ std::filebuf fb;
+ fb.open(m_dstFile, std::ios::out);
+ std::ostream os(&fb);
+ output(data, os, false);
+ }
+
NDNS_LOG_INFO(response);
+
NDNS_LOG_TRACE("to verify the response");
m_validator.validate(data,
bind(&NdnsDig::onDataValidated, this, _1),
@@ -95,6 +136,7 @@
);
}
+
void
onFail(uint32_t errCode, const std::string& errMsg)
{
@@ -131,6 +173,12 @@
return m_hasError;
}
+ void
+ setDstFile(const std::string& dstFile)
+ {
+ m_dstFile = dstFile;
+ }
+
private:
Name m_dstLabel;
name::Component m_rrType;
@@ -145,6 +193,7 @@
std::unique_ptr<QueryController> m_ctr;
bool m_hasError;
+ std::string m_dstFile;
};
} // namespace ndns
@@ -161,7 +210,7 @@
Name dstLabel;
int ttl = 4;
string rrType = "TXT";
-
+ string dstFile;
try {
namespace po = boost::program_options;
po::variables_map vm;
@@ -171,8 +220,10 @@
po::options_description config("Configuration");
config.add_options()
- ("timeout,T", po::value<int>(&ttl), "waiting seconds of query. default: 10 sec")
+ ("timeout,T", po::value<int>(&ttl), "waiting seconds of query. default: 4 sec")
("rrtype,t", po::value<std::string>(&rrType), "set request RR Type. default: TXT")
+ ("dstFile,d", po::value<std::string>(&dstFile), "set output file of the received Data. "
+ "if omitted, not print; if set to be -, print to stdout; else print to file")
;
po::options_description hidden("Hidden Options");
@@ -188,7 +239,10 @@
po::options_description config_file_options;
config_file_options.add(config).add(hidden);
- po::options_description visible("Allowed options");
+ po::options_description visible("Usage: ndns-dig /name/to/be/resolved [-t rrType] [-T ttl]"
+ "[-d dstFile]\n"
+ "Allowed options");
+
visible.add(generic).add(config);
po::parsed_options parsed =
@@ -198,7 +252,6 @@
po::notify(vm);
if (vm.count("help")) {
- std::cout << "Usage: dig /name/to/be/resolved [-t rrType] [-T ttl]" << std::endl;
std::cout << visible << std::endl;
return 0;
}
@@ -210,6 +263,7 @@
ndn::ndns::NdnsDig dig("", dstLabel, ndn::name::Component(rrType));
dig.setInterestLifetime(ndn::time::milliseconds(ttl * 1000));
+ dig.setDstFile(dstFile);
dig.run();
if (dig.hasError())
diff --git a/tools/ndns-update.cpp b/tools/ndns-update.cpp
index bb08adf..6caf991 100644
--- a/tools/ndns-update.cpp
+++ b/tools/ndns-update.cpp
@@ -76,6 +76,7 @@
<< " with rrLabel = " << this->m_update.getRrLabel()
<< " and rrType = " << this->m_rrType
<< " =================================== ");
+ NDNS_LOG_INFO("certificate to sign the data is: " << m_certName);
Interest interest = this->makeUpdateInterest();
NDNS_LOG_TRACE("[* <- *] send Update: " << m_update);
@@ -210,6 +211,12 @@
return m_hasError;
}
+ const Response&
+ getUpdate() const
+ {
+ return m_update;
+ }
+
private:
name::Component m_queryType; ///< NDNS or KEY
name::Component m_rrType;
@@ -245,8 +252,9 @@
string rrType = "TXT";
string ndnsTypeStr = "resp";
Name certName;
- string content;
+ std::vector<string> contents;
string contentFile;
+ string dstFile;
ndn::Block block;
try {
namespace po = boost::program_options;
@@ -263,7 +271,8 @@
("ndnsType,n", po::value<string>(&ndnsTypeStr), "Set the ndnsType of the resource record. "
"Potential values are [resp|nack|auth|raw]. Default: resp")
("cert,c", po::value<Name>(&certName), "set the name of certificate to sign the update")
- ("content,o", po::value<string>(&content), "set the content of the RR")
+ ("content,o", po::value<std::vector<string>>(&contents)->multitoken(),
+ "set the content of the RR")
("contentFile,f", po::value<string>(&contentFile), "set the path of file which contain"
" content of the RR in base64 format")
;
@@ -293,7 +302,7 @@
po::notify(vm);
if (vm.count("help")) {
- std::cout << "Usage: ndns-update zone rrLabel [-t rrType] [-w waitingSec] "
+ std::cout << "Usage: ndns-update zone rrLabel [-t rrType] [-T TTL] "
"[-H hint] [-n NdnsType] [-c cert] [-f contentFile]|[-o content]" << std::endl;
std::cout << visible << std::endl;
return 0;
@@ -301,7 +310,22 @@
KeyChain keyChain;
if (certName.empty()) {
- certName = keyChain.getDefaultCertificateName().toUri();
+ Name name = Name().append(zone).append(rrLabel);
+ // choosing the longest match of the identity who also have default certificate
+ for (size_t i = name.size() + 1; i > 0; --i) { // i >=0 will present warnning
+ Name tmp = name.getPrefix(i - 1);
+ if (keyChain.doesIdentityExist(tmp)) {
+ try {
+ certName = keyChain.getDefaultCertificateNameForIdentity(tmp);
+ break;
+ }
+ catch (std::exception&) {
+ // If it cannot get a default certificate from one identity,
+ // just ignore this one try next identity.
+ ;
+ }
+ }
+ }
}
else {
if (!keyChain.doesCertificateExist(certName)) {
@@ -310,8 +334,13 @@
}
}
+ if (certName.empty()) {
+ std::cerr << "cannot figure out the certificate automatically. "
+ << "please set it with -c CERT_NAEME" << std::endl;
+ }
+
if (vm.count("content") && vm.count("contentFile")) {
- std::cerr <<"both content and contentFile are set. Only one is allowed" << std::endl;
+ std::cerr << "both content and contentFile are set. Only one is allowed" << std::endl;
return 0;
}
@@ -319,10 +348,6 @@
shared_ptr<ndn::Data> data = ndn::io::load<ndn::Data>(contentFile);
block = data->wireEncode();
}
- else {
- if (!content.empty())
- block = ndn::dataBlock(ndn::ndns::tlv::RrData, content.c_str(), content.size());
- }
}
catch (const std::exception& ex) {
std::cerr << "Parameter Error: " << ex.what() << std::endl;
@@ -336,11 +361,27 @@
ndnsType, certName, face);
update.setInterestLifetime(ndn::time::seconds(ttl));
- if (!block.empty()) {
- if (ndnsType == ndn::ndns::NDNS_RAW)
- update.setUpdateAppContent(block);
- else
- update.addUpdateRr(block);
+ if (!contentFile.empty()) {
+ if (!block.empty()) {
+ if (ndnsType == ndn::ndns::NDNS_RAW)
+ update.setUpdateAppContent(block);
+ else {
+ update.addUpdateRr(block);
+ }
+ }
+ }
+ else {
+ if (ndnsType == ndn::ndns::NDNS_RAW) {
+ // since NDNS_RAW's message tlv type cannot be decided, here we stop this option
+ std::cerr << "--content (-o) does not support NDNS-RAW Response" << std::endl;
+ return 0;
+ }
+ else {
+ for (const auto& content : contents) {
+ block = ndn::dataBlock(ndn::ndns::tlv::RrData, content.c_str(), content.size());
+ update.addUpdateRr(block);
+ }
+ }
}
update.run();