]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/configreader.cpp
Update m_cloaking to use free-form keys instead of weakening the hash IV
[user/henk/code/inspircd.git] / src / configreader.cpp
index 159ca598fce99bb6f24c7a40015f624ef12c7beb..05171ea60d605de4b093ccf0df8ec2d6d57f236f 100644 (file)
 #include "commands/cmd_whowas.h"
 #include "modes/cmode_h.h"
 
-ServerConfig::ServerConfig(InspIRCd* Instance) : ServerInstance(Instance)
+ServerConfig::ServerConfig()
 {
-       *sid = *ServerName = *Network = *ServerDesc = *AdminName = '\0';
-       *HideWhoisServer = *AdminEmail = *AdminNick = *diepass = *restartpass = *FixedQuit = *HideKillsServer = '\0';
-       *DefaultModes = *CustomVersion = *motd = *rules = *PrefixQuit = *DieValue = *DNSServer = '\0';
-       *UserStats = *DisabledCommands = *SuffixQuit = '\0';
        WhoWasGroupSize = WhoWasMaxGroups = WhoWasMaxKeep = 0;
        log_file = NULL;
        NoUserDns = forcedebug = OperSpyWhois = nofork = HideBans = HideSplits = UndernetMsgPrefix = false;
@@ -45,7 +41,7 @@ ServerConfig::ServerConfig(InspIRCd* Instance) : ServerInstance(Instance)
        dns_timeout = DieDelay = 5;
        MaxTargets = 20;
        NetBufferSize = 10240;
-       SoftLimit = Instance->SE->GetMaxFds();
+       SoftLimit = ServerInstance->SE->GetMaxFds();
        MaxConn = SOMAXCONN;
        MaxWhoResults = 0;
        debugging = 0;
@@ -199,7 +195,7 @@ static bool ValidateMaxTargets(ServerConfig* conf, const char*, const char*, Val
 {
        if ((data.GetInteger() < 1) || (data.GetInteger() > 31))
        {
-               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <security:maxtargets> value is greater than 31 or less than 1, set to 20.");
+               ServerInstance->Logs->Log("CONFIG",DEFAULT,"WARNING: <security:maxtargets> value is greater than 31 or less than 1, set to 20.");
                data.Set(20);
        }
        return true;
@@ -207,10 +203,10 @@ static bool ValidateMaxTargets(ServerConfig* conf, const char*, const char*, Val
 
 static bool ValidateSoftLimit(ServerConfig* conf, const char*, const char*, ValueItem &data)
 {
-       if ((data.GetInteger() < 1) || (data.GetInteger() > conf->GetInstance()->SE->GetMaxFds()))
+       if ((data.GetInteger() < 1) || (data.GetInteger() > ServerInstance->SE->GetMaxFds()))
        {
-               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <performance:softlimit> value is greater than %d or less than 0, set to %d.",conf->GetInstance()->SE->GetMaxFds(),conf->GetInstance()->SE->GetMaxFds());
-               data.Set(conf->GetInstance()->SE->GetMaxFds());
+               ServerInstance->Logs->Log("CONFIG",DEFAULT,"WARNING: <performance:softlimit> value is greater than %d or less than 0, set to %d.",ServerInstance->SE->GetMaxFds(),ServerInstance->SE->GetMaxFds());
+               data.Set(ServerInstance->SE->GetMaxFds());
        }
        return true;
 }
@@ -218,11 +214,11 @@ static bool ValidateSoftLimit(ServerConfig* conf, const char*, const char*, Valu
 static bool ValidateMaxConn(ServerConfig* conf, const char*, const char*, ValueItem &data)
 {
        if (data.GetInteger() > SOMAXCONN)
-               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <performance:somaxconn> value may be higher than the system-defined SOMAXCONN value!");
+               ServerInstance->Logs->Log("CONFIG",DEFAULT,"WARNING: <performance:somaxconn> value may be higher than the system-defined SOMAXCONN value!");
        return true;
 }
 
-bool ServerConfig::ApplyDisabledCommands(const char* data)
+bool ServerConfig::ApplyDisabledCommands(const std::string& data)
 {
        std::stringstream dcmds(data);
        std::string thiscmd;
@@ -275,7 +271,7 @@ static bool ValidateDnsServer(ServerConfig* conf, const char*, const char*, Valu
        {
                std::string nameserver;
                // attempt to look up their nameserver from /etc/resolv.conf
-               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in /etc/resolv.conf...");
+               ServerInstance->Logs->Log("CONFIG",DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in /etc/resolv.conf...");
                std::ifstream resolv("/etc/resolv.conf");
                bool found_server = false;
 
@@ -288,19 +284,19 @@ static bool ValidateDnsServer(ServerConfig* conf, const char*, const char*, Valu
                                        resolv >> nameserver;
                                        data.Set(nameserver.c_str());
                                        found_server = true;
-                                       conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"<dns:server> set to '%s' as first resolver in /etc/resolv.conf.",nameserver.c_str());
+                                       ServerInstance->Logs->Log("CONFIG",DEFAULT,"<dns:server> set to '%s' as first resolver in /etc/resolv.conf.",nameserver.c_str());
                                }
                        }
 
                        if (!found_server)
                        {
-                               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!");
+                               ServerInstance->Logs->Log("CONFIG",DEFAULT,"/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!");
                                data.Set("127.0.0.1");
                        }
                }
                else
                {
-                       conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"/etc/resolv.conf can't be opened! Defaulting to nameserver '127.0.0.1'!");
+                       ServerInstance->Logs->Log("CONFIG",DEFAULT,"/etc/resolv.conf can't be opened! Defaulting to nameserver '127.0.0.1'!");
                        data.Set("127.0.0.1");
                }
        }
@@ -310,11 +306,11 @@ static bool ValidateDnsServer(ServerConfig* conf, const char*, const char*, Valu
 
 static bool ValidateServerName(ServerConfig* conf, const char*, const char*, ValueItem &data)
 {
-       conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Validating server name");
+       ServerInstance->Logs->Log("CONFIG",DEFAULT,"Validating server name");
        /* If we already have a servername, and they changed it, we should throw an exception. */
        if (!strchr(data.GetString(), '.'))
        {
-               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <server:name> '%s' is not a fully-qualified domain name. Changed to '%s.'",
+               ServerInstance->Logs->Log("CONFIG",DEFAULT,"WARNING: <server:name> '%s' is not a fully-qualified domain name. Changed to '%s.'",
                        data.GetString(),data.GetString());
                std::string moo = data.GetValue();
                data.Set(moo.append("."));
@@ -328,7 +324,7 @@ static bool ValidateNetBufferSize(ServerConfig* conf, const char*, const char*,
        // 65534 not 65535 because of null terminator
        if ((!data.GetInteger()) || (data.GetInteger() > 65534) || (data.GetInteger() < 1024))
        {
-               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
+               ServerInstance->Logs->Log("CONFIG",DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
                data.Set(10240);
        }
        return true;
@@ -338,22 +334,22 @@ static bool ValidateMaxWho(ServerConfig* conf, const char*, const char*, ValueIt
 {
        if ((data.GetInteger() > 65535) || (data.GetInteger() < 1))
        {
-               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"<performance:maxwho> size out of range, setting to default of 128.");
-               data.Set(128);
+               ServerInstance->Logs->Log("CONFIG",DEFAULT,"<performance:maxwho> size out of range, setting to default of 1024.");
+               data.Set(1024);
        }
        return true;
 }
 
 static bool ValidateHalfOp(ServerConfig* conf, const char*, const char*, ValueItem &data)
 {
-       ModeHandler* mh = conf->GetInstance()->Modes->FindMode('h', MODETYPE_CHANNEL);
+       ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL);
        if (data.GetBool() && !mh) {
-               conf->GetInstance()->Logs->Log("CONFIG", DEFAULT, "Enabling halfop mode.");
-               mh = new ModeChannelHalfOp(conf->GetInstance());
-               conf->GetInstance()->Modes->AddMode(mh);
+               ServerInstance->Logs->Log("CONFIG", DEFAULT, "Enabling halfop mode.");
+               mh = new ModeChannelHalfOp;
+               ServerInstance->Modes->AddMode(mh);
        } else if (!data.GetBool() && mh) {
-               conf->GetInstance()->Logs->Log("CONFIG", DEFAULT, "Disabling halfop mode.");
-               conf->GetInstance()->Modes->DelMode(mh);
+               ServerInstance->Logs->Log("CONFIG", DEFAULT, "Disabling halfop mode.");
+               ServerInstance->Modes->DelMode(mh);
                delete mh;
        }
        return true;
@@ -412,23 +408,23 @@ static bool ValidateInvite(ServerConfig* conf, const char*, const char*, ValueIt
 
 static bool ValidateSID(ServerConfig* conf, const char*, const char*, ValueItem &data)
 {
-       conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Validating server id");
+       ServerInstance->Logs->Log("CONFIG",DEFAULT,"Validating server id");
 
        const char *sid = data.GetString();
 
-       if (*sid && !conf->GetInstance()->IsSID(sid))
+       if (*sid && !ServerInstance->IsSID(sid))
        {
                throw CoreException(std::string(sid) + " is not a valid server ID. A server ID must be 3 characters long, with the first character a digit and the next two characters a digit or letter.");
        }
 
-       strlcpy(conf->sid, sid, 5);
+       conf->sid = sid;
 
        return true;
 }
 
 static bool ValidateWhoWas(ServerConfig* conf, const char*, const char*, ValueItem &data)
 {
-       conf->WhoWasMaxKeep = conf->GetInstance()->Duration(data.GetString());
+       conf->WhoWasMaxKeep = ServerInstance->Duration(data.GetString());
 
        if (conf->WhoWasGroupSize < 0)
                conf->WhoWasGroupSize = 0;
@@ -439,10 +435,10 @@ static bool ValidateWhoWas(ServerConfig* conf, const char*, const char*, ValueIt
        if (conf->WhoWasMaxKeep < 3600)
        {
                conf->WhoWasMaxKeep = 3600;
-               conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <whowas:maxkeep> value less than 3600, setting to default 3600");
+               ServerInstance->Logs->Log("CONFIG",DEFAULT,"WARNING: <whowas:maxkeep> value less than 3600, setting to default 3600");
        }
 
-       Module* whowas = conf->GetInstance()->Modules->Find("cmd_whowas.so");
+       Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so");
        if (whowas)
        {
                WhowasRequest(NULL, whowas, WhowasRequest::WHOWAS_PRUNE).Send();
@@ -476,8 +472,8 @@ static bool DoZLine(ServerConfig* conf, const char* tag, const char** entries, V
        const char* reason = values[0].GetString();
        const char* ipmask = values[1].GetString();
 
-       ZLine* zl = new ZLine(conf->GetInstance(), conf->GetInstance()->Time(), 0, "<Config>", reason, ipmask);
-       if (!conf->GetInstance()->XLines->AddLine(zl, NULL))
+       ZLine* zl = new ZLine(ServerInstance->Time(), 0, "<Config>", reason, ipmask);
+       if (!ServerInstance->XLines->AddLine(zl, NULL))
                delete zl;
 
        return true;
@@ -488,8 +484,8 @@ static bool DoQLine(ServerConfig* conf, const char* tag, const char** entries, V
        const char* reason = values[0].GetString();
        const char* nick = values[1].GetString();
 
-       QLine* ql = new QLine(conf->GetInstance(), conf->GetInstance()->Time(), 0, "<Config>", reason, nick);
-       if (!conf->GetInstance()->XLines->AddLine(ql, NULL))
+       QLine* ql = new QLine(ServerInstance->Time(), 0, "<Config>", reason, nick);
+       if (!ServerInstance->XLines->AddLine(ql, NULL))
                delete ql;
 
        return true;
@@ -500,11 +496,11 @@ static bool DoKLine(ServerConfig* conf, const char* tag, const char** entries, V
        const char* reason = values[0].GetString();
        const char* host = values[1].GetString();
 
-       XLineManager* xlm = conf->GetInstance()->XLines;
+       XLineManager* xlm = ServerInstance->XLines;
 
        IdentHostPair ih = xlm->IdentSplit(host);
 
-       KLine* kl = new KLine(conf->GetInstance(), conf->GetInstance()->Time(), 0, "<Config>", reason, ih.first.c_str(), ih.second.c_str());
+       KLine* kl = new KLine(ServerInstance->Time(), 0, "<Config>", reason, ih.first.c_str(), ih.second.c_str());
        if (!xlm->AddLine(kl, NULL))
                delete kl;
        return true;
@@ -515,11 +511,11 @@ static bool DoELine(ServerConfig* conf, const char* tag, const char** entries, V
        const char* reason = values[0].GetString();
        const char* host = values[1].GetString();
 
-       XLineManager* xlm = conf->GetInstance()->XLines;
+       XLineManager* xlm = ServerInstance->XLines;
 
        IdentHostPair ih = xlm->IdentSplit(host);
 
-       ELine* el = new ELine(conf->GetInstance(), conf->GetInstance()->Time(), 0, "<Config>", reason, ih.first.c_str(), ih.second.c_str());
+       ELine* el = new ELine(ServerInstance->Time(), 0, "<Config>", reason, ih.first.c_str(), ih.second.c_str());
        if (!xlm->AddLine(el, NULL))
                delete el;
        return true;
@@ -688,7 +684,19 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
                        if (ConfValue("connect", "pingfreq", i, tmpv, false))
                                me->pingtime = atol(tmpv.c_str());
                        if (ConfValue("connect", "sendq", i, tmpv, false))
-                               me->sendqmax = atol(tmpv.c_str());
+                       {
+                               // attempt to guess a good hard/soft sendq from a single value
+                               long value = atol(tmpv.c_str());
+                               if (value > 16384)
+                                       me->softsendqmax = value / 16;
+                               else
+                                       me->softsendqmax = value;
+                               me->hardsendqmax = value * 8;
+                       }
+                       if (ConfValue("connect", "softsendq", i, tmpv, false))
+                               me->softsendqmax = atol(tmpv.c_str());
+                       if (ConfValue("connect", "hardsendq", i, tmpv, false))
+                               me->hardsendqmax = atol(tmpv.c_str());
                        if (ConfValue("connect", "recvq", i, tmpv, false))
                                me->recvqmax = atol(tmpv.c_str());
                        if (ConfValue("connect", "localmax", i, tmpv, false))
@@ -715,11 +723,6 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
                        Classes[i] = me;
                }
        }
-
-       for(ClassMap::iterator toRemove = oldBlocksByMask.begin(); toRemove != oldBlocksByMask.end(); toRemove++)
-       {
-               removed_classes.push_back(toRemove->second);
-       }
 }
 
 
@@ -749,45 +752,45 @@ static const Deprecated ChangedConfig[] = {
 static const InitialConfig Values[] = {
        {"performance", "softlimit",    "0",                    new ValueContainerUInt (&ServerConfig::SoftLimit),              DT_INTEGER,  ValidateSoftLimit},
        {"performance", "somaxconn",    SOMAXCONN_S,            new ValueContainerInt  (&ServerConfig::MaxConn),                DT_INTEGER,  ValidateMaxConn},
-       {"options",     "moronbanner",  "You're banned!",       new ValueContainerChar (&ServerConfig::MoronBanner),            DT_CHARPTR,  NULL},
-       {"server",      "name",         "",                     new ValueContainerChar (&ServerConfig::ServerName),             DT_HOSTNAME, ValidateServerName},
-       {"server",      "description",  "Configure Me",         new ValueContainerChar (&ServerConfig::ServerDesc),             DT_CHARPTR,  NULL},
-       {"server",      "network",      "Network",              new ValueContainerChar (&ServerConfig::Network),                        DT_NOSPACES, NULL},
-       {"server",      "id",           "",                     new ValueContainerChar (&ServerConfig::sid),                    DT_CHARPTR,  ValidateSID},
-       {"admin",       "name",         "",                     new ValueContainerChar (&ServerConfig::AdminName),              DT_CHARPTR,  NULL},
-       {"admin",       "email",        "Mis@configu.red",      new ValueContainerChar (&ServerConfig::AdminEmail),             DT_CHARPTR,  NULL},
-       {"admin",       "nick",         "Misconfigured",        new ValueContainerChar (&ServerConfig::AdminNick),              DT_CHARPTR,  NULL},
-       {"files",       "motd",         "",                     new ValueContainerChar (&ServerConfig::motd),                   DT_CHARPTR,  ValidateMotd},
-       {"files",       "rules",        "",                     new ValueContainerChar (&ServerConfig::rules),                  DT_CHARPTR,  ValidateRules},
-       {"power",       "diepass",      "",                     new ValueContainerChar (&ServerConfig::diepass),                        DT_CHARPTR,  ValidateNotEmpty},
+       {"options",     "moronbanner",  "You're banned!",       new ValueContainerString (&ServerConfig::MoronBanner),          DT_CHARPTR,  NULL},
+       {"server",      "name",         "",                     new ValueContainerString (&ServerConfig::ServerName),           DT_HOSTNAME, ValidateServerName},
+       {"server",      "description",  "Configure Me",         new ValueContainerString (&ServerConfig::ServerDesc),           DT_CHARPTR,  NULL},
+       {"server",      "network",      "Network",              new ValueContainerString (&ServerConfig::Network),                      DT_NOSPACES, NULL},
+       {"server",      "id",           "",                     new ValueContainerString (&ServerConfig::sid),                  DT_CHARPTR,  ValidateSID},
+       {"admin",       "name",         "",                     new ValueContainerString (&ServerConfig::AdminName),            DT_CHARPTR,  NULL},
+       {"admin",       "email",        "Mis@configu.red",      new ValueContainerString (&ServerConfig::AdminEmail),           DT_CHARPTR,  NULL},
+       {"admin",       "nick",         "Misconfigured",        new ValueContainerString (&ServerConfig::AdminNick),            DT_CHARPTR,  NULL},
+       {"files",       "motd",         "",                     new ValueContainerString (&ServerConfig::motd),                 DT_CHARPTR,  ValidateMotd},
+       {"files",       "rules",        "",                     new ValueContainerString (&ServerConfig::rules),                        DT_CHARPTR,  ValidateRules},
+       {"power",       "diepass",      "",                     new ValueContainerString (&ServerConfig::diepass),                      DT_CHARPTR,  ValidateNotEmpty},
        {"power",       "pause",        "",                     new ValueContainerInt  (&ServerConfig::DieDelay),               DT_INTEGER,  NULL},
-       {"power",       "hash",         "",                     new ValueContainerChar (&ServerConfig::powerhash),              DT_CHARPTR,  NULL},
-       {"power",       "restartpass",  "",                     new ValueContainerChar (&ServerConfig::restartpass),            DT_CHARPTR,  ValidateNotEmpty},
-       {"options",     "prefixquit",   "",                     new ValueContainerChar (&ServerConfig::PrefixQuit),             DT_CHARPTR,  NULL},
-       {"options",     "suffixquit",   "",                     new ValueContainerChar (&ServerConfig::SuffixQuit),             DT_CHARPTR,  NULL},
-       {"options",     "fixedquit",    "",                     new ValueContainerChar (&ServerConfig::FixedQuit),              DT_CHARPTR,  NULL},
-       {"options",     "prefixpart",   "",                     new ValueContainerChar (&ServerConfig::PrefixPart),             DT_CHARPTR,  NULL},
-       {"options",     "suffixpart",   "",                     new ValueContainerChar (&ServerConfig::SuffixPart),             DT_CHARPTR,  NULL},
-       {"options",     "fixedpart",    "",                     new ValueContainerChar (&ServerConfig::FixedPart),              DT_CHARPTR,  NULL},
+       {"power",       "hash",         "",                     new ValueContainerString (&ServerConfig::powerhash),            DT_CHARPTR,  NULL},
+       {"power",       "restartpass",  "",                     new ValueContainerString (&ServerConfig::restartpass),          DT_CHARPTR,  ValidateNotEmpty},
+       {"options",     "prefixquit",   "",                     new ValueContainerString (&ServerConfig::PrefixQuit),           DT_CHARPTR,  NULL},
+       {"options",     "suffixquit",   "",                     new ValueContainerString (&ServerConfig::SuffixQuit),           DT_CHARPTR,  NULL},
+       {"options",     "fixedquit",    "",                     new ValueContainerString (&ServerConfig::FixedQuit),            DT_CHARPTR,  NULL},
+       {"options",     "prefixpart",   "",                     new ValueContainerString (&ServerConfig::PrefixPart),           DT_CHARPTR,  NULL},
+       {"options",     "suffixpart",   "",                     new ValueContainerString (&ServerConfig::SuffixPart),           DT_CHARPTR,  NULL},
+       {"options",     "fixedpart",    "",                     new ValueContainerString (&ServerConfig::FixedPart),            DT_CHARPTR,  NULL},
        {"performance", "netbuffersize","10240",                new ValueContainerInt  (&ServerConfig::NetBufferSize),          DT_INTEGER,  ValidateNetBufferSize},
-       {"performance", "maxwho",       "128",                  new ValueContainerInt  (&ServerConfig::MaxWhoResults),          DT_INTEGER,  ValidateMaxWho},
+       {"performance", "maxwho",       "1024",                 new ValueContainerInt  (&ServerConfig::MaxWhoResults),          DT_INTEGER,  ValidateMaxWho},
        {"options",     "allowhalfop",  "0",                    new ValueContainerBool (&ServerConfig::AllowHalfop),            DT_BOOLEAN,  ValidateHalfOp},
-       {"dns",         "server",       "",                     new ValueContainerChar (&ServerConfig::DNSServer),              DT_IPADDRESS,ValidateDnsServer},
+       {"dns",         "server",       "",                     new ValueContainerString (&ServerConfig::DNSServer),            DT_IPADDRESS,ValidateDnsServer},
        {"dns",         "timeout",      "5",                    new ValueContainerInt  (&ServerConfig::dns_timeout),            DT_INTEGER,  NULL},
        {"options",     "moduledir",    MOD_PATH,               new ValueContainerString (&ServerConfig::ModPath),                      DT_CHARPTR,  NULL},
-       {"disabled",    "commands",     "",                     new ValueContainerChar (&ServerConfig::DisabledCommands),       DT_CHARPTR,  NULL},
+       {"disabled",    "commands",     "",                     new ValueContainerString (&ServerConfig::DisabledCommands),     DT_CHARPTR,  NULL},
        {"disabled",    "usermodes",    "",                     NULL, DT_NOTHING,  ValidateDisabledUModes},
        {"disabled",    "chanmodes",    "",                     NULL, DT_NOTHING,  ValidateDisabledCModes},
        {"disabled",    "fakenonexistant",      "0",            new ValueContainerBool (&ServerConfig::DisabledDontExist),              DT_BOOLEAN,  NULL},
 
-       {"security",            "runasuser",    "",             new ValueContainerChar(&ServerConfig::SetUser),                         DT_CHARPTR, NULL},
-       {"security",            "runasgroup",   "",             new ValueContainerChar(&ServerConfig::SetGroup),                                DT_CHARPTR, NULL},
-       {"security",    "userstats",    "",                     new ValueContainerChar (&ServerConfig::UserStats),              DT_CHARPTR,  NULL},
-       {"security",    "customversion","",                     new ValueContainerChar (&ServerConfig::CustomVersion),          DT_CHARPTR,  NULL},
+       {"security",            "runasuser",    "",             new ValueContainerString(&ServerConfig::SetUser),                               DT_CHARPTR, NULL},
+       {"security",            "runasgroup",   "",             new ValueContainerString(&ServerConfig::SetGroup),                              DT_CHARPTR, NULL},
+       {"security",    "userstats",    "",                     new ValueContainerString (&ServerConfig::UserStats),            DT_CHARPTR,  NULL},
+       {"security",    "customversion","",                     new ValueContainerString (&ServerConfig::CustomVersion),                DT_CHARPTR,  NULL},
        {"security",    "hidesplits",   "0",                    new ValueContainerBool (&ServerConfig::HideSplits),             DT_BOOLEAN,  NULL},
        {"security",    "hidebans",     "0",                    new ValueContainerBool (&ServerConfig::HideBans),               DT_BOOLEAN,  NULL},
-       {"security",    "hidewhois",    "",                     new ValueContainerChar (&ServerConfig::HideWhoisServer),                DT_NOSPACES, NULL},
-       {"security",    "hidekills",    "",                     new ValueContainerChar (&ServerConfig::HideKillsServer),                DT_NOSPACES,  NULL},
+       {"security",    "hidewhois",    "",                     new ValueContainerString (&ServerConfig::HideWhoisServer),              DT_NOSPACES, NULL},
+       {"security",    "hidekills",    "",                     new ValueContainerString (&ServerConfig::HideKillsServer),              DT_NOSPACES,  NULL},
        {"security",    "operspywhois", "0",                    new ValueContainerBool (&ServerConfig::OperSpyWhois),           DT_BOOLEAN,  NULL},
        {"security",    "restrictbannedusers",  "1",            new ValueContainerBool (&ServerConfig::RestrictBannedUsers),            DT_BOOLEAN,  NULL},
        {"security",    "genericoper",  "0",                    new ValueContainerBool (&ServerConfig::GenericOper),            DT_BOOLEAN,  NULL},
@@ -800,12 +803,12 @@ static const InitialConfig Values[] = {
        {"security",    "hidemodes",    "",                     NULL, DT_NOTHING,  ValidateModeLists},
        {"options",     "exemptchanops","",                     NULL, DT_NOTHING,  ValidateExemptChanOps},
        {"security",    "maxtargets",   "20",                   new ValueContainerUInt (&ServerConfig::MaxTargets),             DT_INTEGER,  ValidateMaxTargets},
-       {"options",     "defaultmodes", "nt",                   new ValueContainerChar (&ServerConfig::DefaultModes),           DT_CHARPTR,  NULL},
+       {"options",     "defaultmodes", "nt",                   new ValueContainerString (&ServerConfig::DefaultModes),         DT_CHARPTR,  NULL},
        {"pid",         "file",         "",                     new ValueContainerString (&ServerConfig::PID),                  DT_CHARPTR,  NULL},
        {"whowas",      "groupsize",    "10",                   new ValueContainerInt  (&ServerConfig::WhoWasGroupSize),        DT_INTEGER,  NULL},
        {"whowas",      "maxgroups",    "10240",                new ValueContainerInt  (&ServerConfig::WhoWasMaxGroups),        DT_INTEGER,  NULL},
        {"whowas",      "maxkeep",      "3600",                 NULL, DT_NOTHING,  ValidateWhoWas},
-       {"die",         "value",        "",                     new ValueContainerChar (&ServerConfig::DieValue),               DT_CHARPTR,  NULL},
+       {"die",         "value",        "",                     new ValueContainerString (&ServerConfig::DieValue),             DT_CHARPTR,  NULL},
        {"channels",    "users",        "20",                   new ValueContainerUInt (&ServerConfig::MaxChans),               DT_INTEGER,  NULL},
        {"channels",    "opers",        "60",                   new ValueContainerUInt (&ServerConfig::OperMaxChans),           DT_INTEGER,  NULL},
        {"cidr",        "ipv4clone",    "32",                   new ValueContainerInt (&ServerConfig::c_ipv4_range),            DT_INTEGER,  NULL},
@@ -957,40 +960,37 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
                        {
                                case DT_NOSPACES:
                                {
-                                       ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
+                                       ValueContainerString* vcc = (ValueContainerString*)Values[Index].val;
                                        ValidateNoSpaces(vi.GetString(), Values[Index].tag, Values[Index].value);
-                                       vcc->Set(this, vi);
+                                       vcc->Set(this, vi.GetValue());
                                }
                                break;
                                case DT_HOSTNAME:
                                {
-                                       ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
+                                       ValueContainerString* vcc = (ValueContainerString*)Values[Index].val;
                                        ValidateHostname(vi.GetString(), Values[Index].tag, Values[Index].value);
-                                       vcc->Set(this, vi);
+                                       vcc->Set(this, vi.GetValue());
                                }
                                break;
                                case DT_IPADDRESS:
                                {
-                                       ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
+                                       ValueContainerString* vcc = (ValueContainerString*)Values[Index].val;
                                        ValidateIP(vi.GetString(), Values[Index].tag, Values[Index].value, allow_wild);
-                                       vcc->Set(this, vi);
+                                       vcc->Set(this, vi.GetValue());
                                }
                                break;
                                case DT_CHANNEL:
                                {
-                                       ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
+                                       ValueContainerString* vcc = (ValueContainerString*)Values[Index].val;
                                        if (*(vi.GetString()) && !ServerInstance->IsChannel(vi.GetString(), MAXBUF))
                                        {
                                                throw CoreException("The value of <"+std::string(Values[Index].tag)+":"+Values[Index].value+"> is not a valid channel name");
                                        }
-                                       vcc->Set(this, vi);
+                                       vcc->Set(this, vi.GetValue());
                                }
                                break;
                                case DT_CHARPTR:
                                {
-                                       ValueContainerChar* vcc = dynamic_cast<ValueContainerChar*>(Values[Index].val);
-                                       if (vcc)
-                                               vcc->Set(this, vi);
                                        ValueContainerString* vcs = dynamic_cast<ValueContainerString*>(Values[Index].val);
                                        if (vcs)
                                                vcs->Set(this, vi.GetValue());
@@ -1131,28 +1131,30 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
        // write once here, to try it out and make sure its ok
        ServerInstance->WritePID(this->PID);
 
-       FailedPortList pl;
-       ServerInstance->BindPorts(pl);
-
        /*
         * These values can only be set on boot. Keep their old values. Do it before we send messages so we actually have a servername.
         */
        if (old)
        {
-               memcpy(this->ServerName, old->ServerName, sizeof(this->ServerName));
-               memcpy(this->sid, old->sid, sizeof(this->sid));
-       }
-
-       if (pl.size())
-       {
-               errstr << "Not all your client ports could be bound.\nThe following port(s) failed to bind:\n";
-
-               int j = 1;
-               for (FailedPortList::iterator i = pl.begin(); i != pl.end(); i++, j++)
+               this->ServerName = old->ServerName;
+               this->sid = old->sid;
+               this->argv = old->argv;
+               this->argc = old->argc;
+
+               // Same for ports... they're bound later on first run.
+               FailedPortList pl;
+               ServerInstance->BindPorts(pl);
+               if (pl.size())
                {
-                       char buf[MAXBUF];
-                       snprintf(buf, MAXBUF, "%d.   Address: %s   Reason: %s\n", j, i->first.empty() ? "<all>" : i->first.c_str(), i->second.c_str());
-                       errstr << buf;
+                       errstr << "Not all your client ports could be bound.\nThe following port(s) failed to bind:\n";
+
+                       int j = 1;
+                       for (FailedPortList::iterator i = pl.begin(); i != pl.end(); i++, j++)
+                       {
+                               char buf[MAXBUF];
+                               snprintf(buf, MAXBUF, "%d.   Address: %s   Reason: %s\n", j, i->first.empty() ? "<all>" : i->first.c_str(), i->second.c_str());
+                               errstr << buf;
+                       }
                }
        }
 
@@ -1200,12 +1202,6 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
                return;
 
        ApplyModules(user);
-       for (std::vector<ConnectClass*>::iterator i = removed_classes.begin(); i != removed_classes.end(); i++)
-       {
-               ConnectClass* c = *i;
-               if (0 == --c->RefCount)
-                       delete c;
-       }
 }
 
 void ServerConfig::ApplyModules(User* user)
@@ -2012,11 +2008,6 @@ std::string ServerConfig::GetFullProgDir()
        return "/";
 }
 
-InspIRCd* ServerConfig::GetInstance()
-{
-       return ServerInstance;
-}
-
 std::string ServerConfig::GetSID()
 {
        return sid;
@@ -2068,7 +2059,7 @@ bool ValueItem::GetBool()
 
 void ConfigReaderThread::Run()
 {
-       Config = new ServerConfig(ServerInstance);
+       Config = new ServerConfig;
        Config->Read();
        done = true;
 }
@@ -2097,7 +2088,7 @@ void ConfigReaderThread::Finish()
                ServerInstance->ResetMaxBans();
                Config->ApplyDisabledCommands(Config->DisabledCommands);
                User* user = TheUserUID.empty() ? ServerInstance->FindNick(TheUserUID) : NULL;
-               FOREACH_MOD_I(ServerInstance, I_OnRehash, OnRehash(user));
+               FOREACH_MOD(I_OnRehash, OnRehash(user));
                ServerInstance->BuildISupport();
 
                delete old;
@@ -2111,9 +2102,3 @@ void ConfigReaderThread::Finish()
                delete this->Config;
        }
 }
-
-template<>
-void ValueContainer<char[MAXBUF]>::Set(ServerConfig* conf, ValueItem const& item)
-{
-       strlcpy(conf->*vptr, item.GetString(), MAXBUF);
-}