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