]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/dnsqueue.cpp
Whoops, forgot SocketEngine::SocketEngine() gets called recursively from *Engine...
[user/henk/code/inspircd.git] / src / dnsqueue.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "inspircd_config.h"
18 #include "inspircd.h"
19 #include "configreader.h"
20 #include <unistd.h>
21 #include <sys/errno.h>
22 #include <sys/ioctl.h>
23 #include <sys/utsname.h>
24 #include <string>
25 #include "users.h"
26 #include "globals.h"
27 #include "inspstring.h"
28 #include "dnsqueue.h"
29 #include "dns.h"
30 #include "helperfuncs.h"
31 #include "hashcomp.h"
32 #include "socketengine.h"
33 #include "socket.h"
34
35 extern ServerConfig* Config;
36 extern InspIRCd* ServerInstance;
37
38 class Lookup;
39
40 Lookup* dnslist[MAX_DESCRIPTORS];
41 Lookup* user_fd_to_dns[MAX_DESCRIPTORS];
42
43 //enum LookupState { reverse, forward };
44
45 class Lookup {
46 private:
47         char u[NICKMAX];
48         std::string hostname;
49 public:
50         DNS resolver1;
51         DNS resolver2;
52
53         Lookup()
54         {
55                 *u = 0;
56                 hostname = "";
57         }
58
59         void Reset()
60         {
61                 *u = 0;
62                 hostname = "";
63         }
64
65         ~Lookup()
66         {
67         }
68
69         bool DoLookup(std::string nick)
70         {
71                 hostname = "";
72                 userrec* usr = Find(nick);
73                 if (usr)
74                 {
75                         resolver1.SetNS(std::string(Config->DNSServer));
76                         if (!resolver1.ReverseLookup(std::string(usr->host), true))
77                         {
78                                 return false;
79                         }
80                         strlcpy(u,nick.c_str(),NICKMAX-1);
81
82                         /* ASSOCIATE WITH DNS LOOKUP LIST */
83                         if (resolver1.GetFD() != -1)
84                         {
85                                 dnslist[resolver1.GetFD()] = this;
86                                 user_fd_to_dns[usr->fd] = this;
87                                 return true;
88                         }
89                 }
90                 return false;
91         }
92
93         bool Done(int fdcheck)
94         {
95                 if (hostname != "")
96                 {
97                         // doing forward lookup
98                         userrec* usr = NULL;
99                         if (resolver2.HasResult(fdcheck))
100                         {
101                                 if (resolver2.GetFD() != -1)
102                                 {
103                                         dnslist[resolver2.GetFD()] = NULL;
104                                         std::string ip = resolver2.GetResultIP();
105                                         usr = Find(u);
106                                         if (usr)
107                                         {
108                                                 if (usr->registered > 3)
109                                                 {
110                                                         usr->dns_done = true;
111                                                         return true;
112                                                 }
113                                                 if ((hostname != "") && (usr->registered != 7))
114                                                 {
115                                                         if ((std::string(inet_ntoa(usr->ip4)) == ip) && (hostname.length() < 65))
116                                                         {
117                                                                 if ((hostname.find_last_of(".in-addr.arpa") == hostname.length() - 1) && (hostname.find_last_of(".in-addr.arpa") != std::string::npos))
118                                                                 {
119                                                                         WriteServ(usr->fd,"NOTICE Auth :*** Your ISP are muppets -- reverse resolution resolves back to same reverse .arpa domain (!)");
120                                                                 }
121                                                                 else
122                                                                 {
123                                                                         strlcpy(usr->host,hostname.c_str(),64);
124                                                                         strlcpy(usr->dhost,hostname.c_str(),64);
125                                                                         WriteServ(usr->fd,"NOTICE Auth :*** Found your hostname");
126                                                                 }
127                                                         }
128                                                         usr->dns_done = true;
129                                                         return true;
130                                                 }
131                                         }
132                                 }
133                                 else
134                                 {
135                                         usr = Find(u);
136                                         if (usr)
137                                         {
138                                                 usr->dns_done = true;
139                                         }
140                                         return true;
141                                 }
142                         }
143                         return false;
144                 }
145                 else
146                 {
147                         // doing reverse lookup
148                         userrec* usr = NULL;
149                         if (resolver1.HasResult(fdcheck))
150                         {
151                                 usr = Find(u);
152                                 if ((usr) && (usr->dns_done))
153                                 {
154                                         if (resolver1.GetFD() != -1)
155                                         {
156                                                 dnslist[resolver1.GetFD()] = NULL;
157                                                 user_fd_to_dns[usr->fd] = NULL;
158                                         }
159                                         return true;
160                                 }
161                                 if (resolver1.GetFD() != -1)
162                                 {
163                                         dnslist[resolver1.GetFD()] = NULL;
164                                         hostname = resolver1.GetResult();
165                                         if (usr)
166                                         {
167                                                 user_fd_to_dns[usr->fd] = NULL;
168                                                 if ((usr->registered > 3) || (hostname == ""))
169                                                 {
170                                                         WriteServ(usr->fd,"NOTICE Auth :*** Could not resolve your hostname -- Using your IP address instead");
171                                                         usr->dns_done = true;
172                                                         return true;
173                                                 }
174                                                 if (hostname != "")
175                                                 {
176                                                         resolver2.ForwardLookup(hostname, true);
177                                                         if (resolver2.GetFD() != -1)
178                                                         {
179                                                                 dnslist[resolver2.GetFD()] = this;
180                                                                 if (usr)
181                                                                         user_fd_to_dns[usr->fd] = this;
182                                                         }
183                                                 }
184                                         }
185                                 }
186                         }
187                 }
188                 return false;
189         }
190
191         int GetFD()
192         {
193                 userrec* usr = Find(u);
194                 if (!usr)
195                         return 0;
196                 if (usr->dns_done)
197                         return 0;
198                 return usr->fd;
199         }
200 };
201
202 bool lookup_dns(const std::string &nick)
203 {
204         /* First attempt to find the nickname */
205         userrec* u = Find(nick);
206         if (u)
207         {
208                 /* Check the cache */
209                 /*address_cache::iterator address = addrcache.find(u->ip4);
210                 if (address != addrcache.end())
211                 {
212                         WriteServ(u->fd,"NOTICE Auth :*** Found your hostname (cached)");
213                         log(DEBUG,"Found cached host");
214                         strlcpy(u->host,address->second->c_str(),MAXBUF);
215                         strlcpy(u->dhost,address->second->c_str(),MAXBUF);
216                         u->dns_done = true;
217                         return true;
218                 }*/
219                 /* If the user exists, create a new
220                  * lookup object, and associate it
221                  * with the user. The lookup object
222                  * will maintain the reference table
223                  * which we use for quickly finding
224                  * dns results. Please note that we
225                  * do not associate a lookup with a
226                  * userrec* pointer and we use the
227                  * nickname instead because, by the
228                  * time the DNS lookup has completed,
229                  * the nickname could have quit and
230                  * if we then try and access the
231                  * pointer we get a nice segfault.
232                  */
233                 Lookup* L = new Lookup();
234                 L->DoLookup(nick);
235                 return true;
236         }
237         return false;
238 }
239
240 void ZapThisDns(int fd)
241 {
242         if ((fd < 0) || (fd > MAX_DESCRIPTORS))
243                 return;
244
245         Lookup *x = user_fd_to_dns[fd];
246
247         if (x)
248         {
249                 if (x->resolver1.GetFD() > 0)
250                 {
251                         log(DEBUG,"Whacked resolver1");
252                         dns_close(x->resolver1.GetFD());
253                 }
254
255                 if (x->resolver2.GetFD() > 0)
256                 {
257                         log(DEBUG,"Whacked resolver2");
258                         dns_close(x->resolver2.GetFD());
259                 }
260         }
261 }
262
263 void dns_poll(int fdcheck)
264 {
265         /* Check the given file descriptor is in valid range */
266         if ((fdcheck < 0) || (fdcheck > MAX_DESCRIPTORS))
267                 return;
268
269         /* Try and find the file descriptor in our list of
270          * active DNS lookups
271          */
272         Lookup *x = dnslist[fdcheck];
273         if (x)
274         {
275                 /* If it exists check if its a valid fd still */
276                 if (x->GetFD() != -1)
277                 {
278                         /* Check if its done, if it is delete it */
279                         if (x->Done(fdcheck))
280                         {
281                                 /* We don't need to delete the file descriptor
282                                  * from the socket engine, as dns.cpp tracks it
283                                  * for us if we are in single-threaded country.
284                                  */
285                                 DELETE(x);
286                         }
287                 }
288                 else
289                 {
290                         /* its fd is dodgy, the dns code probably
291                          * bashed it due to error. Free the class.
292                          */
293                         DELETE(x);
294                 }
295                 /* If we got down here, the dns lookup was valid, BUT,
296                  * its still in progress. Be patient, and wait for
297                  * more socketengine events to complete the lookups.
298                  */
299                 return;
300         }
301         /* This FD doesnt belong here, lets be rid of it,
302          * just to be safe so we dont get any more events
303          * about it.
304          */
305         if (ServerInstance && ServerInstance->SE)
306                 ServerInstance->SE->DelFd(fdcheck);
307 }