summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2005-04-01 19:15:55 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2005-04-01 19:15:55 +0000
commitb7f823b059aa6f8133abf0a0d1895983ccd04590 (patch)
tree9e09fa0b2a02ce2380a7069ef18d198c9a22c773 /src
parent3ae5210daedc65958799d38dd9eb05a8b5beee6c (diff)
DNS timeout fixes!
Docs to come git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@940 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src')
-rw-r--r--src/dns.cpp50
-rw-r--r--src/dnsqueue.cpp28
-rw-r--r--src/inspircd.cpp239
3 files changed, 187 insertions, 130 deletions
diff --git a/src/dns.cpp b/src/dns.cpp
index ffde3f2a1..a1287e499 100644
--- a/src/dns.cpp
+++ b/src/dns.cpp
@@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
+#include <poll.h>
#include "dns.h"
static const char tagstring[] = "$Id$";
@@ -255,7 +256,7 @@ static s_connection *dns_add_query(s_header *h) { /* build DNS query, add to lis
}
}
if (s->fd == -1) {
- free(s);
+ delete s;
return NULL;
}
/* create new connection object, add to linked list */
@@ -315,7 +316,7 @@ in_addr* DNS::dns_aton4_r(const char *ipstring) { /* ascii to numeric (reentrant
in_addr* ip;
ip = new in_addr;
if(dns_aton4_s(ipstring,ip) == NULL) {
- free(ip);
+ delete ip;
return NULL;
}
return ip;
@@ -470,7 +471,7 @@ char* DNS::dns_getresult_r(const int fd) { /* retrieve result of DNS query (reen
char *result;
result = new char[RESULTSIZE];
if(dns_getresult_s(fd,result) == NULL) {
- free(result);
+ delete result;
return NULL;
}
return result;
@@ -484,6 +485,11 @@ char* DNS::dns_getresult_s(const int fd, char *result) { /* retrieve result of D
unsigned char buffer[sizeof(s_header)];
unsigned short p;
+ if (result)
+ {
+ result[0] = 0;
+ }
+
prev = NULL;
c = connection_head;
while (c != NULL) { /* find query in list of open queries */
@@ -504,28 +510,28 @@ char* DNS::dns_getresult_s(const int fd, char *result) { /* retrieve result of D
l = recv(c->fd,buffer,sizeof(s_header),0);
dns_close(c->fd);
if (l < 12) {
- free(c);
+ delete c;
return NULL;
}
dns_fill_header(&h,buffer,l - 12);
if (c->id[0] != h.id[0] || c->id[1] != h.id[1]) {
- free(c);
+ delete c;
return NULL; /* ID mismatch */
}
if ((h.flags1 & FLAGS1_MASK_QR) == 0) {
- free(c);
+ delete c;
return NULL;
}
if ((h.flags1 & FLAGS1_MASK_OPCODE) != 0) {
- free(c);
+ delete c;
return NULL;
}
if ((h.flags2 & FLAGS2_MASK_RCODE) != 0) {
- free(c);
+ delete c;
return NULL;
}
if (h.ancount < 1) { /* no sense going on if we don't have any answers */
- free(c);
+ delete c;
return NULL;
}
/* skip queries */
@@ -561,7 +567,7 @@ char* DNS::dns_getresult_s(const int fd, char *result) { /* retrieve result of D
}
}
if (l - i < 10) {
- free(c);
+ delete c;
return NULL;
}
dns_fill_rr(&rr,&h.payload[i]);
@@ -617,7 +623,7 @@ char* DNS::dns_getresult_s(const int fd, char *result) { /* retrieve result of D
if (rr._class != 1)
break;
if (rr.rdlength != 4) {
- free(c);
+ delete c;
return NULL;
}
memcpy(&alist->ip,&h.payload[i],4);
@@ -641,7 +647,7 @@ char* DNS::dns_getresult_s(const int fd, char *result) { /* retrieve result of D
}
}
if (l - i < 10) {
- free(c);
+ delete c;
return NULL;
}
dns_fill_rr(&rr,&h.payload[i]);
@@ -661,7 +667,7 @@ char* DNS::dns_getresult_s(const int fd, char *result) { /* retrieve result of D
result[rr.rdlength] = '\0';
break;
}
- free(c);
+ delete c;
return result;
}
@@ -695,14 +701,16 @@ bool DNS::ForwardLookup(std::string host)
bool DNS::HasResult()
{
- fd_set fds;
- FD_ZERO(&fds);
- FD_SET(this->fd,&fds);
- timeval tvs;
- tvs.tv_usec = 0;
- tvs.tv_sec = 0;
- int result = select(this->fd+1, &fds, NULL, NULL, &tvs);
- return (result > 0);
+ pollfd polls;
+ polls.fd = this->fd;
+ polls.events = POLLIN;
+ int ret = poll(&polls,1,1);
+ return (ret > 0);
+}
+
+int DNS::GetFD()
+{
+ return this->fd;
}
std::string DNS::GetResult()
diff --git a/src/dnsqueue.cpp b/src/dnsqueue.cpp
index ac521f091..4c328e71c 100644
--- a/src/dnsqueue.cpp
+++ b/src/dnsqueue.cpp
@@ -193,13 +193,26 @@ public:
{
if (resolver->HasResult())
{
- log(DEBUG,"DNS Result available!");
- std::string hostname = resolver->GetResult();
- if (u)
+ log(DEBUG,"resolver says result available!");
+ if (resolver->GetFD() != 0)
+ {
+ log(DEBUG,"Resolver FD is not 0");
+ std::string hostname = resolver->GetResult();
+ if (u)
+ {
+ log(DEBUG,"Applying hostname lookup to %s: %s",u->nick,hostname.c_str());
+ if (hostname != "")
+ {
+ strlcpy(u->host,hostname.c_str(),MAXBUF);
+ WriteServ(u->fd,"NOTICE Auth :Resolved your hostname: %s",hostname.c_str());
+ u->dns_done = true;
+ return true;
+ }
+ return false;
+ }
+ }
+ else
{
- log(DEBUG,"Applying hostname lookup to %s: %s",u->nick,hostname.c_str());
- if (hostname != "")
- strlcpy(u->host,hostname.c_str(),MAXBUF);
u->dns_done = true;
return true;
}
@@ -225,6 +238,7 @@ bool lookup_dns(userrec* u)
{
// place a new user into the queue...
log(DEBUG,"Queueing DNS lookup for %s",u->nick);
+ WriteServ(u->fd,"NOTICE Auth :Looking up your hostname...");
Lookup L(u);
dnsq.push_back(L);
return true;
@@ -235,11 +249,9 @@ void dns_poll()
// do we have items in the queue?
if (dnsq.size())
{
- log(DEBUG,"DNS items pending...");
// are any ready, or stale?
if (dnsq[0].Done() || (!dnsq[0].GetFD()))
{
- // if they are take them out...
log(DEBUG,"****** DNS lookup for fd %d is complete. ******",dnsq[0].GetFD());
dnsq.erase(dnsq.begin());
}
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 491c67cd2..989e3e6b7 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -87,6 +87,7 @@ time_t startup_time = time(NULL);
int NetBufferSize = 10240; // NetBufferSize used as the buffer size for all read() ops
extern int MaxWhoResults;
time_t nb_start = 0;
+int dns_timeout = 5;
bool AllowHalfop = true;
bool AllowProtect = true;
@@ -97,6 +98,8 @@ std::vector<std::string> module_names;
extern std::vector<ircd_module*> factory;
std::vector<int> fd_reap;
+std::vector<userrec*> pending_connects;
+
extern int MODCOUNT;
bool nofork = false;
@@ -315,7 +318,7 @@ void readfile(file_cache &F, const char* fname)
void ReadConfig(bool bail, userrec* user)
{
char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF],MW[MAXBUF];
- char AH[MAXBUF],AP[MAXBUF],AF[MAXBUF];
+ char AH[MAXBUF],AP[MAXBUF],AF[MAXBUF],DNT[MAXBUF];
ConnectClass c;
std::stringstream errstr;
@@ -372,8 +375,14 @@ void ReadConfig(bool bail, userrec* user)
ConfValue("options","allowprotect",0,AP,&config_f);
ConfValue("options","allowfounder",0,AF,&config_f);
ConfValue("dns","server",0,DNSServer,&config_f);
+ ConfValue("dns","timeout",0,DNT,&config_f);
NetBufferSize = atoi(NB);
MaxWhoResults = atoi(MW);
+ dns_timeout = atoi(DNT);
+ if (!dns_timeout)
+ dns_timeout = 5;
+ if (!strcmp(DNSServer,""))
+ strlcpy(DNSServer,"127.0.0.1",MAXBUF);
AllowHalfop = ((!strcasecmp(AH,"true")) || (!strcasecmp(AH,"1")) || (!strcasecmp(AH,"yes")));
AllowProtect = ((!strcasecmp(AP,"true")) || (!strcasecmp(AP,"1")) || (!strcasecmp(AP,"yes")));
AllowFounder = ((!strcasecmp(AF,"true")) || (!strcasecmp(AF,"1")) || (!strcasecmp(AF,"yes")));
@@ -1110,7 +1119,7 @@ void purge_empty_chans(void)
if (i != chanlist.end())
{
log(DEBUG,"del_channel: destroyed: %s",i->second->name);
- delete i->second;
+ if (i->second) delete i->second;
chanlist.erase(i);
go_again = 1;
purge++;
@@ -1619,7 +1628,7 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool
if (iter != chanlist.end())
{
log(DEBUG,"del_channel: destroyed: %s",Ptr->name);
- delete iter->second;
+ if (iter->second) delete iter->second;
chanlist.erase(iter);
}
}
@@ -1698,7 +1707,7 @@ void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason)
if (iter != chanlist.end())
{
log(DEBUG,"del_channel: destroyed: %s",Ptr->name);
- delete iter->second;
+ if (iter->second) delete iter->second;
chanlist.erase(iter);
}
}
@@ -1916,7 +1925,7 @@ void kill_link(userrec *user,const char* r)
{
log(DEBUG,"deleting user hash value %d",iter->second);
if ((iter->second) && (user->registered == 7)) {
- delete iter->second;
+ if (iter->second) delete iter->second;
}
clientlist.erase(iter);
}
@@ -1966,7 +1975,7 @@ void kill_link_silent(userrec *user,const char* r)
{
log(DEBUG,"deleting user hash value %d",iter->second);
if ((iter->second) && (user->registered == 7)) {
- delete iter->second;
+ if (iter->second) delete iter->second;
}
clientlist.erase(iter);
}
@@ -2106,7 +2115,6 @@ userrec* ReHashNick(char* Old, char* New)
clientlist[New] = new userrec();
clientlist[New] = oldnick->second;
- /*delete oldnick->second; */
clientlist.erase(oldnick);
log(DEBUG,"ReHashNick: Nick rehashed as %s",New);
@@ -2141,7 +2149,7 @@ void AddWhoWas(userrec* u)
// 3600 seconds in an hour ;)
if ((i->second->signon)<(time(NULL)-(WHOWAS_STALE*3600)))
{
- delete i->second;
+ if (i->second) delete i->second;
i->second = a;
log(DEBUG,"added WHOWAS entry, purged an old record");
return;
@@ -2157,7 +2165,7 @@ void AddWhoWas(userrec* u)
else
{
log(DEBUG,"updated WHOWAS entry");
- delete iter->second;
+ if (iter->second) delete iter->second;
iter->second = a;
}
}
@@ -2205,15 +2213,6 @@ void AddClient(int socket, char* host, int port, bool iscached, char* ip)
clientlist[tempnick]->port = port;
strncpy(clientlist[tempnick]->ip,ip,32);
- if (iscached)
- {
- WriteServ(socket,"NOTICE Auth :Found your hostname (cached)...");
- }
- else
- {
- WriteServ(socket,"NOTICE Auth :Looking up your hostname...");
- }
-
lookup_dns(clientlist[tempnick]);
// set the registration timeout for this user
@@ -2362,81 +2361,131 @@ void ShowRULES(userrec *user)
}
/* shows the message of the day, and any other on-logon stuff */
-void ConnectUser(userrec *user)
+void FullConnectUser(userrec* user)
{
- user->registered = 7;
- user->idle_lastmsg = time(NULL);
+ user->registered = 7;
+ user->idle_lastmsg = time(NULL);
log(DEBUG,"ConnectUser: %s",user->nick);
- if (strcmp(Passwd(user),"") && (!user->haspassed))
- {
- kill_link(user,"Invalid password");
- return;
- }
- if (IsDenied(user))
+ if (strcmp(Passwd(user),"") && (!user->haspassed))
+ {
+ kill_link(user,"Invalid password");
+ return;
+ }
+ if (IsDenied(user))
+ {
+ kill_link(user,"Unauthorised connection");
+ return;
+ }
+
+ char match_against[MAXBUF];
+ snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host);
+ char* r = matches_gline(match_against);
+ if (r)
+ {
+ char reason[MAXBUF];
+ snprintf(reason,MAXBUF,"G-Lined: %s",r);
+ kill_link_silent(user,reason);
+ return;
+ }
+
+ r = matches_kline(user->host);
+ if (r)
+ {
+ char reason[MAXBUF];
+ snprintf(reason,MAXBUF,"K-Lined: %s",r);
+ kill_link_silent(user,reason);
+ return;
+ }
+
+ WriteServ(user->fd,"NOTICE Auth :Welcome to \002%s\002!",Network);
+ WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Network,user->nick,user->ident,user->host);
+ WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,ServerName,VERSION);
+ WriteServ(user->fd,"003 %s :This server was created %s %s",user->nick,__TIME__,__DATE__);
+ WriteServ(user->fd,"004 %s %s %s iowghraAsORVSxNCWqBzvdHtGI lvhopsmntikrRcaqOALQbSeKVfHGCuzN",user->nick,ServerName,VERSION);
+ // the neatest way to construct the initial 005 numeric, considering the number of configure constants to go in it...
+ std::stringstream v;
+ v << "MESHED WALLCHOPS MODES=13 CHANTYPES=# PREFIX=(ohv)@%+ MAP SAFELIST MAXCHANNELS=" << MAXCHANS;
+ v << " MAXBANS=60 NICKLEN=" << NICKMAX;
+ v << " TOPICLEN=307 KICKLEN=307 MAXTARGETS=20 AWAYLEN=307 CHANMODES=ohvb,k,l,psmnti NETWORK=";
+ v << std::string(Network);
+ std::string data005 = v.str();
+ FOREACH_MOD On005Numeric(data005);
+ // anfl @ #ratbox, efnet reminded me that according to the RFC this cant contain more than 13 tokens per line...
+ // so i'd better split it :)
+ std::stringstream out(data005);
+ std::string token = "";
+ std::string line5 = "";
+ int token_counter = 0;
+ while (!out.eof())
+ {
+ out >> token;
+ line5 = line5 + token + " ";
+ token_counter++;
+ if ((token_counter >= 13) || (out.eof() == true))
+ {
+ WriteServ(user->fd,"005 %s %s:are supported by this server",user->nick,line5.c_str());
+ line5 = "";
+ token_counter = 0;
+ }
+ }
+ ShowMOTD(user);
+ FOREACH_MOD OnUserConnect(user);
+ WriteOpers("*** Client connecting on port %d: %s!%s@%s [%s]",user->port,user->nick,user->ident,user->host,user->ip);
+
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"N %d %s %s %s %s +%s %s %s :%s",user->age,user->nick,user->host,user->dhost,user->ident,user->modes,user->ip,ServerName,user->fullname);
+ NetSendToAll(buffer);
+}
+
+// handles any connects where DNS isnt done yet, times out stale dns queries on users, and lets completed queries connect.
+void HandlePendingConnects()
+{
+ if (pending_connects.size())
{
- kill_link(user,"Unauthorised connection");
- return;
+ for (std::vector<userrec*>::iterator i = pending_connects.begin(); i <= pending_connects.end(); i++)
+ {
+ userrec* a = *i;
+ if (a)
+ {
+ // this user's dns is done now.
+ if ((a->dns_done) && (a->registered == 3))
+ {
+ FullConnectUser(a); // attack! attack!....
+ pending_connects.erase(i);
+ return; // ...RUN AWAY! RUN AWAY!
+ }
+ // this users dns is NOT done, but its timed out.
+ if ((time(NULL) > a->signon+dns_timeout) && (a->registered == 3))
+ {
+ WriteServ(a->fd,"NOTICE Auth :Failed to resolve your hostname, using your IP address instead.");
+ FullConnectUser(a);
+ pending_connects.erase(i);
+ return;
+ }
+ }
+ else
+ {
+ pending_connects.erase(i);
+ return;
+ }
+ }
}
+}
- char match_against[MAXBUF];
- snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host);
- char* r = matches_gline(match_against);
- if (r)
+/* shows the message of the day, and any other on-logon stuff */
+void ConnectUser(userrec *user)
+{
+ // dns is already done, things are fast. no need to wait for dns to complete just pass them straight on
+ if (user->dns_done)
{
- char reason[MAXBUF];
- snprintf(reason,MAXBUF,"G-Lined: %s",r);
- kill_link_silent(user,reason);
- return;
+ FullConnectUser(user);
}
-
- r = matches_kline(user->host);
- if (r)
+ else
{
- char reason[MAXBUF];
- snprintf(reason,MAXBUF,"K-Lined: %s",r);
- kill_link_silent(user,reason);
- return;
+ // add them to the pending queue
+ pending_connects.push_back(user);
}
-
- WriteServ(user->fd,"NOTICE Auth :Welcome to \002%s\002!",Network);
- WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Network,user->nick,user->ident,user->host);
- WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,ServerName,VERSION);
- WriteServ(user->fd,"003 %s :This server was created %s %s",user->nick,__TIME__,__DATE__);
- WriteServ(user->fd,"004 %s %s %s iowghraAsORVSxNCWqBzvdHtGI lvhopsmntikrRcaqOALQbSeKVfHGCuzN",user->nick,ServerName,VERSION);
- // the neatest way to construct the initial 005 numeric, considering the number of configure constants to go in it...
- std::stringstream v;
- v << "MESHED WALLCHOPS MODES=13 CHANTYPES=# PREFIX=(ohv)@%+ MAP SAFELIST MAXCHANNELS=" << MAXCHANS;
- v << " MAXBANS=60 NICKLEN=" << NICKMAX;
- v << " TOPICLEN=307 KICKLEN=307 MAXTARGETS=20 AWAYLEN=307 CHANMODES=ohvb,k,l,psmnti NETWORK=";
- v << std::string(Network);
- std::string data005 = v.str();
- FOREACH_MOD On005Numeric(data005);
- // anfl @ #ratbox, efnet reminded me that according to the RFC this cant contain more than 13 tokens per line...
- // so i'd better split it :)
- std::stringstream out(data005);
- std::string token = "";
- std::string line5 = "";
- int token_counter = 0;
- while (!out.eof())
- {
- out >> token;
- line5 = line5 + token + " ";
- token_counter++;
- if ((token_counter >= 13) || (out.eof() == true))
- {
- WriteServ(user->fd,"005 %s %s:are supported by this server",user->nick,line5.c_str());
- line5 = "";
- token_counter = 0;
- }
- }
- ShowMOTD(user);
- FOREACH_MOD OnUserConnect(user);
- WriteOpers("*** Client connecting on port %d: %s!%s@%s [%s]",user->port,user->nick,user->ident,user->host,user->ip);
-
- char buffer[MAXBUF];
- snprintf(buffer,MAXBUF,"N %d %s %s %s %s +%s %s %s :%s",user->age,user->nick,user->host,user->dhost,user->ident,user->modes,user->ip,ServerName,user->fullname);
- NetSendToAll(buffer);
}
void handle_version(char **parameters, int pcnt, userrec *user)
@@ -3409,6 +3458,9 @@ int InspIRCd(void)
// poll dns queue
dns_poll();
+ // handle pending connects
+ HandlePendingConnects();
+
user_hash::iterator count2 = clientlist.begin();
// *FIX* Instead of closing sockets in kill_link when they receive the ERROR :blah line, we should queue
@@ -3698,23 +3750,8 @@ int InspIRCd(void)
length = sizeof (client);
incomingSockfd = accept (openSockfd[count], (struct sockaddr *) &client, &length);
- //address_cache::iterator iter = IP.find(client.sin_addr);
- bool iscached = false;
- //if (iter == IP.end())
- //{
- /* ip isn't in cache, add it */
- strlcpy (target, (char *) inet_ntoa (client.sin_addr), MAXBUF);
- strlcpy (resolved, target, MAXBUF);
- /* hostname now in 'target' */
- //IP[client.sin_addr] = new string(resolved);
- /* hostname in cache */
- //}
- //else
- //{
- // /* found ip (cached) */
- // strlcpy(resolved, iter->second->c_str(), MAXBUF);
- // iscached = true;
- //}
+ strlcpy (target, (char *) inet_ntoa (client.sin_addr), MAXBUF);
+ strlcpy (resolved, target, MAXBUF);
if (incomingSockfd < 0)
{
@@ -3723,7 +3760,7 @@ int InspIRCd(void)
}
else
{
- AddClient(incomingSockfd, resolved, ports[count], iscached, inet_ntoa (client.sin_addr));
+ AddClient(incomingSockfd, resolved, ports[count], false, inet_ntoa (client.sin_addr));
log(DEBUG,"InspIRCd: adding client on port %d fd=%d",ports[count],incomingSockfd);
}
goto label;