+extern ServerConfig *Config;
+extern InspIRCd* ServerInstance;
+extern int openSockfd[MAXSOCKS];
+extern time_t TIME;
+
+extern int MODCOUNT;
+extern std::vector<Module*> modules;
+extern std::vector<ircd_module*> factory;
+
+ServerConfig::ServerConfig()
+{
+ this->ClearStack();
+ *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;
+ MaxWhoResults = 100;
+ debugging = 0;
+ LogLevel = DEFAULT;
+ DieDelay = 5;
+}
+
+void ServerConfig::ClearStack()
+{
+ include_stack.clear();
+}
+
+Module* ServerConfig::GetIOHook(int port)
+{
+ std::map<int,Module*>::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<int,Module*>::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)
+{
+ /** 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();
+
+ if (!LoadConf(CONFIG_FILE,&Config->config_f,&errstr))
+ {
+ errstr.seekg(0);
+ log(DEFAULT,"There were errors in your configuration:\n%s",errstr.str().c_str());
+ if (bail)
+ {
+ printf("There were errors in your configuration:\n%s",errstr.str().c_str());
+ Exit(0);
+ }
+ else
+ {
+ char dataline[1024];
+ if (user)
+ {
+ WriteServ(user->fd,"NOTICE %s :There were errors in the configuration file:",user->nick);
+ while (!errstr.eof())
+ {
+ errstr.getline(dataline,1024);
+ WriteServ(user->fd,"NOTICE %s :%s",user->nick,dataline);
+ }
+ }
+ else
+ {
+ WriteOpers("There were errors in the configuration file:");
+ while (!errstr.eof())
+ {
+ errstr.getline(dataline,1024);
+ WriteOpers(dataline);
+ }
+ }
+ return;
+ }
+ }
+
+ /* 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);
+ ConfValue("admin","name",0,Config->AdminName,&Config->config_f);
+ ConfValue("admin","email",0,Config->AdminEmail,&Config->config_f);
+ ConfValue("admin","nick",0,Config->AdminNick,&Config->config_f);
+ ConfValue("files","motd",0,Config->motd,&Config->config_f);
+ ConfValue("files","rules",0,Config->rules,&Config->config_f);
+ ConfValue("power","diepass",0,Config->diepass,&Config->config_f);
+ ConfValue("power","pause",0,pauseval,&Config->config_f);
+ ConfValue("power","restartpass",0,Config->restartpass,&Config->config_f);
+ ConfValue("options","prefixquit",0,Config->PrefixQuit,&Config->config_f);
+ ConfValue("die","value",0,Config->DieValue,&Config->config_f);
+ ConfValue("options","loglevel",0,dbg,&Config->config_f);
+ ConfValue("options","netbuffersize",0,NB,&Config->config_f);
+ ConfValue("options","maxwho",0,MW,&Config->config_f);
+ ConfValue("options","allowhalfop",0,AH,&Config->config_f);
+ ConfValue("options","allowprotect",0,AP,&Config->config_f);
+ ConfValue("options","allowfounder",0,AF,&Config->config_f);
+ ConfValue("dns","server",0,Config->DNSServer,&Config->config_f);
+ ConfValue("dns","timeout",0,DNT,&Config->config_f);
+ ConfValue("options","moduledir",0,Config->ModPath,&Config->config_f);
+ 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: <options:maxtargets> 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: <options:softlimit> value is greater than %d or less than 0, set to %d.",MAXCLIENTS,MAXCLIENTS);
+ Config->SoftLimit = MAXCLIENTS;
+ }
+ Config->MaxConn = atoi(MCON);
+ if (Config->MaxConn > SOMAXCONN)
+ log(DEFAULT,"WARNING: <options:somaxconn> value may be higher than the system-defined SOMAXCONN value!");
+ Config->NetBufferSize = atoi(NB);
+ Config->MaxWhoResults = atoi(MW);
+ Config->dns_timeout = atoi(DNT);
+ if (!strchr(Config->ServerName,'.'))
+ {
+ log(DEFAULT,"WARNING: <server:name> '%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)
+ {
+ // attempt to look up their nameserver from /etc/resolv.conf
+ log(DEFAULT,"WARNING: <dns:server> 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,"<dns:server> 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")));
+ if ((!Config->NetBufferSize) || (Config->NetBufferSize > 65535) || (Config->NetBufferSize < 1024))
+ {
+ log(DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
+ Config->NetBufferSize = 10240;
+ }
+ if ((!Config->MaxWhoResults) || (Config->MaxWhoResults > 65535) || (Config->MaxWhoResults < 1))
+ {
+ log(DEFAULT,"No MaxWhoResults specified or size out of range, setting to default of 128.");
+ Config->MaxWhoResults = 128;
+ }
+ Config->LogLevel = DEFAULT;
+ if (!strcmp(dbg,"debug"))
+ {
+ Config->LogLevel = DEBUG;
+ Config->debugging = 1;
+ }
+ if (!strcmp(dbg,"verbose"))
+ Config->LogLevel = VERBOSE;
+ if (!strcmp(dbg,"default"))
+ Config->LogLevel = DEFAULT;
+ if (!strcmp(dbg,"sparse"))
+ Config->LogLevel = SPARSE;
+ if (!strcmp(dbg,"none"))
+ Config->LogLevel = NONE;
+
+ readfile(Config->MOTD,Config->motd);
+ log(DEFAULT,"Reading message of the day...");
+ readfile(Config->RULES,Config->rules);
+ log(DEFAULT,"Reading connect classes...");
+ Classes.clear();
+ for (int i = 0; i < ConfValueEnum("connect",&Config->config_f); i++)
+ {
+ *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);
+ ConfValue("connect","pingfreq",i,pfreq,&Config->config_f);
+ 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;
+ c.type = CC_ALLOW;
+ strlcpy(Value,"",MAXBUF);
+ ConfValue("connect","password",i,Value,&Config->config_f);
+ 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);
+ }
+ if (atoi(rqmax)>0)
+ {
+ c.recvqmax = atoi(rqmax);
+ }
+ if (atoi(timeout)>0)
+ {
+ c.registration_timeout = atoi(timeout);
+ }
+ if (atoi(pfreq)>0)
+ {
+ c.pingtime = atoi(pfreq);
+ }
+ Classes.push_back(c);
+ }
+ else
+ {
+ ConfValue("connect","deny",i,Value,&Config->config_f);
+ c.host = Value;
+ c.type = CC_DENY;
+ Classes.push_back(c);
+ log(DEBUG,"Read connect class type DENY, host=%s",c.host.c_str());
+ }
+
+ }
+ log(DEFAULT,"Reading K lines,Q lines and Z lines from config...");
+ read_xline_defaults();
+ log(DEFAULT,"Applying K lines, Q lines and Z lines...");
+ apply_lines(APPLY_ALL);
+
+ ConfValue("pid","file",0,Config->PID,&Config->config_f);
+ // write once here, to try it out and make sure its ok
+ WritePID(Config->PID);