anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

dns.h (4137B)

      1 /*
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 #ifndef DNS_H
     13 #define DNS_H
     14 
     15 namespace DNS
     16 {
     17 	/** Valid query types
     18 	 */
     19 	enum QueryType
     20 	{
     21 		/* Nothing */
     22 		QUERY_NONE,
     23 		/* A simple A lookup */
     24 		QUERY_A = 1,
     25 		/* An authoritative name server */
     26 		QUERY_NS = 2,
     27 		/* A CNAME lookup */
     28 		QUERY_CNAME = 5,
     29 		/* Start of a zone of authority */
     30 		QUERY_SOA = 6,
     31 		/* Reverse DNS lookup */
     32 		QUERY_PTR = 12,
     33 		/* IPv6 AAAA lookup */
     34 		QUERY_AAAA = 28,
     35 		/* Zone transfer */
     36 		QUERY_AXFR = 252,
     37 		/* A lookup for any record */
     38 		QUERY_ANY = 255
     39 	};
     40 
     41 	/** Flags that can be AND'd into DNSPacket::flags to receive certain values
     42 	 */
     43 	enum
     44 	{
     45 		QUERYFLAGS_QR = 0x8000,
     46 		QUERYFLAGS_OPCODE = 0x7800,
     47 		QUERYFLAGS_OPCODE_NOTIFY = 0x2000,
     48 		QUERYFLAGS_AA = 0x400,
     49 		QUERYFLAGS_TC = 0x200,
     50 		QUERYFLAGS_RD = 0x100,
     51 		QUERYFLAGS_RA = 0x80,
     52 		QUERYFLAGS_Z = 0x70,
     53 		QUERYFLAGS_RCODE = 0xF
     54 	};
     55 
     56 	enum Error
     57 	{
     58 		ERROR_NONE,
     59 		ERROR_UNKNOWN,
     60 		ERROR_UNLOADED,
     61 		ERROR_TIMEDOUT,
     62 		ERROR_NOT_AN_ANSWER,
     63 		ERROR_NONSTANDARD_QUERY,
     64 		ERROR_FORMAT_ERROR,
     65 		ERROR_SERVER_FAILURE,
     66 		ERROR_DOMAIN_NOT_FOUND,
     67 		ERROR_NOT_IMPLEMENTED,
     68 		ERROR_REFUSED,
     69 		ERROR_NO_RECORDS,
     70 		ERROR_INVALIDTYPE
     71 	};
     72 
     73 	struct Question
     74 	{
     75 		Anope::string name;
     76 		QueryType type;
     77 		unsigned short qclass;
     78 
     79 		Question() : type(QUERY_NONE), qclass(0) { }
     80 		Question(const Anope::string &n, QueryType t, unsigned short c = 1) : name(n), type(t), qclass(c) { }
     81 		inline bool operator==(const Question & other) const { return name == other.name && type == other.type && qclass == other.qclass; }
     82 
     83 		struct hash
     84 		{
     85 			size_t operator()(const Question &q) const
     86 			{
     87 				return Anope::hash_ci()(q.name);
     88 			}
     89 		};
     90 	};
     91 
     92 	struct ResourceRecord : Question
     93 	{
     94 		unsigned int ttl;
     95 		Anope::string rdata;
     96 		time_t created;
     97 
     98 		ResourceRecord(const Anope::string &n, QueryType t, unsigned short c = 1) : Question(n, t, c), ttl(0), created(Anope::CurTime) { }
     99 		ResourceRecord(const Question &q) : Question(q), ttl(0), created(Anope::CurTime) { }
    100 	};
    101 
    102 	struct Query
    103 	{
    104 		std::vector<Question> questions;
    105 		std::vector<ResourceRecord> answers, authorities, additional;
    106 		Error error;
    107 
    108 		Query() : error(ERROR_NONE) { }
    109 		Query(const Question &q) : error(ERROR_NONE) { questions.push_back(q); }
    110 	};
    111 
    112 	class ReplySocket;
    113 	class Request;
    114 
    115 	/** DNS manager
    116 	 */
    117 	class Manager : public Service
    118 	{
    119 	 public:
    120 		Manager(Module *creator) : Service(creator, "DNS::Manager", "dns/manager") { }
    121 		virtual ~Manager() { }
    122 
    123 		virtual void Process(Request *req) = 0;
    124 		virtual void RemoveRequest(Request *req) = 0;
    125 
    126 		virtual bool HandlePacket(ReplySocket *s, const unsigned char *const data, int len, sockaddrs *from) = 0;
    127 
    128 		virtual void UpdateSerial() = 0;
    129 		virtual void Notify(const Anope::string &zone) = 0;
    130 		virtual uint32_t GetSerial() const = 0;
    131 	};
    132 
    133 	/** A DNS query.
    134 	 */
    135 	class Request : public Timer, public Question
    136 	{
    137 		Manager *manager;
    138 	 public:
    139 		/* Use result cache if available */
    140 		bool use_cache;
    141 		/* Request id */
    142 		unsigned short id;
    143 		/* Creator of this request */
    144 		Module *creator;
    145 
    146 		Request(Manager *mgr, Module *c, const Anope::string &addr, QueryType qt, bool cache = false) : Timer(0), Question(addr, qt), manager(mgr),
    147 			use_cache(cache), id(0), creator(c) { }
    148 
    149 		virtual ~Request()
    150 		{
    151 			manager->RemoveRequest(this);
    152 		}
    153 
    154 		/** Called when this request succeeds
    155 		 * @param r The query sent back from the nameserver
    156 		 */
    157 		virtual void OnLookupComplete(const Query *r) = 0;
    158 
    159 		/** Called when this request fails or times out.
    160 		 * @param r The query sent back from the nameserver, check the error code.
    161 		 */
    162 		virtual void OnError(const Query *r) { }
    163 
    164 		/** Used to time out the query, xalls OnError and lets the TimerManager
    165 		 * delete this request.
    166 		 */
    167 		void Tick(time_t) anope_override
    168 		{
    169 			Log(LOG_DEBUG_2) << "Resolver: timeout for query " << this->name;
    170 			Query rr(*this);
    171 			rr.error = ERROR_TIMEDOUT;
    172 			this->OnError(&rr);
    173 		}
    174 	};
    175 
    176 } // namespace DNS
    177 
    178 #endif // DNS_H