X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Finspircd_io.cpp;h=aee8abe88d2ecc57c1814a71091a4f1aa50dadbd;hb=59b1a8955142935b02af6446005ab47fc7c3fc8c;hp=b1e90bfd0b7c0eb296bd5d72271bef9cb1d5d3b6;hpb=03b51e9cb691848f9906e7dc8dca4894c60e5bcc;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/inspircd_io.cpp b/src/inspircd_io.cpp index b1e90bfd0..aee8abe88 100644 --- a/src/inspircd_io.cpp +++ b/src/inspircd_io.cpp @@ -2,7 +2,7 @@ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * - * Inspire is copyright (C) 2002-2004 ChatSpike-Dev. + * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev. * E-mail: * * @@ -29,6 +29,7 @@ using namespace std; #include "inspircd_io.h" #include "inspstring.h" #include "helperfuncs.h" +#include "userprocess.h" #include "xline.h" extern ServerConfig *Config; @@ -36,19 +37,24 @@ extern InspIRCd* ServerInstance; extern int openSockfd[MAXSOCKS]; extern time_t TIME; +extern int MODCOUNT; +extern std::vector modules; +extern std::vector factory; ServerConfig::ServerConfig() { this->ClearStack(); - *ServerName = *Network = *ServerDesc = *AdminName = '\0'; - *AdminEmail = *AdminNick = *diepass = *restartpass = '\0'; - *motd = *rules = *PrefixQuit = *DieValue = *DNSServer = '\0'; - *ModPath = *MyExecutable = *DisabledCommands = *PID = '\0'; + *TempDir = *ServerName = *Network = *ServerDesc = *AdminName = '\0'; + *HideWhoisServer = *AdminEmail = *AdminNick = *diepass = *restartpass = '\0'; + *CustomVersion = *motd = *rules = *PrefixQuit = *DieValue = *DNSServer = '\0'; + *OperOnlyStats = *ModPath = *MyExecutable = *DisabledCommands = *PID = '\0'; log_file = NULL; nofork = false; unlimitcore = false; AllowHalfop = true; + HideSplits = false; dns_timeout = 5; + MaxTargets = 20; NetBufferSize = 10240; SoftLimit = MAXCLIENTS; MaxConn = SOMAXCONN; @@ -63,11 +69,98 @@ void ServerConfig::ClearStack() include_stack.clear(); } +Module* ServerConfig::GetIOHook(int port) +{ + std::map::iterator x = IOHookModule.find(port); + return (x != IOHookModule.end() ? x->second : NULL); +} + +bool ServerConfig::AddIOHook(int port, Module* iomod) +{ + if (!GetIOHook(port)) + { + IOHookModule[port] = iomod; + return true; + } + else + { + ModuleException err("Port already hooked by another module"); + throw(err); + return false; + } +} + +bool ServerConfig::DelIOHook(int port) +{ + std::map::iterator x = IOHookModule.find(port); + if (x != IOHookModule.end()) + { + IOHookModule.erase(x); + return true; + } + return false; +} + +bool ServerConfig::CheckOnce(char* tag, bool bail, userrec* user) +{ + int count = ConfValueEnum(tag,&Config->config_f); + if (count > 1) + { + if (bail) + { + printf("There were errors in your configuration:\nYou have more than one <%s> tag, this is not permitted.\n",tag); + Exit(0); + } + else + { + if (user) + { + WriteServ(user->fd,"There were errors in your configuration:"); + WriteServ(user->fd,"You have more than one <%s> tag, this is not permitted.\n",tag); + } + else + { + WriteOpers("There were errors in the configuration file:"); + WriteOpers("You have more than one <%s> tag, this is not permitted.\n",tag); + } + } + return false; + } + if (count < 1) + { + if (bail) + { + printf("There were errors in your configuration:\nYou have not defined a <%s> tag, this is required.\n",tag); + Exit(0); + } + else + { + if (user) + { + WriteServ(user->fd,"There were errors in your configuration:"); + WriteServ(user->fd,"You have not defined a <%s> tag, this is required.",tag); + } + else + { + WriteOpers("There were errors in the configuration file:"); + WriteOpers("You have not defined a <%s> tag, this is required.",tag); + } + } + return false; + } + return true; +} void ServerConfig::Read(bool bail, userrec* user) { - char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF],MW[MAXBUF],MCON[MAXBUF]; + /** Yes yes, i know, this function is craq worthy of + * sirv. Its a mess, and some day i will tidy it. + * ...But that day will not be today. or probaby not + * tomorrow even, because it works fine. + */ + 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],HS[MAXBUF]; ConnectClass c; std::stringstream errstr; include_stack.clear(); @@ -106,6 +199,14 @@ void ServerConfig::Read(bool bail, userrec* user) } } + /* Check we dont have more than one of singular tags + */ + if (!CheckOnce("server",bail,user) || !CheckOnce("admin",bail,user) || !CheckOnce("files",bail,user) + || !CheckOnce("power",bail,user) || !CheckOnce("options",bail,user) || !CheckOnce("pid",bail,user)) + { + return; + } + ConfValue("server","name",0,Config->ServerName,&Config->config_f); ConfValue("server","description",0,Config->ServerDesc,&Config->config_f); ConfValue("server","network",0,Config->Network,&Config->config_f); @@ -131,8 +232,24 @@ void ServerConfig::Read(bool bail, userrec* user) ConfValue("disabled","commands",0,Config->DisabledCommands,&Config->config_f); ConfValue("options","somaxconn",0,MCON,&Config->config_f); ConfValue("options","softlimit",0,SLIMT,&Config->config_f); - + ConfValue("options","operonlystats",0,Config->OperOnlyStats,&Config->config_f); + ConfValue("options","customversion",0,Config->CustomVersion,&Config->config_f); + ConfValue("options","maxtargets",0,MT,&Config->config_f); + ConfValue("options","hidesplits",0,HS,&Config->config_f); + ConfValue("options","hidewhois",0,Config->HideWhoisServer,&Config->config_f); + ConfValue("options","tempdir",0,Config->TempDir,&Config->config_f); + + if (!*Config->TempDir) + strlcpy(Config->TempDir,"/tmp",1024); + Config->HideSplits = ((*HS == 'y') || (*HS == 'Y') || (*HS == '1') || (*HS == 't') || (*HS == 'T')); Config->SoftLimit = atoi(SLIMT); + if (*MT) + Config->MaxTargets = atoi(MT); + if ((Config->MaxTargets < 0) || (Config->MaxTargets > 31)) + { + log(DEFAULT,"WARNING: value is greater than 31 or less than 0, set to 20."); + Config->MaxTargets = 20; + } if ((Config->SoftLimit < 1) || (Config->SoftLimit > MAXCLIENTS)) { log(DEFAULT,"WARNING: value is greater than %d or less than 0, set to %d.",MAXCLIENTS,MAXCLIENTS); @@ -144,12 +261,46 @@ void ServerConfig::Read(bool bail, userrec* user) Config->NetBufferSize = atoi(NB); Config->MaxWhoResults = atoi(MW); Config->dns_timeout = atoi(DNT); + if (!strchr(Config->ServerName,'.')) + { + log(DEFAULT,"WARNING: '%s' is not a fully-qualified domain name. Changed to '%s%c'",Config->ServerName,Config->ServerName,'.'); + strlcat(Config->ServerName,".",MAXBUF); + } if (!Config->dns_timeout) Config->dns_timeout = 5; if (!Config->MaxConn) Config->MaxConn = SOMAXCONN; if (!*Config->DNSServer) - strlcpy(Config->DNSServer,"127.0.0.1",MAXBUF); + { + // attempt to look up their nameserver from /etc/resolv.conf + log(DEFAULT,"WARNING: not defined, attempting to find working server in /etc/resolv.conf..."); + ifstream resolv("/etc/resolv.conf"); + std::string nameserver; + bool found_server = false; + if (resolv.is_open()) + { + while (resolv >> nameserver) + { + if ((nameserver == "nameserver") && (!found_server)) + { + resolv >> nameserver; + strlcpy(Config->DNSServer,nameserver.c_str(),MAXBUF); + found_server = true; + log(DEFAULT," set to '%s' as first resolver in /etc/resolv.conf.",nameserver.c_str()); + } + } + if (!found_server) + { + log(DEFAULT,"/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!"); + strlcpy(Config->DNSServer,"127.0.0.1",MAXBUF); + } + } + else + { + log(DEFAULT,"/etc/resolv.conf can't be opened! Defaulting to nameserver '127.0.0.1'!"); + strlcpy(Config->DNSServer,"127.0.0.1",MAXBUF); + } + } if (!*Config->ModPath) strlcpy(Config->ModPath,MOD_PATH,MAXBUF); Config->AllowHalfop = ((!strcasecmp(AH,"true")) || (!strcasecmp(AH,"1")) || (!strcasecmp(AH,"yes"))); @@ -185,7 +336,7 @@ void ServerConfig::Read(bool bail, userrec* user) Classes.clear(); for (int i = 0; i < ConfValueEnum("connect",&Config->config_f); i++) { - strcpy(Value,""); + *Value = 0; ConfValue("connect","allow",i,Value,&Config->config_f); ConfValue("connect","timeout",i,timeout,&Config->config_f); ConfValue("connect","flood",i,flood,&Config->config_f); @@ -193,23 +344,41 @@ 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) { - strlcpy(c.host,Value,MAXBUF); + c.host = Value; c.type = CC_ALLOW; strlcpy(Value,"",MAXBUF); ConfValue("connect","password",i,Value,&Config->config_f); - strlcpy(c.pass,Value,MAXBUF); + c.pass = Value; c.registration_timeout = 90; // default is 2 minutes c.pingtime = 120; c.flood = atoi(flood); 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); } + else + { + c.threshold = 1; + c.flood = 999; + log(DEFAULT,"Warning: Connect allow line '%s' has no flood/threshold settings. Setting this tag to 999 lines in 1 second.",c.host.c_str()); + } if (atoi(sqmax)>0) { c.sendqmax = atoi(sqmax); @@ -231,10 +400,10 @@ void ServerConfig::Read(bool bail, userrec* user) else { ConfValue("connect","deny",i,Value,&Config->config_f); - strlcpy(c.host,Value,MAXBUF); + c.host = Value; c.type = CC_DENY; Classes.push_back(c); - log(DEBUG,"Read connect class type DENY, host=%s",c.host); + log(DEBUG,"Read connect class type DENY, host=%s",c.host.c_str()); } } @@ -300,12 +469,14 @@ void ServerConfig::Read(bool bail, userrec* user) if (ServerInstance->UnloadModule(removing->c_str())) { WriteOpers("*** REHASH UNLOADED MODULE: %s",removing->c_str()); - WriteServ(user->fd,"973 %s %s :Module %s successfully unloaded.",user->nick, removing->c_str(), removing->c_str()); + if (user) + WriteServ(user->fd,"973 %s %s :Module %s successfully unloaded.",user->nick, removing->c_str(), removing->c_str()); rem++; } else { - WriteServ(user->fd,"972 %s %s :Failed to unload module %s: %s",user->nick, removing->c_str(), removing->c_str(), ServerInstance->ModuleError()); + if (user) + WriteServ(user->fd,"972 %s %s :Failed to unload module %s: %s",user->nick, removing->c_str(), removing->c_str(), ServerInstance->ModuleError()); } } if (!added_modules.empty()) @@ -314,12 +485,14 @@ void ServerConfig::Read(bool bail, userrec* user) if (ServerInstance->LoadModule(adding->c_str())) { WriteOpers("*** REHASH LOADED MODULE: %s",adding->c_str()); - WriteServ(user->fd,"975 %s %s :Module %s successfully loaded.",user->nick, adding->c_str(), adding->c_str()); + if (user) + WriteServ(user->fd,"975 %s %s :Module %s successfully loaded.",user->nick, adding->c_str(), adding->c_str()); add++; } else { - WriteServ(user->fd,"974 %s %s :Failed to load module %s: %s",user->nick, adding->c_str(), adding->c_str(), ServerInstance->ModuleError()); + if (user) + WriteServ(user->fd,"974 %s %s :Failed to load module %s: %s",user->nick, adding->c_str(), adding->c_str(), ServerInstance->ModuleError()); } } log(DEFAULT,"Successfully unloaded %lu of %lu modules and loaded %lu of %lu modules.",(unsigned long)rem,(unsigned long)removed_modules.size(), @@ -344,10 +517,21 @@ void Killed(int status) exit(status); } +char* CleanFilename(char* name) +{ + char* p = name + strlen(name); + while ((p != name) && (*p != '/')) p--; + return (p != name ? ++p : p); +} + + void Rehash(int status) { - WriteOpers("Rehashing config file %s due to SIGHUP",CONFIG_FILE); + WriteOpers("Rehashing config file %s due to SIGHUP",CleanFilename(CONFIG_FILE)); + fclose(Config->log_file); + OpenLog(NULL,0); Config->Read(false,NULL); + FOREACH_MOD(I_OnRehash,OnRehash("")); } @@ -378,15 +562,19 @@ void WritePID(std::string filename) } } - -int DaemonSeed (void) +void SetSignals() { - int childpid; signal (SIGALRM, SIG_IGN); signal (SIGHUP, Rehash); signal (SIGPIPE, SIG_IGN); signal (SIGTERM, Exit); signal (SIGSEGV, Error); +} + + +int DaemonSeed (void) +{ + int childpid; if ((childpid = fork ()) < 0) return (ERROR); else if (childpid > 0) @@ -464,11 +652,11 @@ std::string ServerConfig::ConfProcess(char* buffer, long linenumber, std::string return ""; } // firstly clean up the line by stripping spaces from the start and end and converting tabs to spaces - for (unsigned int d = 0; d < strlen(buffer); d++) - if ((buffer[d]) == 9) - buffer[d] = ' '; - while ((buffer[0] == ' ') && (strlen(buffer)>0)) buffer++; - while ((buffer[strlen(buffer)-1] == ' ') && (strlen(buffer)>0)) buffer[strlen(buffer)-1] = '\0'; + for (char* d = buffer; *d; d++) + if (*d == 9) + *d = ' '; + while (*buffer == ' ') buffer++; + while ((buffer[strlen(buffer)-1] == ' ') && (*buffer)) buffer[strlen(buffer)-1] = '\0'; // empty lines are syntactically valid, as are comments if (!(*buffer) || buffer[0] == '#') @@ -636,7 +824,7 @@ bool ServerConfig::LoadConf(const char* filename, std::stringstream *target, std break; } } - log(DEFAULT,"Opening included file '%s'",buf); + log(DEBUG,"Opening included file '%s'",buf); if (*buf != '/') { strlcpy(confpath,CONFIG_FILE,10240); @@ -647,7 +835,7 @@ bool ServerConfig::LoadConf(const char* filename, std::stringstream *target, std } snprintf(newconf,10240,"%s/%s",confpath,buf); } - else snprintf(newconf,10240,"%s",buf); + else strlcpy(newconf,buf,10240); std::stringstream merge(stringstream::in | stringstream::out); // recursively call LoadConf and get the new data, use the same errorstream if (LoadConf(newconf, &merge, errorstream)) @@ -910,7 +1098,7 @@ int ServerConfig::ReadConf(std::stringstream *config, const char* tag, const cha if (!key) { /* value not found in tag */ - strcpy(result,""); + *result = 0; return 0; } else @@ -921,7 +1109,7 @@ int ServerConfig::ReadConf(std::stringstream *config, const char* tag, const cha if (!*key) { /* missing quote */ - strcpy(result,""); + *result = 0; return 0; } key++; @@ -959,7 +1147,7 @@ int ServerConfig::ReadConf(std::stringstream *config, const char* tag, const cha } } } - strcpy(result,""); // value or its tag not found at all + *result = 0; // value or its tag not found at all return 0; } @@ -1032,7 +1220,7 @@ int BindPorts() Config->ConfValue("bind","port",count,configToken,&Config->config_f); Config->ConfValue("bind","address",count,Addr,&Config->config_f); Config->ConfValue("bind","type",count,Type,&Config->config_f); - if (strcmp(Type,"servers")) + if ((!*Type) || (!strcmp(Type,"clients"))) { // modules handle server bind types now, // its not a typo in the strcmp.