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