17#define DNS_REPARSE_TIME 60
19#define DNS_OPTION_SEARCH 1
20#define DNS_OPTION_NAMESERVERS 2
21#define DNS_OPTION_MISC 4
22#define DNS_OPTIONS_ALL 7
27#define DNS_ERR_FORMAT 1
29#define DNS_ERR_SERVERFAILED 2
31#define DNS_ERR_NOTEXIST 3
33#define DNS_ERR_NOTIMPL 4
35#define DNS_ERR_REFUSED 5
37#define DNS_ERR_UNKNOWN 16
39#define DNS_ERR_TRUNCATED 17
50struct search_list_imp;
54typedef ref_ptr<packet_imp> packet;
55typedef ref_ptr<reply_imp> reply;
56typedef ref_ptr<search_list_imp> search_list;
57typedef ref_ptr<request_imp> request;
58typedef ref_ptr<nameserver_imp> nameserver;
67packet make_packet(
size_t size);
68packet make_packet(uint8_t * buf,
size_t size);
69reply make_reply(packet p);
70search_list make_search_list(
int ndots);
71request make_request_a(std::string name,
bool search =
false, search_list s = search_list());
72request make_request_ptr(
struct in_addr *in);
73nameserver make_nameserver(uint32_t addr,
int port = 53);
75class packet_imp :
public enable_ref_ptr_with_full_release<packet_imp> {
77 struct _strlen_t {
int len; _strlen_t(
int l) : len(l) {}};
80 typedef void (packet_imp::*unspecified_bool_type)()
const;
81 void unspecified_method()
const {}
89 void expand() {
if (_off > _fill) _fill = _off; }
92 packet_imp(
size_t size);
93 packet_imp(uint8_t * buf,
size_t size);
96 operator unspecified_bool_type()
const;
98 static _strlen_t set_strlen(
int len);
99 packet_imp &operator>>(_strlen_t _strlen);
100 packet_imp &operator<<(_strlen_t _strlen);
103 ssize_t size()
const;
104 off_t offset()
const;
105 packet_imp &operator+=(
unsigned int p);
107 const uint8_t * getbuf()
const;
109 packet_imp &operator>>(uint8_t &val);
110 packet_imp &operator>>(uint16_t &val);
111 packet_imp &operator>>(uint32_t &val);
112 packet_imp &operator>>(
struct in_addr &val);
113 packet_imp &operator>>(std::string &val);
115 packet_imp &operator<<(uint8_t val);
116 packet_imp &operator<<(uint16_t val);
117 packet_imp &operator<<(uint32_t val);
118 packet_imp &operator<<(std::string val);
121inline packet make_packet(
size_t size) {
122 return packet(
new packet_imp(size));
125inline packet make_packet(uint8_t * buf,
size_t size) {
126 return packet(
new packet_imp(buf, size));
129inline packet_imp::packet_imp(
size_t size)
130 : _off(0), _fill(0), _max(size), _buf(new uint8_t[size]), _strlen(_strlen_t(-1)) {
131 memset(_buf, 0, size);
134inline packet_imp::packet_imp(uint8_t * buf,
size_t size)
135 : _off(0), _fill(size), _max(size), _buf(new uint8_t[size]), _strlen(_strlen_t(-1)) {
136 memcpy(_buf, buf, size);
139inline packet_imp::operator unspecified_bool_type()
const {
140 return (_off > _max || _fill > _max) ? 0 : &packet_imp::unspecified_method;
143inline void packet_imp::full_release() {
147inline packet_imp::_strlen_t packet_imp::set_strlen(
int len) {
148 return _strlen_t(len);
151inline packet_imp &packet_imp::operator>>(_strlen_t s) {
156inline packet_imp &packet_imp::operator<<(_strlen_t s) {
160inline void packet_imp::reset() {
164inline ssize_t packet_imp::size()
const {
168inline off_t packet_imp::offset()
const {
172inline packet_imp &packet_imp::operator+=(
unsigned int p) {
178inline const uint8_t * packet_imp::getbuf()
const {
182inline packet_imp &packet_imp::operator>>(uint8_t &val) {
184 _off +=
sizeof(uint8_t);
188inline packet_imp &packet_imp::operator>>(uint16_t &val) {
189 val = htons(*(uint16_t *)&_buf[_off]);
190 _off +=
sizeof(uint16_t);
194inline packet_imp &packet_imp::operator>>(uint32_t &val) {
195 val = htonl(*(uint32_t *)&_buf[_off]);
196 _off +=
sizeof(uint32_t);
200inline packet_imp &packet_imp::operator>>(
struct in_addr &val) {
201 val.s_addr = *(uint32_t *)&_buf[_off];
202 _off +=
sizeof(uint32_t);
206inline packet_imp &packet_imp::operator>>(std::string &val) {
207 if (_strlen.len < 0) {
208 val = std::string((
char *)&_buf[_off]);
209 _off += val.length() + 1;
211 val = std::string((
char *)&_buf[_off], _strlen.len);
218inline packet_imp &packet_imp::operator<<(uint8_t val) {
220 _off +=
sizeof(uint8_t);
226inline packet_imp &packet_imp::operator<<(uint16_t val) {
227 *(uint16_t *)&_buf[_off] = htons(val);
228 _off +=
sizeof(uint16_t);
234inline packet_imp &packet_imp::operator<<(uint32_t val) {
235 *(uint32_t *)&_buf[_off] = htonl(val);
236 _off +=
sizeof(uint32_t);
242inline packet_imp &packet_imp::operator<<(std::string val) {
243 if (_strlen.len < 0) {
244 strcpy((
char *)&_buf[_off], val.c_str());
245 _off += val.length();
247 memcpy(&_buf[_off], val.c_str(), _strlen.len);
256struct reply_imp :
public enable_ref_ptr {
258 typedef void (reply_imp::*unspecified_bool_type)()
const;
259 void unspecified_method()
const {};
265 std::vector<uint32_t> addrs;
269 operator unspecified_bool_type()
const;
272 static int skip_name(ref_ptr<packet_imp> &p);
275inline reply make_reply(packet p) {
276 return reply(
new reply_imp(p));
279inline reply_imp::operator unspecified_bool_type()
const {
280 return (err) ? 0 : &reply_imp::unspecified_method;
283inline int reply_imp::skip_name(ref_ptr<packet_imp> &p) {
289 if (len & 0xC0){ *p += 1;
break; }
290 if (len > 63)
return -1;
297struct search_list_imp :
public enable_ref_ptr {
299 std::list<std::string> domains;
300 search_list_imp(
int n) : ndots(n) {}
303inline search_list make_search_list(
int ndots) {
304 return search_list(
new search_list_imp(ndots));
307class request_imp :
public enable_ref_ptr {
308 typedef void (request_imp::*unspecified_bool_type)()
const;
309 void unspecified_method()
const {}
319 std::string _curr_name;
322 request_imp(uint16_t type);
323 virtual ~request_imp() {};
324 operator unspecified_bool_type()
const;
326 int tx_count()
const;
327 uint16_t trans_id()
const;
329 virtual bool hasnext()
const = 0;
330 virtual void next(uint16_t trans_id) = 0;
331 void reissue(uint16_t trans_id);
333 int getpacket(packet &p,
bool tcp =
false);
336inline request_imp::request_imp(uint16_t type)
337 : _type(type), _err(-1), _tx_count(0), _sent_raw(0), _trans_id(0xFFFF) {
340inline request_imp::operator unspecified_bool_type()
const {
341 return (_err) ? 0 : &request_imp::unspecified_method;
344inline int request_imp::error()
const {
348inline int request_imp::tx_count()
const {
352inline uint16_t request_imp::trans_id()
const {
356inline void request_imp::reissue(uint16_t trans_id) {
357 _trans_id = trans_id;
361class request_a :
public request_imp {
367 std::list<std::string>::const_iterator _doms_it;
369 static bool check_name(std::string name);
372 request_a(std::string name,
bool search =
false, search_list s = search_list());
374 bool hasnext()
const;
375 void next(uint16_t trans_id);
378inline request make_request_a(std::string name,
bool search, search_list s) {
379 return request(
new request_a(name, search, s));
382inline request_a::request_a(std::string name,
bool search, search_list s)
383 : request_imp(TYPE_A), _search(search), _name(name), _ndots(0), _s(s) {
385 if ((_err = check_name(name) ? 0 : -1))
389 _doms_it = _s->domains.begin();
390 for (
int i = name.find(
'.', 0); i >= 0; i = name.find(
'.', i + 1))
395inline bool request_a::hasnext()
const {
396 return (!_sent_raw || (_search && _doms_it != _s->domains.end())) ? 1 : 0;
399inline bool request_a::check_name(std::string name) {
401 if (name.size() > 255)
403 for (
size_t p = name.find(
'.'); p != std::string::npos; i = p + 1, p = name.find(
'.', i))
406 if (name.size() - i > 63)
411class request_ptr :
public request_imp {
413 request_ptr(
struct in_addr * addr);
415 bool hasnext()
const;
416 void next(uint16_t trans_id);
419inline request make_request_ptr(
struct in_addr *in) {
420 return request(
new request_ptr(in));
423inline request_ptr::request_ptr(
struct in_addr * addr) : request_imp(TYPE_PTR) {
424 std::ostringstream s;
429 a = ntohl(addr->s_addr);
430 s << (int)((a )&0xff) <<
"." <<
431 (int)((a>>8 )&0xff) <<
"." <<
432 (int)((a>>16)&0xff) <<
"." <<
433 (int)((a>>24)&0xff) <<
".in-addr.arpa";
434 _curr_name = s.str();
437inline bool request_ptr::hasnext()
const {
442 :
public enable_ref_ptr_with_full_release<nameserver_imp> {
445 std::list<reply> received;
449 typedef void (nameserver_imp::*unspecified_bool_type)()
const;
450 void unspecified_method()
const {}
455 std::list<packet> _tcp_outgoing;
462 nameserver_imp(uint32_t addr,
int port);
464 operator unspecified_bool_type()
const;
465 bool operator< (
const nameserver_imp &n2)
const;
467 void full_release() {
468 if (ready) ready.trigger(-1);
469 if (_udp) _udp.close();
470 if (_tcp) _tcp.close();
476 printf(
"ns: %s\n", inet_ntoa(ina));
479 void init(event<int> e);
480 void init_tcp(event<int> e, timeval timeout);
481 void query(packet p);
482 void query_tcp(packet p, timeval timeout);
485 class closure__init__Qi_;
486 void init(closure__init__Qi_ &);
488 class closure__init_tcp__Qi_7timeval;
489 void init_tcp(closure__init_tcp__Qi_7timeval &);
491 class closure__query__6packet;
492 void query(closure__query__6packet&);
494 class closure__query_tcp__6packet7timeval;
495 void query_tcp(closure__query_tcp__6packet7timeval&);
498class nameserver_comp {
500 bool operator() (
const nameserver &n1,
const nameserver &n2)
const {
505typedef std::set<nameserver, nameserver_comp> nameservers;
507inline nameserver make_nameserver(uint32_t addr,
int port) {
508 return nameserver(
new nameserver_imp(addr, port));
511inline nameserver_imp::nameserver_imp(uint32_t addr,
int port)
512 : timeouts(0), _addr(addr), _port(port), _tcp_outbound(0) {
515inline nameserver_imp::operator unspecified_bool_type()
const {
516 return (!_udp) ? 0 : &nameserver_imp::unspecified_method;
519inline bool nameserver_imp::operator< (
const nameserver_imp &n)
const {
520 return _addr < n._addr || (_addr == n._addr && _port < n._port);
528 query() : q(), p() {}
529 query(request q, event<reply> p) : q(q), p(p) {}
530 operator uint16_t() {
return q->trans_id(); }
533class resolver :
public enable_ref_ptr_with_full_release<resolver> {
534 typedef void (resolver::*unspecified_bool_type)()
const;
535 void unspecified_method()
const {}
542 int _max_retransmits;
544 int _max_reqs_inflight;
545 search_list _search_list;
551 std::map<uint16_t, query> _requests;
553 nameservers _nameservers;
555 nameservers::iterator _nsindex;
561 uint16_t get_trans_id();
563 void resolve(request q, event<reply> e);
565 void add_nameservers(nameservers n, event<>);
566 void handle_nameserver(nameserver n);
567 void failed_nameserver(nameserver n);
568 nameserver next_nameserver();
573 void set_default(event<> e);
574 void set_default_options();
575 void set_option(
const char * option);
576 void set_from_hostname();
577 void add_domain(
const char * name);
579 static int strtoint(
const char * val,
int min,
int max);
580 static char * next_line(
char *buf);
582 class closure__ready__Q_;
583 void ready(closure__ready__Q_&);
585 class closure__parse_loop;
586 void parse_loop(closure__parse_loop&);
588 class closure__parse;
589 void parse(closure__parse&);
591 class closure__resolve__7requestQ5reply_;
592 void resolve(closure__resolve__7requestQ5reply_&);
594 class closure__add_nameservers__11nameserversQ_;
595 void add_nameservers(closure__add_nameservers__11nameserversQ_&);
597 class closure__failed_nameserver__10nameserver;
598 void failed_nameserver(closure__failed_nameserver__10nameserver&);
600 class closure__handle_nameserver__10nameserver;
601 void handle_nameserver(closure__handle_nameserver__10nameserver&);
603#if defined(HOST_NAME_MAX)
604 enum { host_name_max = HOST_NAME_MAX };
605#elif defined(_POSIX_HOST_NAME_MAX)
606 enum { host_name_max = _POSIX_HOST_NAME_MAX };
608 enum { host_name_max = 255 };
612 resolver(
int flags, std::string rc =
"/etc/resolv.conf");
614 operator unspecified_bool_type()
const;
617 void ready(event<> e);
618 void resolve_a(std::string name,
bool search, event<reply> e);
619 void resolve_ptr(
struct in_addr *in, event<reply> e);
624inline resolver::resolver(
int flags, std::string rc)
625 : _rcname(rc), _flags(flags), _err(0), _reqs_inflight(0),
626 _fst(), _nsindex(_nameservers.begin()), _is_init(false) {
628 set_default_options();
629 gettimeofday(&tv, NULL);
634inline resolver::operator unspecified_bool_type()
const {
635 return (_err) ? 0 : &resolver::unspecified_method;
638inline int resolver::error()
const {
642inline void resolver::resolve_a(std::string name,
bool search, event<reply> e) {
645 q = make_request_a(name, search, _search_list);
652inline void resolver::resolve_ptr(
struct in_addr *in, event<reply> e) {
655 q = make_request_ptr(in);
659inline void resolver::full_release() {
660 _nameservers.clear();
662 for (std::map<uint16_t, query >::iterator i = _requests.begin();
663 i != _requests.end(); i++)
664 i->second.p.trigger(reply());
668inline nameserver resolver::next_nameserver() {
670 assert(_nameservers.size());
671 if (_nsindex == _nameservers.end())
672 _nsindex = _nameservers.begin();
679inline void resolver::set_default_options() {
682 _timeout.tv_usec = 0;
683 _max_retransmits = 1;
685 _max_reqs_inflight = 64;
688inline void resolver::set_from_hostname() {
689 char hostname[host_name_max + 1];
692 _search_list = make_search_list(_ndots);
693 if (gethostname(hostname,
sizeof(hostname)))
return;
694 domainname = strchr(hostname,
'.');
695 if (!domainname)
return;
696 add_domain(domainname);
699inline void resolver::add_domain(
const char * name) {
700 assert(_search_list);
701 _search_list->domains.push_back(name);
704inline int resolver::strtoint(
const char * val,
int min,
int max) {
706 int r = strtol(val, &end, 10);
718inline char* resolver::next_line(
char * buf) {
720 return (r = strchr(buf,
'\n')) ? (*r = 0) + r + 1 : 0;
A future occurrence.
Definition event.hh:116
Event-based file descriptor wrapper class.
Namespace containing public Tamer classes and functions for the Tamer core.
Definition adapter.hh:17
The main Tamer header file.