From dcd34d37287adb6aa03d32edd17fc8015b52feb8 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 15 Dec 2012 01:33:31 -0500 Subject: Move DNS handling to a module --- modules/extra/dns.h | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 modules/extra/dns.h (limited to 'modules/extra/dns.h') diff --git a/modules/extra/dns.h b/modules/extra/dns.h new file mode 100644 index 000000000..9d141249b --- /dev/null +++ b/modules/extra/dns.h @@ -0,0 +1,178 @@ +/* + * + * (C) 2003-2012 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + */ + +#ifndef DNS_H +#define DNS_H + +namespace DNS +{ + /** Valid query types + */ + enum QueryType + { + /* Nothing */ + QUERY_NONE, + /* A simple A lookup */ + QUERY_A = 1, + /* An authoritative name server */ + QUERY_NS = 2, + /* A CNAME lookup */ + QUERY_CNAME = 5, + /* Start of a zone of authority */ + QUERY_SOA = 6, + /* Reverse DNS lookup */ + QUERY_PTR = 12, + /* IPv6 AAAA lookup */ + QUERY_AAAA = 28, + /* Zone transfer */ + QUERY_AXFR = 252 + }; + + /** Flags that can be AND'd into DNSPacket::flags to receive certain values + */ + enum + { + QUERYFLAGS_QR = 0x8000, + QUERYFLAGS_OPCODE = 0x7800, + QUERYFLAGS_AA = 0x400, + QUERYFLAGS_TC = 0x200, + QUERYFLAGS_RD = 0x100, + QUERYFLAGS_RA = 0x80, + QUERYFLAGS_Z = 0x70, + QUERYFLAGS_RCODE = 0xF + }; + + enum Error + { + ERROR_NONE, + ERROR_UNKNOWN, + ERROR_UNLOADED, + ERROR_TIMEOUT, + ERROR_NOT_AN_ANSWER, + ERROR_NONSTANDARD_QUERY, + ERROR_FORMAT_ERROR, + ERROR_SERVER_FAILURE, + ERROR_DOMAIN_NOT_FOUND, + ERROR_NOT_IMPLEMENTED, + ERROR_REFUSED, + ERROR_NO_RECORDS, + ERROR_INVALIDTYPE + }; + + struct Question + { + Anope::string name; + QueryType type; + unsigned short qclass; + + Question() : type(QUERY_NONE), qclass(0) { } + Question(const Anope::string &n, QueryType t, unsigned short c = 1) : name(n), type(t), qclass(c) { } + }; + + struct ResourceRecord : public Question + { + unsigned int ttl; + Anope::string rdata; + time_t created; + + ResourceRecord(const Anope::string &n, QueryType t, unsigned short c = 1) : Question(n, t, c), ttl(0), created(Anope::CurTime) { } + ResourceRecord(const Question &q) : Question(q), ttl(0), created(Anope::CurTime) { } + }; + + struct Query + { + std::vector questions; + std::vector answers, authorities, additional; + Error error; + + Query() : error(ERROR_NONE) { } + Query(const Question &q) : error(ERROR_NONE) { questions.push_back(q); } + }; + + class Packet : public Query + { + public: + static const int POINTER = 0xC0; + static const int LABEL = 0x3F; + static const int HEADER_LENGTH = 12; + + virtual ~Packet() { } + }; + + class ReplySocket; + class Request; + + /** DNS manager + */ + class Manager : public Service + { + public: + Manager(Module *creator) : Service(creator, "DNS::Manager", "dns/manager") { } + virtual ~Manager() { } + + virtual void Process(Request *req) = 0; + virtual void RemoveRequest(Request *req) = 0; + + virtual bool HandlePacket(ReplySocket *s, const unsigned char *const data, int len, sockaddrs *from) = 0; + + virtual void UpdateSerial() = 0; + virtual uint32_t GetSerial() const = 0; + }; + + /** A DNS query. + */ + class Request : public Timer, public Question + { + Manager *manager; + public: + /* Use result cache if available */ + bool use_cache; + /* Request id */ + unsigned short id; + /* Creator of this request */ + Module *creator; + + Request(Manager *mgr, Module *c, const Anope::string &addr, QueryType qt, bool cache = false) : Timer(0), Question(addr, qt), manager(mgr), + use_cache(cache), id(0), creator(c) { } + + virtual ~Request() + { + manager->RemoveRequest(this); + } + + /** Called when this request succeeds + * @param r The query sent back from the nameserver + */ + virtual void OnLookupComplete(const Query *r) = 0; + + /** Called when this request fails or times out. + * @param r The query sent back from the nameserver, check the error code. + */ + virtual void OnError(const Query *r) { } + + /** Used to time out the query, xalls OnError and lets the TimerManager + * delete this request. + */ + void Tick(time_t) anope_override + { + Log(LOG_DEBUG_2) << "Resolver: timeout for query " << this->name; + Query rr(*this); + rr.error = ERROR_TIMEOUT; + this->OnError(&rr); + } + }; + +} // namespace DNS + +#endif // DNS_H + + -- cgit