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