From 653638c68684ec035fd58bc2d0d91c9bf9aa2ab9 Mon Sep 17 00:00:00 2001 From: brain Date: Fri, 27 Jan 2006 15:26:59 +0000 Subject: Improved IP handling. Now uses in_addr to store client ip, not char[16]! Added global and local session limits All of this needs TESTING. git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@2934 e03df62e-2008-0410-955e-edbf42e46eb7 --- src/commands.cpp | 4 +-- src/dnsqueue.cpp | 2 +- src/inspircd.cpp | 5 ++-- src/inspircd_io.cpp | 13 +++++++++ src/modules/m_spanningtree.cpp | 8 +++--- src/modules/m_userip.cpp | 2 +- src/userprocess.cpp | 14 +++++----- src/users.cpp | 60 ++++++++++++++++++++++++++++++++++-------- src/xline.cpp | 2 +- 9 files changed, 80 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/commands.cpp b/src/commands.cpp index e9b921beb..37f1fcef2 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -119,7 +119,7 @@ void do_whois(userrec* user, userrec* dest,unsigned long signon, unsigned long i WriteServ(user->fd,"311 %s %s %s %s * :%s",user->nick, dest->nick, dest->ident, dest->dhost, dest->fullname); if ((user == dest) || (strchr(user->modes,'o'))) { - WriteServ(user->fd,"378 %s %s :is connecting from *@%s %s",user->nick, dest->nick, dest->host, dest->ip); + WriteServ(user->fd,"378 %s %s :is connecting from *@%s %s",user->nick, dest->nick, dest->host, (char*)inet_ntoa(dest->ip4)); } std::string cl = chlist(dest,user); if (cl.length()) @@ -309,7 +309,7 @@ bool ip_matches_everyone(std::string ip, userrec* user) long matches = 0; for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++) { - if (match(u->second->ip,ip.c_str())) + if (match((char*)inet_ntoa(u->second->ip4),ip.c_str())) matches++; } float percent = ((float)matches / (float)clientlist.size()) * 100; diff --git a/src/dnsqueue.cpp b/src/dnsqueue.cpp index 7e2ad86c3..dee671aa1 100644 --- a/src/dnsqueue.cpp +++ b/src/dnsqueue.cpp @@ -125,7 +125,7 @@ public: } if ((hostname != "") && (usr->registered != 7)) { - if (std::string(usr->ip) == ip) + if (std::string((char*)inet_ntoa(usr->ip4)) == ip) { strlcpy(usr->host,hostname.c_str(),MAXBUF); strlcpy(usr->dhost,hostname.c_str(),MAXBUF); diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 4b390eeb0..a834d4d5c 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -714,7 +714,6 @@ int InspIRCd::Run() { in_port = ntohs(sock_us.sin_port); log(DEBUG,"Accepted socket %d",incomingSockfd); - target = (char*)inet_ntoa(client.sin_addr); /* Years and years ago, we used to resolve here * using gethostbyaddr(). That is sucky and we * don't do that any more... @@ -722,10 +721,10 @@ int InspIRCd::Run() NonBlocking(incomingSockfd); if (Config->GetIOHook(in_port)) { - Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, target, in_port); + Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, (char*)inet_ntoa(client.sin_addr), in_port); } stats->statsAccept++; - AddClient(incomingSockfd, target, in_port, false, target); + AddClient(incomingSockfd, in_port, false, client.sin_addr); log(DEBUG,"Adding client on port %lu fd=%lu",(unsigned long)in_port,(unsigned long)incomingSockfd); } else diff --git a/src/inspircd_io.cpp b/src/inspircd_io.cpp index a52c5933b..8534af18e 100644 --- a/src/inspircd_io.cpp +++ b/src/inspircd_io.cpp @@ -149,6 +149,7 @@ void ServerConfig::Read(bool bail, userrec* user) { char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF],MW[MAXBUF],MCON[MAXBUF],MT[MAXBUF]; char AH[MAXBUF],AP[MAXBUF],AF[MAXBUF],DNT[MAXBUF],pfreq[MAXBUF],thold[MAXBUF],sqmax[MAXBUF],rqmax[MAXBUF],SLIMT[MAXBUF]; + char localmax[MAXBUF],globalmax[MAXBUF]; ConnectClass c; std::stringstream errstr; include_stack.clear(); @@ -293,6 +294,8 @@ void ServerConfig::Read(bool bail, userrec* user) ConfValue("connect","threshold",i,thold,&Config->config_f); ConfValue("connect","sendq",i,sqmax,&Config->config_f); ConfValue("connect","recvq",i,rqmax,&Config->config_f); + ConfValue("connect","localmax",i,localmax,&Config->config_f); + ConfValue("connect","globalmax",i,globalmax,&Config->config_f); if (*Value) { c.host = Value; @@ -306,6 +309,16 @@ void ServerConfig::Read(bool bail, userrec* user) c.threshold = 5; c.sendqmax = 262144; // 256k c.recvqmax = 4096; // 4k + c.maxlocal = 3; + c.maxglobal = 3; + if (atoi(localmax)>0) + { + c.maxlocal = atoi(localmax); + } + if (atoi(globalmax)>0) + { + c.maxglobal = atoi(globalmax); + } if (atoi(thold)>0) { c.threshold = atoi(thold); diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index e694c4570..160632bef 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -1069,7 +1069,7 @@ class TreeSocket : public InspSocket clientlist[tempnick]->registered = 7; clientlist[tempnick]->signon = age; strlcpy(clientlist[tempnick]->modes, modes.c_str(),53); - strlcpy(clientlist[tempnick]->ip,ip.c_str(),16); + inet_aton(ip.c_str(),&clientlist[tempnick]->ip4); ucrec a; a.channel = NULL; @@ -1079,7 +1079,7 @@ class TreeSocket : public InspSocket if (!this->bursting) { - WriteOpers("*** Client connecting at %s: %s!%s@%s [%s]",clientlist[tempnick]->server,clientlist[tempnick]->nick,clientlist[tempnick]->ident,clientlist[tempnick]->host,clientlist[tempnick]->ip); + WriteOpers("*** Client connecting at %s: %s!%s@%s [%s]",clientlist[tempnick]->server,clientlist[tempnick]->nick,clientlist[tempnick]->ident,clientlist[tempnick]->host,(char*)inet_ntoa(clientlist[tempnick]->ip4)); } params[7] = ":" + params[7]; DoOneToAllButSender(source,"NICK",params,source); @@ -1210,7 +1210,7 @@ class TreeSocket : public InspSocket { if (u->second->registered == 7) { - snprintf(data,MAXBUF,":%s NICK %lu %s %s %s %s +%s %s :%s",u->second->server,(unsigned long)u->second->age,u->second->nick,u->second->host,u->second->dhost,u->second->ident,u->second->modes,u->second->ip,u->second->fullname); + snprintf(data,MAXBUF,":%s NICK %lu %s %s %s %s +%s %s :%s",u->second->server,(unsigned long)u->second->age,u->second->nick,u->second->host,u->second->dhost,u->second->ident,u->second->modes,(char*)inet_ntoa(u->second->ip4),u->second->fullname); this->WriteLine(data); if (strchr(u->second->modes,'o')) { @@ -3028,7 +3028,7 @@ class ModuleSpanningTree : public Module params.push_back(user->dhost); params.push_back(user->ident); params.push_back("+"+std::string(user->modes)); - params.push_back(user->ip); + params.push_back((char*)inet_ntoa(user->ip4)); params.push_back(":"+std::string(user->fullname)); DoOneToMany(Srv->GetServerName(),"NICK",params); diff --git a/src/modules/m_userip.cpp b/src/modules/m_userip.cpp index fe37ebc7f..48befe370 100644 --- a/src/modules/m_userip.cpp +++ b/src/modules/m_userip.cpp @@ -44,7 +44,7 @@ class cmd_userip : public command_t userrec *u = Find(parameters[i]); if (u) { - snprintf(junk,MAXBUF,"%s%s=+%s@%s ",u->nick,strchr(u->modes,'o') ? "*" : "",u->ident,u->ip); + snprintf(junk,MAXBUF,"%s%s=+%s@%s ",u->nick,strchr(u->modes,'o') ? "*" : "",u->ident,(char*)inet_ntoa(u->ip4)); strlcat(Return,junk,MAXBUF); } } diff --git a/src/userprocess.cpp b/src/userprocess.cpp index c7e7aa545..29560871f 100644 --- a/src/userprocess.cpp +++ b/src/userprocess.cpp @@ -148,9 +148,9 @@ void ProcessUser(userrec* cu) } else { - WriteOpers("*** Excess flood from %s",current->ip); - log(DEFAULT,"Excess flood from: %s",current->ip); - add_zline(120,Config->ServerName,"Flood from unregistered connection",current->ip); + WriteOpers("*** Excess flood from %s",(char*)inet_ntoa(current->ip4)); + log(DEFAULT,"Excess flood from: %s",(char*)inet_ntoa(current->ip4)); + add_zline(120,Config->ServerName,"Flood from unregistered connection",(char*)inet_ntoa(current->ip4)); apply_lines(APPLY_ZLINES); } return; @@ -163,9 +163,9 @@ void ProcessUser(userrec* cu) } else { - WriteOpers("*** Excess flood from %s",current->ip); - log(DEFAULT,"Excess flood from: %s",current->ip); - add_zline(120,Config->ServerName,"Flood from unregistered connection",current->ip); + WriteOpers("*** Excess flood from %s",(char*)inet_ntoa(current->ip4)); + log(DEFAULT,"Excess flood from: %s",(char*)inet_ntoa(current->ip4)); + add_zline(120,Config->ServerName,"Flood from unregistered connection",(char*)inet_ntoa(current->ip4)); apply_lines(APPLY_ZLINES); } return; @@ -197,7 +197,7 @@ void ProcessUser(userrec* cu) } else { - add_zline(120,Config->ServerName,"Flood from unregistered connection",current->ip); + add_zline(120,Config->ServerName,"Flood from unregistered connection",(char*)inet_ntoa(current->ip4)); apply_lines(APPLY_ZLINES); } return; diff --git a/src/users.cpp b/src/users.cpp index 8bc2f8baa..8089f5c23 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -64,7 +64,7 @@ template inline string ConvToStr(const T &in) userrec::userrec() { // the PROPER way to do it, AVOID bzero at *ALL* costs - *nick = *ident = *host = *dhost = *fullname = *modes = *awaymsg = *oper = *ip = 0; + *nick = *ident = *host = *dhost = *fullname = *modes = *awaymsg = *oper = 0; server = (char*)FindServerNamePtr(Config->ServerName); reset_due = TIME; lines_in = fd = lastping = signon = idle_lastmsg = nping = registered = 0; @@ -554,14 +554,14 @@ void AddWhoWas(userrec* u) } /* add a client connection to the sockets list */ -void AddClient(int socket, char* host, int port, bool iscached, char* ip) +void AddClient(int socket, int port, bool iscached, in_addr ip4) { string tempnick; char tn2[MAXBUF]; user_hash::iterator iter; tempnick = ConvToStr(socket) + "-unknown"; - sprintf(tn2,"%lu-unknown",(unsigned long)socket); + sprintf(tn2,"%d-unknown",socket); iter = clientlist.find(tempnick); @@ -588,19 +588,24 @@ void AddClient(int socket, char* host, int port, bool iscached, char* ip) */ clientlist[tempnick] = new userrec(); - log(DEBUG,"AddClient: %lu %s %d %s",(unsigned long)socket,host,port,ip); + char *ipaddr = (char*)inet_ntoa(ip4); + + log(DEBUG,"AddClient: %d %d %s",socket,port,ipaddr); clientlist[tempnick]->fd = socket; strlcpy(clientlist[tempnick]->nick, tn2,NICKMAX); - strlcpy(clientlist[tempnick]->host, host,160); - strlcpy(clientlist[tempnick]->dhost, host,160); + /* We don't know the host yet, dns lookup could still be going on, + * so instead we just put the ip address here, for now. + */ + strlcpy(clientlist[tempnick]->host, ipaddr, 160); + strlcpy(clientlist[tempnick]->dhost, ipaddr, 160); clientlist[tempnick]->server = (char*)FindServerNamePtr(Config->ServerName); strlcpy(clientlist[tempnick]->ident, "unknown",IDENTMAX); clientlist[tempnick]->registered = 0; clientlist[tempnick]->signon = TIME + Config->dns_timeout; clientlist[tempnick]->lastping = 1; + clientlist[tempnick]->ip4 = ip4; clientlist[tempnick]->port = port; - strlcpy(clientlist[tempnick]->ip,ip,16); // set the registration timeout for this user unsigned long class_regtimeout = 90; @@ -611,7 +616,7 @@ void AddClient(int socket, char* host, int port, bool iscached, char* ip) for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++) { - if (match(clientlist[tempnick]->host,i->host.c_str()) && (i->type == CC_ALLOW)) + if (match(ipaddr,i->host.c_str()) && (i->type == CC_ALLOW)) { class_regtimeout = (unsigned long)i->registration_timeout; class_flood = i->flood; @@ -660,10 +665,10 @@ void AddClient(int socket, char* host, int port, bool iscached, char* ip) kill_link(clientlist[tempnick],"Server is full"); return; } - char* e = matches_exception(ip); + char* e = matches_exception(ipaddr); if (!e) { - char* r = matches_zline(ip); + char* r = matches_zline(ipaddr); if (r) { char reason[MAXBUF]; @@ -679,6 +684,29 @@ void AddClient(int socket, char* host, int port, bool iscached, char* ip) WriteServ(clientlist[tempnick]->fd,"NOTICE Auth :*** Looking up your hostname..."); } +long FindMatchingGlobal(userrec* user) +{ + long x = 0; + for (user_hash::const_iterator a = clientlist.begin(); a != clientlist.end(); a++) + { + if (a->second->ip4.s_addr == user->ip4.s_addr) + x++; + } + return x; +} + +long FindMatchingLocal(userrec* user) +{ + long x = 0; + for (std::vector::const_iterator a = local_users.begin(); a != local_users.end(); a++) + { + userrec* comp = (userrec*)(*a); + if (comp->ip4.s_addr == user->ip4.s_addr) + x++; + } + return x; +} + void FullConnectUser(userrec* user, CullList* Goners) { ServerInstance->stats->statsConnects++; @@ -697,6 +725,16 @@ void FullConnectUser(userrec* user, CullList* Goners) Goners->AddItem(user,"Invalid password"); return; } + if (FindMatchingLocal(user) > a.maxlocal) + { + Goners->AddItem(user,"No more connections allowed from your host via this connect class (local)"); + return; + } + if (FindMatchingGlobal(user) > a.maxglobal) + { + Goners->AddItem(user,"No more connections allowed from your host via this connect class (global)"); + return; + } char match_against[MAXBUF]; snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host); @@ -752,7 +790,7 @@ void FullConnectUser(userrec* user, CullList* Goners) FOREACH_MOD(I_OnUserConnect,OnUserConnect(user)); FOREACH_MOD(I_OnGlobalConnect,OnGlobalConnect(user)); user->registered = 7; - WriteOpers("*** Client connecting on port %lu: %s!%s@%s [%s]",(unsigned long)user->port,user->nick,user->ident,user->host,user->ip); + WriteOpers("*** Client connecting on port %lu: %s!%s@%s [%s]",(unsigned long)user->port,user->nick,user->ident,user->host,(char*)inet_ntoa(user->ip4)); } /* re-allocates a nick in the user_hash after they change nicknames, diff --git a/src/xline.cpp b/src/xline.cpp index ed16fc4c1..bfffd0d84 100644 --- a/src/xline.cpp +++ b/src/xline.cpp @@ -692,7 +692,7 @@ void apply_lines(const int What) } if ((What & APPLY_ZLINES) && (zlines.size() || pzlines.size())) { - if ((check = matches_zline(u->ip))) + if ((check = matches_zline((char*)inet_ntoa(u->ip4)))) { snprintf(reason,MAXBUF,"Z-Lined: %s",check); Goners->AddItem(u,reason); -- cgit v1.2.3