base-dns.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "base-dns.hpp"
27 
28 #include <sys/types.h>
29 #include <netinet/in.h>
30 #include <resolv.h>
31 #include <arpa/nameser.h>
32 
33 #ifdef __APPLE__
34 #include <arpa/nameser_compat.h>
35 #endif
36 
37 namespace ndn {
38 namespace tools {
39 namespace autoconfig {
40 
41 union BaseDns::QueryAnswer
42 {
43  HEADER header;
44  uint8_t buf[NS_PACKETSZ];
45 };
46 
47 BaseDns::BaseDns(Face& face, KeyChain& keyChain, const NextStageCallback& nextStageOnFailure)
48  : Base(face, keyChain, nextStageOnFailure)
49 {
50 }
51 
52 std::string
53 BaseDns::querySrvRr(const std::string& fqdn)
54 {
55  std::string srvDomain = "_ndn._udp." + fqdn;
56  std::cerr << "Sending DNS query for SRV record for " << srvDomain << std::endl;
57 
58  res_init();
59 
60  _res.retrans = 1;
61  _res.retry = 2;
62  _res.ndots = 10;
63 
64  QueryAnswer queryAnswer;
65  int answerSize = res_query(srvDomain.c_str(),
66  ns_c_in,
67  ns_t_srv,
68  queryAnswer.buf,
69  sizeof(queryAnswer));
70  if (answerSize == 0) {
71  BOOST_THROW_EXCEPTION(Error("No DNS SRV records found for " + srvDomain));
72  }
73  return parseSrvRr(queryAnswer, answerSize);
74 }
75 
79 std::string
81 {
82  std::cerr << "Sending DNS query for SRV record for _ndn._udp" << std::endl;
83 
84  QueryAnswer queryAnswer;
85 
86  res_init();
87 
88  _res.retrans = 1;
89  _res.retry = 2;
90  _res.ndots = 10;
91 
92  int answerSize = res_search("_ndn._udp",
93  ns_c_in,
94  ns_t_srv,
95  queryAnswer.buf,
96  sizeof(queryAnswer));
97 
98  if (answerSize == 0) {
99  BOOST_THROW_EXCEPTION(Error("No DNS SRV records found for _ndn._udp"));
100  }
101 
102  return parseSrvRr(queryAnswer, answerSize);
103 }
104 
105 std::string
106 BaseDns::parseSrvRr(const QueryAnswer& queryAnswer, int answerSize)
107 {
108  // The references of the next classes are:
109  // http://www.diablotin.com/librairie/networking/dnsbind/ch14_02.htm
110 
111  struct rechdr
112  {
113  uint16_t type;
114  uint16_t iclass;
115  uint32_t ttl;
116  uint16_t length;
117  };
118 
119  struct srv_t
120  {
121  uint16_t priority;
122  uint16_t weight;
123  uint16_t port;
124  uint8_t* target;
125  };
126 
127  if (ntohs(queryAnswer.header.ancount) == 0) {
128  BOOST_THROW_EXCEPTION(Error("SRV record cannot be parsed"));
129  }
130 
131  const uint8_t* blob = queryAnswer.buf + NS_HFIXEDSZ;
132 
133  blob += dn_skipname(blob, queryAnswer.buf + answerSize) + NS_QFIXEDSZ;
134 
135  char srvName[NS_MAXDNAME];
136  int serverNameSize = dn_expand(queryAnswer.buf, // message pointer
137  queryAnswer.buf + answerSize, // end of message
138  blob, // compressed server name
139  srvName, // expanded server name
140  NS_MAXDNAME);
141  if (serverNameSize <= 0) {
142  BOOST_THROW_EXCEPTION(Error("SRV record cannot be parsed (error decoding domain name)"));
143  }
144 
145  const srv_t* server = reinterpret_cast<const srv_t*>(&blob[sizeof(rechdr)]);
146  uint16_t convertedPort = be16toh(server->port);
147 
148  blob += serverNameSize + NS_HFIXEDSZ + NS_QFIXEDSZ;
149 
150  char hostName[NS_MAXDNAME];
151  int hostNameSize = dn_expand(queryAnswer.buf, // message pointer
152  queryAnswer.buf + answerSize, // end of message
153  blob, // compressed host name
154  hostName, // expanded host name
155  NS_MAXDNAME);
156  if (hostNameSize <= 0) {
157  BOOST_THROW_EXCEPTION(Error("SRV record cannot be parsed (error decoding host name)"));
158  }
159 
160  std::string uri = "udp://";
161  uri.append(hostName);
162  uri.append(":");
163  uri.append(to_string(convertedPort));
164 
165  return uri;
166 }
167 
168 } // namespace autoconfig
169 } // namespace tools
170 } // namespace ndn
Copyright (c) 2014-2016, Regents of the University of California, Arizona Board of Regents...
Definition: nfd.hpp:35
std::string querySrvRr(const std::string &fqdn)
Send DNS SRV request for a fqdn fully qualified domain name.
Definition: base-dns.cpp:53
std::string querySrvRrSearch()
Send DNS SRV request using search domain list.
Definition: base-dns.cpp:80
std::function< void(const std::string &)> NextStageCallback
Callback to be called when the stage fails.
Definition: base.hpp:61
Base class for discovery stages.
Definition: base.hpp:45
BaseDns(Face &face, KeyChain &keyChain, const NextStageCallback &nextStageOnFailure)
Definition: base-dns.cpp:47