Skip to content

Commit 26958c3

Browse files
fixed searchpath based dns lookups
1 parent 3acb53e commit 26958c3

File tree

3 files changed

+72
-25
lines changed

3 files changed

+72
-25
lines changed

include/dnscpp/context.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ class SearchLookupHandler;
3838
*/
3939
class Context : private Core
4040
{
41+
private:
42+
/**
43+
* Should the search path be respected?
44+
* @param domain the domain to lookup
45+
* @param handler handler that is already in use
46+
* @return bool
47+
*/
48+
bool searchable(const char *domain, DNS::Handler *handler) const;
49+
4150
public:
4251
/**
4352
* Constructor

src/context.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,33 @@ void Context::capacity(size_t value)
4242
_capacity = std::min((size_t)IdGenerator::capacity(), std::max(size_t(1), value));
4343
}
4444

45+
/**
46+
* Should the search path be respected?
47+
* @param domain the domain to lookup
48+
* @param handler handler that is already in use
49+
* @return bool
50+
*/
51+
bool Context::searchable(const char *domain, DNS::Handler *handler) const
52+
{
53+
// length of the lookup
54+
size_t length = strlen(domain);
55+
56+
// empty domains fail anyway
57+
if (length == 0) return false;
58+
59+
// canonical domains don't go into recursion
60+
if (domain[length-1] == '.') return false;
61+
62+
// count the dots
63+
size_t ndots = std::count(domain, domain + length + 1, '.');
64+
65+
// compare with the 'ndots' setting
66+
if (ndots >= _ndots) return false;
67+
68+
// do not do recursion (if the current handler already is a SearchLookup)
69+
return dynamic_cast<SearchLookup*>(handler) == nullptr;
70+
}
71+
4572
/**
4673
* Do a dns lookup
4774
* @param domain the record name to look for
@@ -52,13 +79,9 @@ void Context::capacity(size_t value)
5279
*/
5380
Operation *Context::query(const char *domain, ns_type type, const Bits &bits, DNS::Handler *handler)
5481
{
55-
// count the dots
56-
size_t ndots = std::count(domain, domain + strlen(domain) + 1, '.');
57-
58-
// if the searchpath contains less then ndots dots, and we are not already wrapped
59-
// we wrap the call in a searchlookuphandler, to retry the call with the appended searchpaths
60-
if (!dynamic_cast<SearchLookup*>(handler) && ndots < _ndots && !_searchpaths.empty()) return new SearchLookup(this, type, bits, domain, handler);
61-
82+
// check if we should respect the search path
83+
if (searchable(domain, handler)) return new SearchLookup(this, type, bits, domain, handler);
84+
6285
// for A and AAAA lookups we also check the /etc/hosts file
6386
if (type == ns_t_a && _hosts.lookup(domain, 4)) return add(new LocalLookup(this, _hosts, domain, type, handler));
6487
if (type == ns_t_aaaa && _hosts.lookup(domain, 6)) return add(new LocalLookup(this, _hosts, domain, type, handler));
@@ -76,6 +99,8 @@ Operation *Context::query(const char *domain, ns_type type, const Bits &bits, DN
7699
}
77100
}
78101

102+
103+
79104
/**
80105
* Do a reverse IP lookup, this is only meaningful for PTR lookups
81106
* @param ip the ip address to lookup

src/searchlookup.h

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -122,38 +122,51 @@ class SearchLookup : public DNS::Operation, public DNS::Handler
122122
*/
123123
bool proceed()
124124
{
125+
// do nothing if we already have exhausted all calls
126+
if (_index == size_t(-1)) return false;
127+
125128
// shortcut to the search-paths
126129
const auto &searchpaths = _context->searchpaths();
127130

128131
// if there are no more paths left, return false
129-
if (_index >= searchpaths.size()) return false;
132+
if (_index >= searchpaths.size()) return finalize();
130133

131134
// the next path to check
132135
const auto &nextdomain = searchpaths[_index++];
133136

134137
// for empty domains we do not need to concatenate
135-
if (nextdomain.empty())
136-
{
137-
// start a lookup for just the requested domain
138-
_operation = _context->query(_basedomain.c_str(), _type, _bits, this);
139-
}
140-
else
141-
{
142-
// create a string to hold the next domain, and fill it with the user-domain
143-
std::string nextdomain(_basedomain);
144-
145-
// add a . and the searchpath
146-
nextdomain.append(".").append(nextdomain);
147-
148-
// perform dns-query on the constructed path
149-
// and save the operation so we can cancell it if requested
150-
_operation = _context->query(nextdomain.c_str(), _type, _bits, this);
151-
}
138+
if (nextdomain.empty()) return finalize();
139+
140+
// create a string to hold the next domain, and fill it with the user-domain
141+
std::string nexthost(_basedomain);
142+
143+
// add a . and the searchpath
144+
nexthost.append(".").append(nextdomain);
145+
146+
// perform dns-query on the constructed path
147+
// and save the operation so we can cancell it if requested
148+
_operation = _context->query(nexthost.c_str(), _type, _bits, this);
152149

153150
// return success
154151
return true;
155152
}
156153

154+
/**
155+
* Do the ultimate, final lookup
156+
* @return bool
157+
*/
158+
bool finalize()
159+
{
160+
// start a lookup for just the requested domain
161+
_operation = _context->query(_basedomain.c_str(), _type, _bits, this);
162+
163+
// update index to prevent loops
164+
_index = size_t(-1);
165+
166+
// still busy
167+
return true;
168+
}
169+
157170
/**
158171
* Private destructor because this is a self-destructing object
159172
*/

0 commit comments

Comments
 (0)