]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/modules/dns.h
Merge insp20
[user/henk/code/inspircd.git] / include / modules / dns.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2013 Adam <Adam@anope.org>
5  *   Copyright (C) 2003-2013 Anope Team <team@anope.org>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #pragma once
21
22 namespace DNS
23 {
24         /** Valid query types
25          */
26         enum QueryType
27         {
28                 /* Nothing */
29                 QUERY_NONE,
30                 /* A simple A lookup */
31                 QUERY_A = 1,
32                 /* A CNAME lookup */
33                 QUERY_CNAME = 5,
34                 /* Reverse DNS lookup */
35                 QUERY_PTR = 12,
36                 /* IPv6 AAAA lookup */
37                 QUERY_AAAA = 28
38         };
39
40         /** Flags that can be AND'd into DNSPacket::flags to receive certain values
41          */
42         enum
43         {
44                 QUERYFLAGS_QR = 0x8000,
45                 QUERYFLAGS_OPCODE = 0x7800,
46                 QUERYFLAGS_AA = 0x400,
47                 QUERYFLAGS_TC = 0x200,
48                 QUERYFLAGS_RD = 0x100,
49                 QUERYFLAGS_RA = 0x80,
50                 QUERYFLAGS_Z = 0x70,
51                 QUERYFLAGS_RCODE = 0xF
52         };
53
54         enum Error
55         {
56                 ERROR_NONE,
57                 ERROR_UNKNOWN,
58                 ERROR_UNLOADED,
59                 ERROR_TIMEDOUT,
60                 ERROR_NOT_AN_ANSWER,
61                 ERROR_NONSTANDARD_QUERY,
62                 ERROR_FORMAT_ERROR,
63                 ERROR_SERVER_FAILURE,
64                 ERROR_DOMAIN_NOT_FOUND,
65                 ERROR_NOT_IMPLEMENTED,
66                 ERROR_REFUSED,
67                 ERROR_NO_RECORDS,
68                 ERROR_INVALIDTYPE
69         };
70
71         const int PORT = 53;
72
73         /**
74          * The maximum value of a dns request id,
75          * 16 bits wide, 0xFFFF.
76          */
77         const int MAX_REQUEST_ID = 0xFFFF;
78
79         class Exception : public ModuleException
80         {
81          public:
82                 Exception(const std::string& message) : ModuleException(message) { }
83         };
84
85         struct Question
86         {
87                 std::string name;
88                 QueryType type;
89                 unsigned short qclass;
90
91                 Question() : type(QUERY_NONE), qclass(0) { }
92                 Question(const std::string& n, QueryType t, unsigned short c = 1) : name(n), type(t), qclass(c) { }
93                 inline bool operator==(const Question& other) const { return name == other.name && type == other.type && qclass == other.qclass; }
94
95                 struct hash
96                 {
97                         size_t operator()(const Question& question) const
98                         {
99                                 return irc::insensitive()(question.name);
100                         }
101                 };
102         };
103
104         struct ResourceRecord : Question
105         {
106                 unsigned int ttl;
107                 std::string rdata;
108                 time_t created;
109
110                 ResourceRecord(const std::string& n, QueryType t, unsigned short c = 1) : Question(n, t, c), ttl(0), created(ServerInstance->Time()) { }
111                 ResourceRecord(const Question& question) : Question(question), ttl(0), created(ServerInstance->Time()) { }
112         };
113
114         struct Query
115         {
116                 std::vector<Question> questions;
117                 std::vector<ResourceRecord> answers;
118                 Error error;
119                 bool cached;
120
121                 Query() : error(ERROR_NONE), cached(false) { }
122                 Query(const Question& question) : error(ERROR_NONE), cached(false) { questions.push_back(question); }
123         };
124
125         class ReplySocket;
126         class Request;
127
128         /** DNS manager
129          */
130         class Manager : public DataProvider
131         {
132          public:
133                 Manager(Module* mod) : DataProvider(mod, "DNS") { }
134
135                 virtual void Process(Request* req) = 0;
136                 virtual void RemoveRequest(Request* req) = 0;
137                 virtual std::string GetErrorStr(Error) = 0;
138         };
139
140         /** A DNS query.
141          */
142         class Request : public Timer, public Question
143         {
144          protected:
145                 Manager* const manager;
146          public:
147                 /* Use result cache if available */
148                 bool use_cache;
149                 /* Request id */
150                 unsigned short id;
151                 /* Creator of this request */
152                 Module* const creator;
153
154                 Request(Manager* mgr, Module* mod, const std::string& addr, QueryType qt, bool usecache = true)
155                         : Timer((ServerInstance->Config->dns_timeout ? ServerInstance->Config->dns_timeout : 5), ServerInstance->Time())
156                         , Question(addr, qt)
157                         , manager(mgr)
158                         , use_cache(usecache)
159                         , id(0)
160                         , creator(mod)
161                 {
162                         ServerInstance->Timers.AddTimer(this);
163                 }
164
165                 virtual ~Request()
166                 {
167                         manager->RemoveRequest(this);
168                 }
169
170                 /** Called when this request succeeds
171                  * @param r The query sent back from the nameserver
172                  */
173                 virtual void OnLookupComplete(const Query* req) = 0;
174
175                 /** Called when this request fails or times out.
176                  * @param r The query sent back from the nameserver, check the error code.
177                  */
178                 virtual void OnError(const Query* req) { }
179
180                 /** Used to time out the query, calls OnError and asks the TimerManager
181                  * to delete this request
182                  */
183                 bool Tick(time_t now)
184                 {
185                         Query rr(*this);
186                         rr.error = ERROR_TIMEDOUT;
187                         this->OnError(&rr);
188                         delete this;
189                         return false;
190                 }
191         };
192
193 } // namespace DNS