00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef DNS_H
00014 #define DNS_H
00015
00016 namespace DNS
00017 {
00020 enum QueryType
00021 {
00022
00023 QUERY_NONE,
00024
00025 QUERY_A = 1,
00026
00027 QUERY_NS = 2,
00028
00029 QUERY_CNAME = 5,
00030
00031 QUERY_SOA = 6,
00032
00033 QUERY_PTR = 12,
00034
00035 QUERY_AAAA = 28,
00036
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
00138 bool use_cache;
00139
00140 unsigned short id;
00141
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 }
00175
00176 #endif // DNS_H
00177
00178