dns.h

Go to the documentation of this file.
00001 /*
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  *
00011  */
00012         
00013 #ifndef DNS_H
00014 #define DNS_H
00015 
00016 namespace DNS
00017 {
00020         enum QueryType
00021         {
00022                 /* Nothing */
00023                 QUERY_NONE,
00024                 /* A simple A lookup */
00025                 QUERY_A = 1,
00026                 /* An authoritative name server */
00027                 QUERY_NS = 2,
00028                 /* A CNAME lookup */
00029                 QUERY_CNAME = 5,
00030                 /* Start of a zone of authority */
00031                 QUERY_SOA = 6,
00032                 /* Reverse DNS lookup */
00033                 QUERY_PTR = 12,
00034                 /* IPv6 AAAA lookup */
00035                 QUERY_AAAA = 28,
00036                 /* Zone transfer */
00037                 QUERY_AXFR = 252
00038         };
00039         
00042         enum
00043         {
00044                 QUERYFLAGS_QR = 0x8000,
00045                 QUERYFLAGS_OPCODE = 0x7800,
00046                 QUERYFLAGS_AA = 0x400,
00047                 QUERYFLAGS_TC = 0x200,
00048                 QUERYFLAGS_RD = 0x100,
00049                 QUERYFLAGS_RA = 0x80,
00050                 QUERYFLAGS_Z = 0x70,
00051                 QUERYFLAGS_RCODE = 0xF
00052         };
00053         
00054         enum Error
00055         {
00056                 ERROR_NONE,
00057                 ERROR_UNKNOWN,
00058                 ERROR_UNLOADED,
00059                 ERROR_TIMEDOUT,
00060                 ERROR_NOT_AN_ANSWER,
00061                 ERROR_NONSTANDARD_QUERY,
00062                 ERROR_FORMAT_ERROR,
00063                 ERROR_SERVER_FAILURE,
00064                 ERROR_DOMAIN_NOT_FOUND,
00065                 ERROR_NOT_IMPLEMENTED,
00066                 ERROR_REFUSED,
00067                 ERROR_NO_RECORDS,
00068                 ERROR_INVALIDTYPE
00069         };
00070         
00071         struct Question
00072         {
00073                 Anope::string name;
00074                 QueryType type;
00075                 unsigned short qclass;
00076         
00077                 Question() : type(QUERY_NONE), qclass(0) { }
00078                 Question(const Anope::string &n, QueryType t, unsigned short c = 1) : name(n), type(t), qclass(c) { }
00079         };
00080         
00081         struct ResourceRecord : public Question
00082         {
00083                 unsigned int ttl;
00084                 Anope::string rdata;
00085                 time_t created;
00086         
00087                 ResourceRecord(const Anope::string &n, QueryType t, unsigned short c = 1) : Question(n, t, c), ttl(0), created(Anope::CurTime) { }
00088                 ResourceRecord(const Question &q) : Question(q), ttl(0), created(Anope::CurTime) { }
00089         };
00090         
00091         struct Query
00092         {
00093                 std::vector<Question> questions;
00094                 std::vector<ResourceRecord> answers, authorities, additional;
00095                 Error error;
00096         
00097                 Query() : error(ERROR_NONE) { }
00098                 Query(const Question &q) : error(ERROR_NONE) { questions.push_back(q); }
00099         };
00100 
00101         class Packet : public Query
00102         {
00103          public:
00104                 static const int POINTER = 0xC0;
00105                 static const int LABEL = 0x3F;
00106                 static const int HEADER_LENGTH = 12;
00107 
00108                 virtual ~Packet() { }
00109         };
00110 
00111         class ReplySocket;
00112         class Request;
00113 
00116         class Manager : public Service
00117         {
00118          public:
00119                 Manager(Module *creator) : Service(creator, "DNS::Manager", "dns/manager") { }
00120                 virtual ~Manager() { }
00121 
00122                 virtual void Process(Request *req) = 0;
00123                 virtual void RemoveRequest(Request *req) = 0;
00124         
00125                 virtual bool HandlePacket(ReplySocket *s, const unsigned char *const data, int len, sockaddrs *from) = 0;
00126         
00127                 virtual void UpdateSerial() = 0;
00128                 virtual uint32_t GetSerial() const = 0;
00129         };
00130         
00133         class Request : public Timer, public Question
00134         {
00135                 Manager *manager;
00136          public:
00137                 /* Use result cache if available */
00138                 bool use_cache;
00139                 /* Request id */
00140                 unsigned short id;
00141                 /* Creator of this request */
00142                 Module *creator;
00143 
00144                 Request(Manager *mgr, Module *c, const Anope::string &addr, QueryType qt, bool cache = false) : Timer(0), Question(addr, qt), manager(mgr),
00145                         use_cache(cache), id(0), creator(c) { }
00146                 
00147                 virtual ~Request()
00148                 {
00149                         manager->RemoveRequest(this);
00150                 }
00151         
00155                 virtual void OnLookupComplete(const Query *r) = 0;
00156         
00160                 virtual void OnError(const Query *r) { }
00161                 
00165                 void Tick(time_t) anope_override
00166                 {
00167                         Log(LOG_DEBUG_2) << "Resolver: timeout for query " << this->name;
00168                         Query rr(*this);
00169                         rr.error = ERROR_TIMEDOUT;
00170                         this->OnError(&rr);
00171                 }
00172         };
00173         
00174 } // namespace DNS
00175         
00176 #endif // DNS_H
00177         
00178