summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2004-04-09 10:50:26 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2004-04-09 10:50:26 +0000
commit998d526600b866b26bf2d865f21716b5a7eb6c71 (patch)
tree52ddfd2ac3884e18aeae60dc1e21cd34e25d25dc
parent87faee0b4cdb984d3b899b0a9e5538018e56a739 (diff)
Added flood= value to connect allow classes, added checking for flooding
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@462 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--docs/inspircd.conf.example29
-rw-r--r--include/users.h22
-rw-r--r--src/InspIRCd.layout28
-rw-r--r--src/inspircd.cpp49
-rw-r--r--src/users.cpp24
5 files changed, 104 insertions, 48 deletions
diff --git a/docs/inspircd.conf.example b/docs/inspircd.conf.example
index ce24e89d0..6042dc3cf 100644
--- a/docs/inspircd.conf.example
+++ b/docs/inspircd.conf.example
@@ -105,15 +105,21 @@
# <connect allow="ip number"> #
# <connect allow="ip number" password="blahblah"> #
# <connect allow="ip number" password="blah" timeout="10"> #
+# <connect allow="ip number" timeout="blah" flood="5"> #
# <connect deny="ip number"> #
# #
-# You may optionally include timeout="x" on any alllow line, which #
+# You may optionally include timeout="x" on any allow line, which #
# specifies the amount of time given before an unknown connection #
# is closed if USER/NICK/PASS are not given. This value is in secs #
# #
+# You may also optionally include a flood="x" line which indicates #
+# the number of lines a user may place into their buffer at once #
+# before they are disconnected for excess flood. The default is to #
+# DISABLE this feature. A recommended value is 10. #
+
<connect allow="196.12.*" password="tiffany">
-<connect allow="*" timeout="60">
+<connect allow="*" timeout="60" flood="10">
<connect deny="69.254.*">
@@ -230,17 +236,20 @@
# #
# Settings to define which features are useable on your server. #
# #
-# prefixquit - a prefix for a client's quit message #
-# loglevel - specifies what detail of messages to log in the #
-# log file. You may select from debug, verbose, #
-# default, sparse and none. #
-# allowhalfop - allows the +h channel mode #
-# allowprotect - allows the +a channel mode #
-# allowfounder - allows the +q channel mode #
-# #
+# prefixquit - a prefix for a client's quit message #
+# loglevel - specifies what detail of messages to log in the #
+# log file. You may select from debug, verbose, #
+# default, sparse and none. #
+# allowhalfop - allows the +h channel mode #
+# allowprotect - allows the +a channel mode #
+# allowfounder - allows the +q channel mode #
+# netbuffersize - size of the buffer used to receive data from #
+# clients. The ircd may only read() this amount #
+# of text in one go at any time. (OPTIONAL) #
<options prefixquit="Quit: "
loglevel="default"
+ netbuffersize="10240"
allowhalfop="yes"
allowprotect="yes"
allowfounder="yes">
diff --git a/include/users.h b/include/users.h
index dbb237c5f..c1a6aa3af 100644
--- a/include/users.h
+++ b/include/users.h
@@ -34,14 +34,26 @@ class Invited : public classbase
class ConnectClass : public classbase
{
public:
+ /** Type of line, either CC_ALLOW or CC_DENY
+ */
int type;
+ /** Max time to register the connection in seconds
+ */
int registration_timeout;
+ /** Number of lines in buffer before excess flood is triggered
+ */
+ int flood;
+ /** Host mask for this line
+ */
char host[MAXBUF];
+ /** (Optional) Password for this line
+ */
char pass[MAXBUF];
ConnectClass()
{
registration_timeout = 0;
+ flood = 0;
strcpy(host,"");
strcpy(pass,"");
}
@@ -113,8 +125,16 @@ class userrec : public connection
*/
char result[256];
- char carryover[MAXBUF];
+ /** Number of lines the user can place into the buffer
+ * (up to the global NetBufferSize bytes) before they
+ * are disconnected for excess flood
+ */
+ int flood;
+ /** Number of seconds this user is given to send USER/NICK
+ * If they do not send their details in this time limit they
+ * will be disconnected
+ */
unsigned long timeout;
userrec();
diff --git a/src/InspIRCd.layout b/src/InspIRCd.layout
index 3e666488f..6a8683441 100644
--- a/src/InspIRCd.layout
+++ b/src/InspIRCd.layout
@@ -1,6 +1,6 @@
[Editors]
-Focused=1
-Order=1,2,-1,4
+Focused=6
+Order=1,2,-1,4,6
[Editor_0]
Open=0
@@ -12,10 +12,10 @@ LeftChar=1
[Editor_1]
Open=1
-Top=1
-CursorCol=15
-CursorRow=5535
-TopLine=5513
+Top=0
+CursorCol=24
+CursorRow=1459
+TopLine=1431
LeftChar=1
[Editor_2]
@@ -51,11 +51,11 @@ TopLine=1
LeftChar=1
[Editor_6]
-Open=0
-Top=0
-CursorCol=1
-CursorRow=36
-TopLine=1
+Open=1
+Top=1
+CursorCol=2
+CursorRow=92
+TopLine=37
LeftChar=1
[Editor_7]
@@ -181,9 +181,9 @@ LeftChar=1
[Editor_22]
Open=1
Top=0
-CursorCol=25
-CursorRow=116
-TopLine=65
+CursorCol=5
+CursorRow=137
+TopLine=101
LeftChar=1
[Editor_23]
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 63aa079d8..81dee527e 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -75,6 +75,7 @@ int WHOWAS_STALE = 48; // default WHOWAS Entries last 2 days before they go 'sta
int WHOWAS_MAX = 100; // default 100 people maximum in the WHOWAS list
int DieDelay = 5;
time_t startup_time = time(NULL);
+int NetBufferSize = 10240; // NetBufferSize used as the buffer size for all read() ops
extern vector<Module*> modules;
vector<string> module_names;
@@ -382,7 +383,7 @@ void readfile(file_cache &F, const char* fname)
void ReadConfig(void)
{
- char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF];
+ char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF];
ConnectClass c;
LoadConf(CONFIG_FILE,&config_f);
@@ -401,6 +402,13 @@ void ReadConfig(void)
ConfValue("options","prefixquit",0,PrefixQuit,&config_f);
ConfValue("die","value",0,DieValue,&config_f);
ConfValue("options","loglevel",0,dbg,&config_f);
+ ConfValue("options","netbuffersize",0,NB,&config_f);
+ NetBufferSize = atoi(NB);
+ if ((!NetBufferSize) || (NetBufferSize > 65535) || (NetBufferSize < 1024))
+ {
+ log(DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
+ NetBufferSize = 10240;
+ }
if (!strcmp(dbg,"debug"))
LogLevel = DEBUG;
if (!strcmp(dbg,"verbose"))
@@ -421,6 +429,7 @@ void ReadConfig(void)
strcpy(Value,"");
ConfValue("connect","allow",i,Value,&config_f);
ConfValue("connect","timeout",i,timeout,&config_f);
+ ConfValue("connect","flood",i,flood,&config_f);
if (strcmp(Value,""))
{
strcpy(c.host,Value);
@@ -429,12 +438,13 @@ void ReadConfig(void)
ConfValue("connect","password",i,Value,&config_f);
strcpy(c.pass,Value);
c.registration_timeout = 90; // default is 2 minutes
+ c.flood = atoi(flood);
if (atoi(timeout)>0)
{
c.registration_timeout = atoi(timeout);
}
Classes.push_back(c);
- log(DEBUG,"Read connect class type ALLOW, host=%s password=%s",c.host,c.pass);
+ log(DEBUG,"Read connect class type ALLOW, host=%s password=%s timeout=%d flood=%d",c.host,c.pass,c.registration_timeout,c.flood);
}
else
{
@@ -3614,8 +3624,19 @@ void AddClient(int socket, char* host, int port, bool iscached)
break;
}
}
- log(DEBUG,"Client has a connection timeout value of %d",class_regtimeout);
+
+ int class_flood = 0;
+ for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++)
+ {
+ if (match(clientlist[tempnick]->host,i->host) && (i->type == CC_ALLOW))
+ {
+ class_flood = i->flood;
+ break;
+ }
+ }
+
clientlist[tempnick]->timeout = time(NULL)+class_regtimeout;
+ clientlist[tempnick]->flood = class_flood;
if (clientlist.size() == MAXCLIENTS)
kill_link(clientlist[tempnick],"No more connections allowed in this class");
@@ -4989,7 +5010,6 @@ void process_buffer(const char* cmdbuf,userrec *user)
log(DEFAULT,"*** BUG *** process_buffer was given an invalid parameter");
return;
}
- log(DEBUG,"A: %s",cmdbuf);
if (!strcmp(cmdbuf,""))
{
return;
@@ -4999,25 +5019,20 @@ void process_buffer(const char* cmdbuf,userrec *user)
{
return;
}
- log(DEBUG,"B: %s",cmd);
if ((cmd[strlen(cmd)-1] == 13) || (cmd[strlen(cmd)-1] == 10))
{
cmd[strlen(cmd)-1] = '\0';
}
- log(DEBUG,"C: %s",cmd);
if ((cmd[strlen(cmd)-1] == 13) || (cmd[strlen(cmd)-1] == 10))
{
cmd[strlen(cmd)-1] = '\0';
}
- log(DEBUG,"D: %s",cmd);
if (!strcmp(cmd,""))
{
return;
}
- log(DEBUG,"E: %s",cmd);
log(DEBUG,"InspIRCd: processing: %s %s",user->nick,cmd);
tidystring(cmd);
- log(DEBUG,"F: %s",cmd);
if ((user) && (cmd))
{
process_command(user,cmd);
@@ -5530,10 +5545,19 @@ int InspIRCd(void)
userrec* current = count2a->second;
int currfd = current->fd;
char* l = strtok(data,"\n");
+ int floodlines = 0;
while (l)
{
- char sanitized[10240];
- memset(sanitized, 0, 10240);
+ floodlines++;
+ if ((floodlines > current->flood) && (current->flood != 0))
+ {
+ log(DEFAULT,"Excess flood from: %s!%s@%s",current->nick,current->ident,current->host);
+ WriteOpers("*** Excess flood from: %s!%s@%s",current->nick,current->ident,current->host);
+ kill_link(current,"Excess flood");
+ goto label;
+ }
+ char sanitized[NetBufferSize];
+ memset(sanitized, 0, NetBufferSize);
int ptt = 0;
for (int pt = 0; pt < strlen(l); pt++)
{
@@ -5543,7 +5567,6 @@ int InspIRCd(void)
}
}
sanitized[ptt] = '\0';
- l = strtok(NULL,"\n");
if (strlen(sanitized))
{
@@ -5551,7 +5574,6 @@ int InspIRCd(void)
// we're gonna re-scan to check if the nick is gone, after every
// command - if it has, we're gonna bail
bool find_again = false;
- log(DEBUG,"\nProcess line: %s %d\n",sanitized,strlen(sanitized));
process_buffer(sanitized,current);
// look for the user's record in case it's changed
@@ -5569,6 +5591,7 @@ int InspIRCd(void)
goto label;
}
+ l = strtok(NULL,"\n");
}
goto label;
}
diff --git a/src/users.cpp b/src/users.cpp
index 4c7173e30..eb4954897 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -23,7 +23,7 @@ userrec::userrec()
strcpy(server,"");
strcpy(awaymsg,"");
fd = lastping = signon = idle_lastmsg = nping = registered = 0;
- port = bytes_in = bytes_out = cmds_in = cmds_out = 0;
+ flood = port = bytes_in = bytes_out = cmds_in = cmds_out = 0;
haspassed = false;
strcpy(result,"");
for (int i = 0; i < MAXCHANS; i++)
@@ -72,17 +72,21 @@ void userrec::InviteTo(char* channel)
void userrec::RemoveInvite(char* channel)
{
log(DEBUG,"Removing invites");
- if (invites.size())
+ if (channel)
{
- for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++)
- {
- if (i->channel) {
- if (!strcasecmp(i->channel,channel))
+ if (invites.size())
+ {
+ for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++)
+ {
+ if (i->channel)
{
- invites.erase(i);
- return;
- }
- }
+ if (!strcasecmp(i->channel,channel))
+ {
+ invites.erase(i);
+ return;
+ }
+ }
+ }
}
}
}