summaryrefslogtreecommitdiff
path: root/src/inspircd.cpp
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/inspircd.cpp
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/inspircd.cpp')
-rw-r--r--src/inspircd.cpp239
1 files changed, 138 insertions, 101 deletions
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;