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