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