summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-08-12 18:03:52 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-08-12 18:03:52 +0000
commit0036e3a70cabea02e9ec2103ed1dfdf5c799289f (patch)
tree649d2ea45cd483fc83a293b2c2542212cffa051e
parentb33f836f1b863207a430bfa9cd1dffeaa406524d (diff)
Fixes for config reader
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11504 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/configreader.h415
-rw-r--r--include/inspircd.h5
-rw-r--r--include/users.h182
-rw-r--r--src/channels.cpp4
-rw-r--r--src/commands/cmd_pass.cpp2
-rw-r--r--src/configreader.cpp1311
-rw-r--r--src/helperfuncs.cpp10
-rw-r--r--src/inspircd.cpp26
-rw-r--r--src/modules.cpp4
-rw-r--r--src/modules/m_check.cpp2
-rw-r--r--src/users.cpp50
-rw-r--r--win/inspircd_win32wrapper.cpp3
12 files changed, 835 insertions, 1179 deletions
diff --git a/include/configreader.h b/include/configreader.h
index c4b603342..b5e6a887b 100644
--- a/include/configreader.h
+++ b/include/configreader.h
@@ -32,195 +32,10 @@
/* Required forward definitions */
class ServerConfig;
+class ServerLimits;
class InspIRCd;
class BufferedSocket;
-/** Types of data in the core config
- */
-enum ConfigDataType
-{
- DT_NOTHING = 0, /* No data */
- DT_INTEGER = 1, /* Integer */
- DT_CHARPTR = 2, /* Char pointer */
- DT_BOOLEAN = 3, /* Boolean */
- DT_HOSTNAME = 4, /* Hostname syntax */
- DT_NOSPACES = 5, /* No spaces */
- DT_IPADDRESS = 6, /* IP address (v4, v6) */
- DT_CHANNEL = 7, /* Channel name */
- DT_ALLOW_WILD = 64, /* Allow wildcards/CIDR in DT_IPADDRESS */
- DT_ALLOW_NEWLINE = 128 /* New line characters allowed in DT_CHARPTR */
-};
-
-/** The maximum number of values in a core configuration tag. Can be increased if needed.
- */
-#define MAX_VALUES_PER_TAG 18
-
-/** Holds a config value, either string, integer or boolean.
- * Callback functions receive one or more of these, either on
- * their own as a reference, or in a reference to a deque of them.
- * The callback function can then alter the values of the ValueItem
- * classes to validate the settings.
- */
-class ValueItem
-{
- /** Actual data */
- std::string v;
- public:
- /** Initialize with an int */
- ValueItem(int value);
- /** Initialize with a bool */
- ValueItem(bool value);
- /** Initialize with a char pointer */
- ValueItem(const char* value);
- /** Change value to a char pointer */
- void Set(const char* val);
- /** Change value to an int */
- void Set(int value);
- /** Get value as an int */
- int GetInteger();
- /** Get value as a string */
- char* GetString();
- /** Get value as a bool */
- bool GetBool();
-};
-
-/** The base class of the container 'ValueContainer'
- * used internally by the core to hold core values.
- */
-class ValueContainerBase
-{
- public:
- /** Constructor */
- ValueContainerBase() { }
- /** Destructor */
- virtual ~ValueContainerBase() { }
-};
-
-/** ValueContainer is used to contain pointers to different
- * core values such as the server name, maximum number of
- * clients etc.
- * It is specialized to hold a data type, then pointed at
- * a value in the ServerConfig class. When the value has been
- * read and validated, the Set method is called to write the
- * value safely in a type-safe manner.
- */
-template<typename T> class ValueContainer : public ValueContainerBase
-{
- /** Contained item */
- T val;
- public:
-
- /** Initialize with nothing */
- ValueContainer()
- {
- val = NULL;
- }
-
- /** Initialize with a value of type T */
- ValueContainer(T Val)
- {
- val = Val;
- }
-
- /** Change value to type T of size s */
- void Set(T newval, size_t s)
- {
- memcpy(val, newval, s);
- }
-};
-
-/** A specialization of ValueContainer to hold a pointer to a bool
- */
-typedef ValueContainer<bool*> ValueContainerBool;
-
-/** A specialization of ValueContainer to hold a pointer to
- * an unsigned int
- */
-typedef ValueContainer<unsigned int*> ValueContainerUInt;
-
-/** A specialization of ValueContainer to hold a pointer to
- * a char array.
- */
-typedef ValueContainer<char*> ValueContainerChar;
-
-/** A specialization of ValueContainer to hold a pointer to
- * an int
- */
-typedef ValueContainer<int*> ValueContainerInt;
-
-/** A specialization of ValueContainer to hold a pointer to
- * a size_t.
- */
-typedef ValueContainer<size_t*> ValueContainerST;
-
-/** A set of ValueItems used by multi-value validator functions
- */
-typedef std::deque<ValueItem> ValueList;
-
-/** A callback for validating a single value
- */
-typedef bool (*Validator)(ServerConfig* conf, const char*, const char*, ValueItem&);
-/** A callback for validating multiple value entries
- */
-typedef bool (*MultiValidator)(ServerConfig* conf, const char*, char**, ValueList&, int*);
-/** A callback indicating the end of a group of entries
- */
-typedef bool (*MultiNotify)(ServerConfig* conf, const char*);
-
-/** Holds a core configuration item and its callbacks
- */
-struct InitialConfig
-{
- /** Tag name */
- const char* tag;
- /** Value name */
- const char* value;
- /** Default, if not defined */
- const char* default_value;
- /** Value containers */
- ValueContainerBase* val;
- /** Data types */
- int datatype;
- /** Validation function */
- Validator validation_function;
-};
-
-/** Represents a deprecated configuration tag.
- */
-struct Deprecated
-{
- /** Tag name
- */
- const char* tag;
- /** Tag value
- */
- const char* value;
- /** Reason for deprecation
- */
- const char* reason;
-};
-
-/** Holds a core configuration item and its callbacks
- * where there may be more than one item
- */
-struct MultiConfig
-{
- /** Tag name */
- const char* tag;
- /** One or more items within tag */
- const char* items[MAX_VALUES_PER_TAG];
- /** One or more defaults for items within tags */
- const char* items_default[MAX_VALUES_PER_TAG];
- /** One or more data types */
- int datatype[MAX_VALUES_PER_TAG];
- /** Initialization function */
- MultiNotify init_function;
- /** Validation function */
- MultiValidator validation_function;
- /** Completion function */
- MultiNotify finish_function;
-};
-
/** A set of oper types
*/
typedef std::map<irc::string,std::string> opertype_t;
@@ -318,6 +133,9 @@ class CoreExport ServerConfig : public Extensible
*/
std::vector<std::string> include_stack;
+ /* classes removed by this rehash */
+ std::vector<ConnectClass*> removed_classes;
+
/** This private method processes one line of
* configutation, appending errors to errorstream
* and setting error if an error has occured.
@@ -328,6 +146,9 @@ class CoreExport ServerConfig : public Extensible
*/
bool CheckOnce(const char* tag);
+ void CrossCheckOperClassType();
+ void CrossCheckConnectBlocks(ServerConfig* current);
+
public:
/** Process an include executable directive
*/
@@ -351,9 +172,6 @@ class CoreExport ServerConfig : public Extensible
/** Used to indicate who we announce invites to on a channel */
enum InviteAnnounceState { INVITE_ANNOUNCE_NONE, INVITE_ANNOUNCE_ALL, INVITE_ANNOUNCE_OPS, INVITE_ANNOUNCE_DYNAMIC };
- /** Pointer to function that validates dns server addresses (can be changed depending on platform) */
- Validator DNSServerValidator;
-
/** Returns the creator InspIRCd pointer
*/
InspIRCd* GetInstance();
@@ -513,12 +331,12 @@ class CoreExport ServerConfig : public Extensible
* overridden in the configuration file via
* the <options> tag.
*/
- char ModPath[1024];
+ std::string ModPath;
/** The full pathname to the executable, as
* given in argv[0] when the program starts.
*/
- char MyExecutable[1024];
+ std::string MyExecutable;
/** The file handle of the logfile. If this
* value is NULL, the log file is not open,
@@ -658,7 +476,7 @@ class CoreExport ServerConfig : public Extensible
/** The full pathname and filename of the PID
* file as defined in the configuration.
*/
- char PID[1024];
+ std::string PID;
/** The connect classes in use by the IRC server.
*/
@@ -766,10 +584,6 @@ class CoreExport ServerConfig : public Extensible
*/
ServerConfig(InspIRCd* Instance);
- /** Clears the include stack in preperation for a Read() call.
- */
- void ClearStack();
-
/** Get server ID as string with required leading zeroes
*/
std::string GetSID();
@@ -791,6 +605,7 @@ class CoreExport ServerConfig : public Extensible
/** Apply configuration changes from the old configuration.
*/
void Apply(ServerConfig* old, const std::string &useruid);
+ void ApplyModules(User* user);
/** Read a file into a file_cache object
*/
@@ -872,17 +687,7 @@ class CoreExport ServerConfig : public Extensible
*/
int ConfVarEnum(const std::string &tag, int index);
- /** Validates a hostname value, throwing ConfigException if it is not valid
- */
- void ValidateHostname(const char* p, const std::string &tag, const std::string &val);
-
- /** Validates an IP address value, throwing ConfigException if it is not valid
- */
- void ValidateIP(const char* p, const std::string &tag, const std::string &val, bool wild);
-
- /** Validates a value that should not contain spaces, throwing ConfigException of it is not valid
- */
- void ValidateNoSpaces(const char* p, const std::string &tag, const std::string &val);
+ bool ApplyDisabledCommands(const char* data);
/** Returns the fully qualified path to the inspircd directory
* @return The full program directory
@@ -907,50 +712,202 @@ class CoreExport ServerConfig : public Extensible
};
-/** Initialize the disabled commands list
+
+/** Types of data in the core config
+ */
+enum ConfigDataType
+{
+ DT_NOTHING = 0, /* No data */
+ DT_INTEGER = 1, /* Integer */
+ DT_CHARPTR = 2, /* Char pointer */
+ DT_BOOLEAN = 3, /* Boolean */
+ DT_HOSTNAME = 4, /* Hostname syntax */
+ DT_NOSPACES = 5, /* No spaces */
+ DT_IPADDRESS = 6, /* IP address (v4, v6) */
+ DT_CHANNEL = 7, /* Channel name */
+ DT_LIMIT = 8, /* size_t */
+ DT_ALLOW_WILD = 64, /* Allow wildcards/CIDR in DT_IPADDRESS */
+ DT_ALLOW_NEWLINE = 128 /* New line characters allowed in DT_CHARPTR */
+};
+
+/** The maximum number of values in a core configuration tag. Can be increased if needed.
+ */
+#define MAX_VALUES_PER_TAG 18
+
+/** Holds a config value, either string, integer or boolean.
+ * Callback functions receive one or more of these, either on
+ * their own as a reference, or in a reference to a deque of them.
+ * The callback function can then alter the values of the ValueItem
+ * classes to validate the settings.
*/
-CoreExport bool InitializeDisabledCommands(const char* data, InspIRCd* ServerInstance);
+class ValueItem
+{
+ /** Actual data */
+ std::string v;
+ public:
+ /** Initialize with an int */
+ ValueItem(int value);
+ /** Initialize with a bool */
+ ValueItem(bool value);
+ /** Initialize with a string */
+ ValueItem(const char* value) : v(value) { }
+ /** Change value to a string */
+ void Set(const std::string &val);
+ /** Change value to an int */
+ void Set(int value);
+ /** Get value as an int */
+ int GetInteger();
+ /** Get value as a string */
+ const char* GetString() const;
+ /** Get value as a string */
+ inline const std::string& GetValue() const { return v; }
+ /** Get value as a bool */
+ bool GetBool();
+};
-/** Initialize the oper types
+/** The base class of the container 'ValueContainer'
+ * used internally by the core to hold core values.
*/
-bool InitTypes(ServerConfig* conf, const char* tag);
+class ValueContainerBase
+{
+ public:
+ /** Constructor */
+ ValueContainerBase() { }
+ /** Destructor */
+ virtual ~ValueContainerBase() { }
+};
-/** Initialize the oper classes
+/** ValueContainer is used to contain pointers to different
+ * core values such as the server name, maximum number of
+ * clients etc.
+ * It is specialized to hold a data type, then pointed at
+ * a value in the ServerConfig class. When the value has been
+ * read and validated, the Set method is called to write the
+ * value safely in a type-safe manner.
*/
-bool InitClasses(ServerConfig* conf, const char* tag);
+template<typename T> class ValueContainer : public ValueContainerBase
+{
+ T ServerConfig::* const vptr;
+ public:
+ /** Initialize with a value of type T */
+ ValueContainer(T ServerConfig::* const offset) : vptr(offset)
+ {
+ }
+
+ /** Change value to type T of size s */
+ void Set(ServerConfig* conf, const T& value)
+ {
+ conf->*vptr = value;
+ }
+
+ void Set(ServerConfig* conf, const ValueItem& item);
+};
+
+template<> void ValueContainer<char[MAXBUF]>::Set(ServerConfig* conf, ValueItem const& item);
+
+
+class ValueContainerLimit : public ValueContainerBase
+{
+ size_t ServerLimits::* const vptr;
+ public:
+ /** Initialize with a value of type T */
+ ValueContainerLimit(size_t ServerLimits::* const offset) : vptr(offset)
+ {
+ }
+
+ /** Change value to type T of size s */
+ void Set(ServerConfig* conf, const size_t& value)
+ {
+ conf->Limits.*vptr = value;
+ }
+};
-/** Initialize an oper type
+/** A specialization of ValueContainer to hold a pointer to a bool
*/
-bool DoType(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types);
+typedef ValueContainer<bool> ValueContainerBool;
-/** Initialize an oper class
+/** A specialization of ValueContainer to hold a pointer to
+ * an unsigned int
*/
-bool DoClass(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types);
+typedef ValueContainer<unsigned int> ValueContainerUInt;
-/** Finish initializing the oper types and classes
+/** A specialization of ValueContainer to hold a pointer to
+ * a char array.
*/
-bool DoneClassesAndTypes(ServerConfig* conf, const char* tag);
+typedef ValueContainer<char[MAXBUF]> ValueContainerChar;
+/** A specialization of ValueContainer to hold a pointer to
+ * a char array.
+ */
+typedef ValueContainer<std::string> ValueContainerString;
+/** A specialization of ValueContainer to hold a pointer to
+ * an int
+ */
+typedef ValueContainer<int> ValueContainerInt;
-/** Initialize x line
+/** A set of ValueItems used by multi-value validator functions
*/
-bool InitXLine(ServerConfig* conf, const char* tag);
+typedef std::deque<ValueItem> ValueList;
-/** Add a config-defined zline
+/** A callback for validating a single value
*/
-bool DoZLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types);
+typedef bool (*Validator)(ServerConfig* conf, const char*, const char*, ValueItem&);
+/** A callback for validating multiple value entries
+ */
+typedef bool (*MultiValidator)(ServerConfig* conf, const char*, const char**, ValueList&, int*);
+/** A callback indicating the end of a group of entries
+ */
+typedef bool (*MultiNotify)(ServerConfig* conf, const char*);
-/** Add a config-defined qline
+/** Holds a core configuration item and its callbacks
*/
-bool DoQLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types);
+struct InitialConfig
+{
+ /** Tag name */
+ const char* tag;
+ /** Value name */
+ const char* value;
+ /** Default, if not defined */
+ const char* default_value;
+ /** Value containers */
+ ValueContainerBase* val;
+ /** Data types */
+ int datatype;
+ /** Validation function */
+ Validator validation_function;
+};
-/** Add a config-defined kline
+/** Represents a deprecated configuration tag.
*/
-bool DoKLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types);
+struct Deprecated
+{
+ /** Tag name
+ */
+ const char* tag;
+ /** Tag value
+ */
+ const char* value;
+ /** Reason for deprecation
+ */
+ const char* reason;
+};
-/** Add a config-defined eline
+/** Holds a core configuration item and its callbacks
+ * where there may be more than one item
*/
-bool DoELine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types);
+struct MultiConfig
+{
+ /** Tag name */
+ const char* tag;
+ /** One or more items within tag */
+ const char* items[MAX_VALUES_PER_TAG];
+ /** One or more defaults for items within tags */
+ const char* items_default[MAX_VALUES_PER_TAG];
+ /** One or more data types */
+ int datatype[MAX_VALUES_PER_TAG];
+ /** Validation function */
+ MultiValidator validation_function;
+};
#endif
diff --git a/include/inspircd.h b/include/inspircd.h
index ef6c86f28..2609f3cc1 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -611,11 +611,6 @@ class CoreExport InspIRCd : public classbase
*/
Channel* FindChan(const char* chan);
- /** Check for a 'die' tag in the config file, and abort if found
- * @return Depending on the configuration, this function may never return
- */
- void CheckDie();
-
/** Check we aren't running as root, and exit if we are
* @return Depending on the configuration, this function may never return
*/
diff --git a/include/users.h b/include/users.h
index 9d1072f57..175ad0d0f 100644
--- a/include/users.h
+++ b/include/users.h
@@ -74,9 +74,8 @@ class UserResolver;
/** Holds information relevent to &lt;connect allow&gt; and &lt;connect deny&gt; tags in the config file.
*/
-class CoreExport ConnectClass : public classbase
+struct CoreExport ConnectClass : public classbase
{
- private:
/** Type of line, either CC_ALLOW or CC_DENY
*/
char type;
@@ -129,141 +128,33 @@ class CoreExport ConnectClass : public classbase
*/
int port;
-public:
-
- /** Create a new connect class based on an existing connect class. This is required for std::vector (at least under windows).
- */
- ConnectClass(const ConnectClass* source) : classbase(), type(source->type), name(source->name),
- registration_timeout(source->registration_timeout), host(source->host),
- pingtime(source->pingtime), pass(source->pass), hash(source->hash), sendqmax(source->sendqmax),
- recvqmax(source->recvqmax), maxlocal(source->maxlocal), maxglobal(source->maxglobal), maxchans(source->maxchans),
- port(source->port), RefCount(0), disabled(false), limit(source->limit)
- {
- }
-
- /** Create a new connect class with no settings.
- */
- ConnectClass() : type(CC_DENY), name("unnamed"), registration_timeout(0), host(""), pingtime(0), pass(""), hash(""),
- sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), RefCount(0), disabled(false), limit(0)
- {
- }
-
- /** Create a new connect class to ALLOW connections.
- * @param thename Name of the connect class
- * @param timeout The registration timeout
- * @param hst The IP mask to allow
- * @param ping The ping frequency
- * @param pas The password to be used
- * @param hsh The hash to be used
- * @param sendq The maximum sendq value
- * @param recvq The maximum recvq value
- * @param maxl The maximum local sessions
- * @param maxg The maximum global sessions
- */
- ConnectClass(const std::string &thename, unsigned int timeout,const std::string &hst, unsigned int ping,
- const std::string &pas, const std::string &hsh, unsigned long sendq, unsigned long recvq,
- unsigned long maxl, unsigned long maxg, unsigned int maxc, int p = 0) :
- type(CC_ALLOW), name(thename), registration_timeout(timeout), host(hst), pingtime(ping), pass(pas), hash(hsh),
- sendqmax(sendq), recvqmax(recvq), maxlocal(maxl), maxglobal(maxg), maxchans(maxc), port(p), RefCount(0), disabled(false), limit(0) { }
-
- /** Create a new connect class to DENY connections
- * @param thename Name of the connect class
- * @param hst The IP mask to deny
- */
- ConnectClass(const std::string &thename, const std::string &hst) : type(CC_DENY), name(thename), registration_timeout(0),
- host(hst), pingtime(0), pass(""), hash(""), sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), maxchans(0), port(0), RefCount(0), disabled(false), limit(0)
- {
- }
-
- /* Create a new connect class based on another class
- * @param thename The name of the connect class
- * @param source Another connect class to inherit all but the name from
+ /** How many users may be in this connect class before they are refused?
+ * (0 = no limit = default)
*/
- ConnectClass(const std::string &thename, const ConnectClass* source) : type(source->type), name(thename),
- registration_timeout(source->registration_timeout), host(source->host),
- pingtime(source->pingtime), pass(source->pass), hash(source->hash), sendqmax(source->sendqmax),
- recvqmax(source->recvqmax), maxlocal(source->maxlocal), maxglobal(source->maxglobal), maxchans(source->maxchans),
- port(source->port), RefCount(0), disabled(false), limit(source->limit)
- {
- }
-
- void SetDisabled(bool t)
- {
- this->disabled = t;
- }
-
- bool GetDisabled()
- {
- return this->disabled;
- }
-
- /* Update an existing entry with new values
- */
- void Update(unsigned int timeout, const std::string &hst, unsigned int ping,
- const std::string &pas, unsigned long sendq, unsigned long recvq,
- unsigned long maxl, unsigned long maxg, unsigned int maxc, int p, unsigned long llimit)
- {
- if (timeout)
- registration_timeout = timeout;
- if (!hst.empty())
- host = hst;
- if (ping)
- pingtime = ping;
- if (!pas.empty())
- pass = pas;
- if (sendq)
- sendqmax = sendq;
- if (recvq)
- recvqmax = recvq;
- if (maxl)
- maxlocal = maxl;
- if (maxg)
- maxglobal = maxg;
- if (maxc)
- maxchans = maxc;
- if (p)
- port = p;
-
- this->limit = llimit;
- }
-
- void Update(const std::string &n, const std::string &hst)
- {
- name = n;
- host = hst;
- }
+ unsigned long limit;
- /** Reference counter. Contains an int as to how many users are connected to this class. :)
- * This will be 0 if no users are connected. If a <connect> is removed from the config, and there
- * are 0 users on it - it will go away in RAM. :)
+ /** Reference counter.
+ * This will be 1 if no users are connected, as long as it is a valid connect block
+ * When it reaches 0, the object should be deleted
*/
unsigned long RefCount;
- /** If this is true, any attempt to set a user to this class will fail. Default false. This is really private, it's only in the public section thanks to the way this class is written
- */
- bool disabled;
-
- /** How many users may be in this connect class before they are refused? (0 = disabled = default)
+ /** Create a new connect class with no settings.
*/
- unsigned long limit;
-
- size_t GetMaxChans()
- {
- return maxchans;
- }
-
- /** Returns the type, CC_ALLOW or CC_DENY
+ ConnectClass(char type, const std::string& mask);
+ /** Create a new connect class with inherited settings.
*/
- char GetType()
- {
- return (type == CC_ALLOW ? CC_ALLOW : CC_DENY);
- }
+ ConnectClass(char type, const std::string& mask, const ConnectClass& parent);
+
+ /** Update the settings in this block to match the given block */
+ void Update(const ConnectClass* newSettings);
- std::string& GetName()
- {
- return name;
- }
+ const std::string& GetName() { return name; }
+ const std::string& GetPass() { return pass; }
+ const std::string& GetHost() { return host; }
+ const int GetPort() { return port; }
+
/** Returns the registration timeout
*/
time_t GetRegTimeout()
@@ -271,27 +162,6 @@ public:
return (registration_timeout ? registration_timeout : 90);
}
- /** Returns the allowed or denied IP mask
- */
- const std::string& GetHost()
- {
- return host;
- }
-
- /** Get port number
- */
- int GetPort()
- {
- return port;
- }
-
- /** Set port number
- */
- void SetPort(int p)
- {
- port = p;
- }
-
/** Returns the ping frequency
*/
unsigned int GetPingTime()
@@ -299,20 +169,6 @@ public:
return (pingtime ? pingtime : 120);
}
- /** Returns the password or an empty string
- */
- const std::string& GetPass()
- {
- return pass;
- }
-
- /** Returns the hash or an empty string
- */
- const std::string& GetHash()
- {
- return hash;
- }
-
/** Returns the maximum sendq value
*/
unsigned long GetSendqMax()
diff --git a/src/channels.cpp b/src/channels.cpp
index 1ef761a66..0ff1298c1 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -261,7 +261,7 @@ Channel* Channel::JoinUser(InspIRCd* Instance, User *user, const char* cn, bool
if (IS_LOCAL(user) && !override)
{
// Checking MyClass exists because we *may* get here with NULL, not 100% sure.
- if (user->MyClass && user->MyClass->GetMaxChans())
+ if (user->MyClass && user->MyClass->maxchans)
{
if (user->HasPrivPermission("channels/high-join-limit"))
{
@@ -273,7 +273,7 @@ Channel* Channel::JoinUser(InspIRCd* Instance, User *user, const char* cn, bool
}
else
{
- if (user->chans.size() >= Instance->Config->MaxChans)
+ if (user->chans.size() >= user->MyClass->maxchans)
{
user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
return NULL;
diff --git a/src/commands/cmd_pass.cpp b/src/commands/cmd_pass.cpp
index ef54354a1..e4bbf59c2 100644
--- a/src/commands/cmd_pass.cpp
+++ b/src/commands/cmd_pass.cpp
@@ -32,7 +32,7 @@ CmdResult CommandPass::Handle (const std::vector<std::string>& parameters, User
return CMD_FAILURE;
user->password.assign(parameters[0], 0, 63);
- if (!ServerInstance->PassCompare(user, a->GetPass().c_str(), parameters[0].c_str(), a->GetHash().c_str()))
+ if (!ServerInstance->PassCompare(user, a->pass.c_str(), parameters[0].c_str(), a->hash.c_str()))
user->haspassed = true;
return CMD_SUCCESS;
diff --git a/src/configreader.cpp b/src/configreader.cpp
index 04f6e91dc..30db77e4d 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -32,19 +32,12 @@
#include "commands/cmd_whowas.h"
#include "modes/cmode_h.h"
-std::vector<std::string> old_module_names, new_module_names, added_modules, removed_modules;
-
-/* Needs forward declaration */
-bool ValidateDnsServer(ServerConfig* conf, const char* tag, const char* value, ValueItem &data);
-bool DoneELine(ServerConfig* conf, const char* tag);
-
ServerConfig::ServerConfig(InspIRCd* Instance) : ServerInstance(Instance)
{
- this->ClearStack();
*sid = *ServerName = *Network = *ServerDesc = *AdminName = '\0';
*HideWhoisServer = *AdminEmail = *AdminNick = *diepass = *restartpass = *FixedQuit = *HideKillsServer = '\0';
*DefaultModes = *CustomVersion = *motd = *rules = *PrefixQuit = *DieValue = *DNSServer = '\0';
- *UserStats = *ModPath = *MyExecutable = *DisabledCommands = *PID = *SuffixQuit = '\0';
+ *UserStats = *DisabledCommands = *SuffixQuit = '\0';
WhoWasGroupSize = WhoWasMaxGroups = WhoWasMaxKeep = 0;
log_file = NULL;
NoUserDns = forcedebug = OperSpyWhois = nofork = HideBans = HideSplits = UndernetMsgPrefix = false;
@@ -60,13 +53,6 @@ ServerConfig::ServerConfig(InspIRCd* Instance) : ServerInstance(Instance)
OperMaxChans = 30;
c_ipv4_range = 32;
c_ipv6_range = 128;
- maxbans.clear();
- DNSServerValidator = &ValidateDnsServer;
-}
-
-void ServerConfig::ClearStack()
-{
- include_stack.clear();
}
void ServerConfig::Update005()
@@ -114,17 +100,7 @@ bool ServerConfig::CheckOnce(const char* tag)
return true;
}
-bool NoValidation(ServerConfig*, const char*, const char*, ValueItem&)
-{
- return true;
-}
-
-bool DoneConfItem(ServerConfig* conf, const char* tag)
-{
- return true;
-}
-
-void ServerConfig::ValidateNoSpaces(const char* p, const std::string &tag, const std::string &val)
+static void ValidateNoSpaces(const char* p, const std::string &tag, const std::string &val)
{
for (const char* ptr = p; *ptr; ++ptr)
{
@@ -137,7 +113,7 @@ void ServerConfig::ValidateNoSpaces(const char* p, const std::string &tag, const
* even in strerror(errno). They just return 'yes' or 'no' to an address without such detail as to whats WRONG with the address.
* Because ircd users arent as technical as they used to be (;)) we are going to give more of a useful error message.
*/
-void ServerConfig::ValidateIP(const char* p, const std::string &tag, const std::string &val, bool wild)
+static void ValidateIP(const char* p, const std::string &tag, const std::string &val, bool wild)
{
int num_dots = 0;
int num_seps = 0;
@@ -194,7 +170,7 @@ void ServerConfig::ValidateIP(const char* p, const std::string &tag, const std::
}
}
-void ServerConfig::ValidateHostname(const char* p, const std::string &tag, const std::string &val)
+static void ValidateHostname(const char* p, const std::string &tag, const std::string &val)
{
int num_dots = 0;
if (*p)
@@ -217,17 +193,19 @@ void ServerConfig::ValidateHostname(const char* p, const std::string &tag, const
}
}
-bool ValidateMaxTargets(ServerConfig* conf, const char*, const char*, ValueItem &data)
+// Specialized validators
+
+static bool ValidateMaxTargets(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
- if ((data.GetInteger() < 0) || (data.GetInteger() > 31))
+ if ((data.GetInteger() < 1) || (data.GetInteger() > 31))
{
- conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <security:maxtargets> value is greater than 31 or less than 0, set to 20.");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <security:maxtargets> value is greater than 31 or less than 1, set to 20.");
data.Set(20);
}
return true;
}
-bool ValidateSoftLimit(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateSoftLimit(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
if ((data.GetInteger() < 1) || (data.GetInteger() > conf->GetInstance()->SE->GetMaxFds()))
{
@@ -237,14 +215,14 @@ bool ValidateSoftLimit(ServerConfig* conf, const char*, const char*, ValueItem &
return true;
}
-bool ValidateMaxConn(ServerConfig* conf, const char*, const char*, ValueItem &data)
+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!");
return true;
}
-bool InitializeDisabledCommands(const char* data, InspIRCd* ServerInstance)
+bool ServerConfig::ApplyDisabledCommands(const char* data)
{
std::stringstream dcmds(data);
std::string thiscmd;
@@ -265,7 +243,7 @@ bool InitializeDisabledCommands(const char* data, InspIRCd* ServerInstance)
return true;
}
-bool ValidateDisabledUModes(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateDisabledUModes(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
memset(conf->DisabledUModes, 0, sizeof(conf->DisabledUModes));
for (const unsigned char* p = (const unsigned char*)data.GetString(); *p; ++p)
@@ -276,7 +254,7 @@ bool ValidateDisabledUModes(ServerConfig* conf, const char*, const char*, ValueI
return true;
}
-bool ValidateDisabledCModes(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateDisabledCModes(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
memset(conf->DisabledCModes, 0, sizeof(conf->DisabledCModes));
for (const unsigned char* p = (const unsigned char*)data.GetString(); *p; ++p)
@@ -287,7 +265,11 @@ bool ValidateDisabledCModes(ServerConfig* conf, const char*, const char*, ValueI
return true;
}
-bool ValidateDnsServer(ServerConfig* conf, const char*, const char*, ValueItem &data)
+#ifdef WINDOWS
+// Note: the windows validator is in win32wrapper.cpp
+bool ValidateDnsServer(ServerConfig* conf, const char*, const char*, ValueItem &data);
+#else
+static bool ValidateDnsServer(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
if (!*(data.GetString()))
{
@@ -324,22 +306,24 @@ bool ValidateDnsServer(ServerConfig* conf, const char*, const char*, ValueItem &
}
return true;
}
+#endif
-bool ValidateServerName(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateServerName(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
conf->GetInstance()->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%c'",data.GetString(),data.GetString(),'.');
- std::string moo = std::string(data.GetString()).append(".");
- data.Set(moo.c_str());
+ conf->GetInstance()->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("."));
}
- conf->ValidateHostname(data.GetString(), "server", "name");
+ ValidateHostname(data.GetString(), "server", "name");
return true;
}
-bool ValidateNetBufferSize(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateNetBufferSize(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
// 65534 not 65535 because of null terminator
if ((!data.GetInteger()) || (data.GetInteger() > 65534) || (data.GetInteger() < 1024))
@@ -350,7 +334,7 @@ bool ValidateNetBufferSize(ServerConfig* conf, const char*, const char*, ValueIt
return true;
}
-bool ValidateMaxWho(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateMaxWho(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
if ((data.GetInteger() > 65535) || (data.GetInteger() < 1))
{
@@ -360,44 +344,41 @@ bool ValidateMaxWho(ServerConfig* conf, const char*, const char*, ValueItem &dat
return true;
}
-bool ValidateHalfOp(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateHalfOp(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
ModeHandler* mh = conf->GetInstance()->Modes->FindMode('h', MODETYPE_CHANNEL);
- if (data.GetBool() && !mh)
- {
- conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Enabling halfop mode.");
+ if (data.GetBool() && !mh) {
+ conf->GetInstance()->Logs->Log("CONFIG", DEFAULT, "Enabling halfop mode.");
mh = new ModeChannelHalfOp(conf->GetInstance());
conf->GetInstance()->Modes->AddMode(mh);
- }
- else if (!data.GetBool() && mh)
- {
- conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Disabling halfop mode.");
+ } else if (!data.GetBool() && mh) {
+ conf->GetInstance()->Logs->Log("CONFIG", DEFAULT, "Disabling halfop mode.");
conf->GetInstance()->Modes->DelMode(mh);
delete mh;
}
return true;
}
-bool ValidateMotd(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateMotd(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
conf->ReadFile(conf->MOTD, data.GetString());
return true;
}
-bool ValidateNotEmpty(ServerConfig*, const char* tag, const char* val, ValueItem &data)
+static bool ValidateNotEmpty(ServerConfig*, const char* tag, const char* val, ValueItem &data)
{
- if (!*data.GetString())
+ if (data.GetValue().empty())
throw CoreException(std::string("The value for <")+tag+":"+val+"> cannot be empty!");
return true;
}
-bool ValidateRules(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateRules(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
conf->ReadFile(conf->RULES, data.GetString());
return true;
}
-bool ValidateModeLists(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateModeLists(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
memset(conf->HideModeLists, 0, sizeof(conf->HideModeLists));
for (const unsigned char* x = (const unsigned char*)data.GetString(); *x; ++x)
@@ -405,7 +386,7 @@ bool ValidateModeLists(ServerConfig* conf, const char*, const char*, ValueItem &
return true;
}
-bool ValidateExemptChanOps(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateExemptChanOps(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
memset(conf->ExemptChanOps, 0, sizeof(conf->ExemptChanOps));
for (const unsigned char* x = (const unsigned char*)data.GetString(); *x; ++x)
@@ -413,9 +394,9 @@ bool ValidateExemptChanOps(ServerConfig* conf, const char*, const char*, ValueIt
return true;
}
-bool ValidateInvite(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateInvite(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
- std::string v = data.GetString();
+ const std::string& v = data.GetValue();
if (v == "ops")
conf->AnnounceInvites = ServerConfig::INVITE_ANNOUNCE_OPS;
@@ -429,7 +410,7 @@ bool ValidateInvite(ServerConfig* conf, const char*, const char*, ValueItem &dat
return true;
}
-bool ValidateSID(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateSID(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Validating server id");
@@ -445,7 +426,7 @@ bool ValidateSID(ServerConfig* conf, const char*, const char*, ValueItem &data)
return true;
}
-bool ValidateWhoWas(ServerConfig* conf, const char*, const char*, ValueItem &data)
+static bool ValidateWhoWas(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
conf->WhoWasMaxKeep = conf->GetInstance()->Duration(data.GetString());
@@ -471,458 +452,484 @@ bool ValidateWhoWas(ServerConfig* conf, const char*, const char*, ValueItem &dat
return true;
}
-/* Callback called before processing the first <connect> tag
+/* Callback called to process a single <uline> tag
*/
-bool InitConnect(ServerConfig* conf, const char*)
+static bool DoULine(ServerConfig* conf, const char*, const char**, ValueList &values, int*)
{
- conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Reading connect classes... class list is:");
-
- for (ClassVector::iterator i = conf->Classes.begin(); i != conf->Classes.end() ; )
- {
- ConnectClass* c = *i;
-
- /*
- * only delete a class with refcount 0.
- * this is needed to avoid trampling on a wild pointer (User::MyClass)!
- * it's also the most simple way to do it, given that we're looking at threads..
- * -- w00t
- */
- if (c->RefCount == 0)
- {
- conf->GetInstance()->Logs->Log("CONFIG",DEFAULT, "Removing connect class, refcount is 0!");
-
- /* This was causing a crash, because we'd set i to .begin() just here, but then the for loop's increment would
- * set it to .begin() + 1. Which if it was already the last thing in the list, wasn't good.
- * Now the increment is in the else { } below.
- */
- conf->Classes.erase(i);
- i = conf->Classes.begin(); // start over so we don't trample on a bad iterator
- }
- else
- {
- /* also mark all existing classes disabled, if they still exist in the conf, they will be reenabled. */
- c->SetDisabled(true);
- i++;
- }
- }
-
+ const char* server = values[0].GetString();
+ const bool silent = values[1].GetBool();
+ conf->ulines[server] = silent;
return true;
}
-/* Callback called to process a single <connect> tag
+/* Callback called to process a single <banlist> tag
*/
-bool DoConnect(ServerConfig* conf, const char*, char**, ValueList &values, int*)
-{
- ConnectClass c;
- const char* allow = values[0].GetString(); /* Yeah, there are a lot of values. Live with it. */
- const char* deny = values[1].GetString();
- const char* password = values[2].GetString();
- int timeout = values[3].GetInteger();
- int pingfreq = values[4].GetInteger();
- int sendq = values[5].GetInteger();
- int recvq = values[6].GetInteger();
- int localmax = values[7].GetInteger();
- int globalmax = values[8].GetInteger();
- int port = values[9].GetInteger();
- const char* name = values[10].GetString();
- const char* parent = values[11].GetString();
- int maxchans = values[12].GetInteger();
- unsigned long limit = values[13].GetInteger();
- const char* hashtype = values[14].GetString();
-
- conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Adding a connect class!");
-
- ConnectClass *cc = NULL;
-
- if (*parent)
- {
- /* Find 'parent' and inherit a new class from it,
- * then overwrite any values that are set here
- */
- ClassVector::iterator item = conf->Classes.begin();
- for (; item != conf->Classes.end(); ++item)
- {
- cc = *item;
- conf->GetInstance()->Logs->Log("CONFIG",DEBUG,"Class: %s", cc->GetName().c_str());
- if (cc->GetName() == parent)
- {
- cc = new ConnectClass(name, cc);
- cc->Update(timeout, *allow ? allow : deny, pingfreq, password, sendq, recvq, localmax, globalmax, maxchans, port, limit);
- conf->Classes.push_back(cc);
- break;
- }
- }
- if (item == conf->Classes.end())
- throw CoreException("Class name '" + std::string(name) + "' is configured to inherit from class '" + std::string(parent) + "' which cannot be found.");
- }
- else
- {
- if (*allow)
- {
- /* Find existing class by mask, the mask should be unique */
- for (ClassVector::iterator item = conf->Classes.begin(); item != conf->Classes.end(); ++item)
- {
- if ((*item)->GetHost() == allow && !(*item)->GetDisabled())
- {
- (*item)->Update(timeout, allow, pingfreq, password, sendq, recvq, localmax, globalmax, maxchans, port, limit);
- return true;
- }
- }
- cc = new ConnectClass(name, timeout, allow, pingfreq, password, hashtype, sendq, recvq, localmax, globalmax, maxchans);
- cc->limit = limit;
- cc->SetPort(port);
- conf->Classes.push_back(cc);
- }
- else
- {
- /* Find existing class by mask, the mask should be unique */
- for (ClassVector::iterator item = conf->Classes.begin(); item != conf->Classes.end(); ++item)
- {
- if ((*item)->GetHost() == deny && !(*item)->GetDisabled())
- {
- (*item)->Update(name, deny);
- (*item)->SetPort(port);
- return true;
- }
- }
- cc = new ConnectClass(name, deny);
- cc->SetPort(port);
- conf->Classes.push_back(cc);
- }
- }
-
+static bool DoMaxBans(ServerConfig* conf, const char*, const char**, ValueList &values, int*)
+{
+ const char* channel = values[0].GetString();
+ int limit = values[1].GetInteger();
+ conf->maxbans[channel] = limit;
return true;
}
-/* Callback called when there are no more <connect> tags
- */
-bool DoneConnect(ServerConfig *conf, const char*)
+static bool DoZLine(ServerConfig* conf, const char* tag, const char** entries, ValueList &values, int* types)
{
- conf->GetInstance()->Logs->Log("CONFIG",DEFAULT, "Done adding connect classes!");
+ 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))
+ delete zl;
+
return true;
}
-/* Callback called before processing the first <uline> tag
- */
-bool InitULine(ServerConfig* conf, const char*)
+static bool DoQLine(ServerConfig* conf, const char* tag, const char** entries, ValueList &values, int* types)
{
- conf->ulines.clear();
+ 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))
+ delete ql;
+
return true;
}
-/* Callback called to process a single <uline> tag
- */
-bool DoULine(ServerConfig* conf, const char*, char**, ValueList &values, int*)
+static bool DoKLine(ServerConfig* conf, const char* tag, const char** entries, ValueList &values, int* types)
{
- const char* server = values[0].GetString();
- const bool silent = values[1].GetBool();
- conf->ulines[server] = silent;
+ const char* reason = values[0].GetString();
+ const char* host = values[1].GetString();
+
+ XLineManager* xlm = conf->GetInstance()->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());
+ if (!xlm->AddLine(kl, NULL))
+ delete kl;
return true;
}
-/* Callback called when there are no more <uline> tags
- */
-bool DoneULine(ServerConfig*, const char*)
+static bool DoELine(ServerConfig* conf, const char* tag, const char** entries, ValueList &values, int* types)
{
+ const char* reason = values[0].GetString();
+ const char* host = values[1].GetString();
+
+ XLineManager* xlm = conf->GetInstance()->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());
+ if (!xlm->AddLine(el, NULL))
+ delete el;
return true;
}
-/* Callback called before processing the first <module> tag
- */
-bool InitModule(ServerConfig* conf, const char*)
+static bool DoType(ServerConfig* conf, const char*, const char**, ValueList &values, int*)
{
- old_module_names = conf->GetInstance()->Modules->GetAllModuleNames(0);
- new_module_names.clear();
- added_modules.clear();
- removed_modules.clear();
+ const char* TypeName = values[0].GetString();
+ const char* Classes = values[1].GetString();
+
+ conf->opertypes[TypeName] = std::string(Classes);
return true;
}
-/* Callback called to process a single <module> tag
- */
-bool DoModule(ServerConfig*, const char*, char**, ValueList &values, int*)
+static bool DoClass(ServerConfig* conf, const char* tag, const char**, ValueList &values, int*)
{
- const char* modname = values[0].GetString();
- new_module_names.push_back(modname);
+ const char* ClassName = values[0].GetString();
+ const char* CommandList = values[1].GetString();
+ const char* UModeList = values[2].GetString();
+ const char* CModeList = values[3].GetString();
+ const char *PrivsList = values[4].GetString();
+
+ for (const char* c = UModeList; *c; ++c)
+ {
+ if ((*c < 'A' || *c > 'z') && *c != '*')
+ {
+ throw CoreException("Character " + std::string(1, *c) + " is not a valid mode in <class:usermodes>");
+ }
+ }
+ for (const char* c = CModeList; *c; ++c)
+ {
+ if ((*c < 'A' || *c > 'z') && *c != '*')
+ {
+ throw CoreException("Character " + std::string(1, *c) + " is not a valid mode in <class:chanmodes>");
+ }
+ }
+
+ conf->operclass[ClassName].commandlist = strnewdup(CommandList);
+ conf->operclass[ClassName].umodelist = strnewdup(UModeList);
+ conf->operclass[ClassName].cmodelist = strnewdup(CModeList);
+ conf->operclass[ClassName].privs = strnewdup(PrivsList);
return true;
}
-/* Callback called when there are no more <module> tags
- */
-bool DoneModule(ServerConfig*, const char*)
+void ServerConfig::CrossCheckOperClassType()
{
- // now create a list of new modules that are due to be loaded
- // and a seperate list of modules which are due to be unloaded
- for (std::vector<std::string>::iterator _new = new_module_names.begin(); _new != new_module_names.end(); _new++)
+ for (int i = 0; i < ConfValueEnum("type"); ++i)
{
- bool added = true;
-
- for (std::vector<std::string>::iterator old = old_module_names.begin(); old != old_module_names.end(); old++)
+ char item[MAXBUF], classn[MAXBUF], classes[MAXBUF];
+ std::string classname;
+ ConfValue("type", "classes", "", i, classes, MAXBUF, false);
+ irc::spacesepstream str(classes);
+ ConfValue("type", "name", "", i, item, MAXBUF, false);
+ while (str.GetToken(classname))
{
- if (*old == *_new)
- added = false;
+ std::string lost;
+ bool foundclass = false;
+ for (int j = 0; j < ConfValueEnum("class"); ++j)
+ {
+ ConfValue("class", "name", "", j, classn, MAXBUF, false);
+ if (!strcmp(classn, classname.c_str()))
+ {
+ foundclass = true;
+ break;
+ }
+ }
+ if (!foundclass)
+ {
+ char msg[MAXBUF];
+ snprintf(msg, MAXBUF, " Warning: Oper type '%s' has a missing class named '%s', this does nothing!\n",
+ item, classname.c_str());
+ throw CoreException(msg);
+ }
}
+ }
+}
- if (added)
- added_modules.push_back(*_new);
+void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
+{
+ typedef std::map<std::string, ConnectClass*> ClassMap;
+ ClassMap oldBlocksByMask;
+ if (current)
+ {
+ for(ClassVector::iterator i = current->Classes.begin(); i != current->Classes.end(); ++i)
+ {
+ ConnectClass* c = *i;
+ std::string typeMask = (c->type == CC_ALLOW) ? "a" : "d";
+ typeMask += c->host;
+ oldBlocksByMask[typeMask] = c;
+ }
}
- for (std::vector<std::string>::iterator oldm = old_module_names.begin(); oldm != old_module_names.end(); oldm++)
+ int block_count = ConfValueEnum("connect");
+ ClassMap newBlocksByMask;
+ Classes.resize(block_count, NULL);
+ std::map<std::string, int> names;
+
+ bool try_again = true;
+ for(int tries=0; try_again && tries < block_count + 1; tries++)
{
- bool removed = true;
- for (std::vector<std::string>::iterator newm = new_module_names.begin(); newm != new_module_names.end(); newm++)
+ try_again = false;
+ for(int i=0; i < block_count; i++)
{
- if (*newm == *oldm)
- removed = false;
+ if (Classes[i])
+ continue;
+
+ ConnectClass* parent = NULL;
+ std::string parentName;
+ if (ConfValue("connect", "parent", i, parentName, false))
+ {
+ std::map<std::string,int>::iterator parentIter = names.find(parentName);
+ if (parentIter == names.end())
+ {
+ try_again = true;
+ // couldn't find parent this time. If it's the last time, we'll never find it.
+ if (tries == block_count)
+ throw CoreException("Could not find parent connect class \"" + parentName + "\" for connect block " + ConvToStr(i));
+ continue;
+ }
+ parent = Classes[parentIter->second];
+ }
+
+ std::string name;
+ if (ConfValue("connect", "name", i, name, false))
+ {
+ if (names.find(name) != names.end())
+ throw CoreException("Two connect classes with name \"" + name + "\" defined!");
+ names[name] = i;
+ }
+
+ std::string mask, typeMask;
+ char type;
+
+ if (ConfValue("connect", "allow", i, mask, false))
+ {
+ type = CC_ALLOW;
+ typeMask = 'a' + mask;
+ }
+ else if (ConfValue("connect", "deny", i, mask, false))
+ {
+ type = CC_DENY;
+ typeMask = 'd' + mask;
+ }
+ else
+ {
+ throw CoreException("Connect class must have an allow or deny mask (#" + ConvToStr(i) + ")");
+ }
+ ClassMap::iterator dupMask = newBlocksByMask.find(typeMask);
+ if (dupMask != newBlocksByMask.end())
+ throw CoreException("Two connect classes cannot have the same mask (" + mask + ")");
+
+ ConnectClass* me = parent ?
+ new ConnectClass(type, mask, *parent) :
+ new ConnectClass(type, mask);
+
+ if (!name.empty())
+ me->name = name;
+
+ std::string tmpv;
+ if (ConfValue("connect", "password", i, tmpv, false))
+ me->pass= tmpv;
+ if (ConfValue("connect", "hash", i, tmpv, false))
+ me->hash = tmpv;
+ if (ConfValue("connect", "timeout", i, tmpv, false))
+ me->registration_timeout = atol(tmpv.c_str());
+ 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());
+ if (ConfValue("connect", "recvq", i, tmpv, false))
+ me->recvqmax = atol(tmpv.c_str());
+ if (ConfValue("connect", "localmax", i, tmpv, false))
+ me->maxlocal = atol(tmpv.c_str());
+ if (ConfValue("connect", "globalmax", i, tmpv, false))
+ me->maxglobal = atol(tmpv.c_str());
+ if (ConfValue("connect", "port", i, tmpv, false))
+ me->port = atol(tmpv.c_str());
+ if (ConfValue("connect", "maxchans", i, tmpv, false))
+ me->maxchans = atol(tmpv.c_str());
+ if (ConfValue("connect", "limit", i, tmpv, false))
+ me->limit = atol(tmpv.c_str());
+
+ ClassMap::iterator oldMask = oldBlocksByMask.find(typeMask);
+ if (oldMask != oldBlocksByMask.end())
+ {
+ oldBlocksByMask.erase(oldMask);
+ ConnectClass* old = oldMask->second;
+ old->Update(me);
+ delete me;
+ me = old;
+ }
+ newBlocksByMask[typeMask] = me;
+ Classes[i] = me;
}
+ }
- if (removed)
- removed_modules.push_back(*oldm);
+ for(ClassMap::iterator toRemove = oldBlocksByMask.begin(); toRemove != oldBlocksByMask.end(); toRemove++)
+ {
+ removed_classes.push_back(toRemove->second);
}
- return true;
}
-/* Callback called before processing the first <banlist> tag
- */
-bool InitMaxBans(ServerConfig* conf, const char*)
-{
- conf->maxbans.clear();
- return true;
-}
-/* Callback called to process a single <banlist> tag
+static const Deprecated ChangedConfig[] = {
+ {"options", "hidelinks", "has been moved to <security:hidelinks> as of 1.2a3"},
+ {"options", "hidewhois", "has been moved to <security:hidewhois> as of 1.2a3"},
+ {"options", "userstats", "has been moved to <security:userstats> as of 1.2a3"},
+ {"options", "customversion", "has been moved to <security:customversion> as of 1.2a3"},
+ {"options", "hidesplits", "has been moved to <security:hidesplits> as of 1.2a3"},
+ {"options", "hidebans", "has been moved to <security:hidebans> as of 1.2a3"},
+ {"options", "hidekills", "has been moved to <security:hidekills> as of 1.2a3"},
+ {"options", "operspywhois", "has been moved to <security:operspywhois> as of 1.2a3"},
+ {"options", "announceinvites", "has been moved to <security:announceinvites> as of 1.2a3"},
+ {"options", "hidemodes", "has been moved to <security:hidemodes> as of 1.2a3"},
+ {"options", "maxtargets", "has been moved to <security:maxtargets> as of 1.2a3"},
+ {"options", "nouserdns", "has been moved to <performance:nouserdns> as of 1.2a3"},
+ {"options", "maxwho", "has been moved to <performance:maxwho> as of 1.2a3"},
+ {"options", "softlimit", "has been moved to <performance:softlimit> as of 1.2a3"},
+ {"options", "somaxconn", "has been moved to <performance:somaxconn> as of 1.2a3"},
+ {"options", "netbuffersize", "has been moved to <performance:netbuffersize> as of 1.2a3"},
+ {"options", "maxwho", "has been moved to <performance:maxwho> as of 1.2a3"},
+ {"options", "loglevel", "1.2 does not use the loglevel value. Please define <log> tags instead."},
+ {"die", "value", "has always been deprecated"},
+};
+
+/* These tags can occur ONCE or not at all */
+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},
+ {"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},
+ {"performance", "netbuffersize","10240", new ValueContainerInt (&ServerConfig::NetBufferSize), DT_INTEGER, ValidateNetBufferSize},
+ {"performance", "maxwho", "128", 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", "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", "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", "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", "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},
+ {"performance", "nouserdns", "0", new ValueContainerBool (&ServerConfig::NoUserDns), DT_BOOLEAN, NULL},
+ {"options", "syntaxhints", "0", new ValueContainerBool (&ServerConfig::SyntaxHints), DT_BOOLEAN, NULL},
+ {"options", "cyclehosts", "0", new ValueContainerBool (&ServerConfig::CycleHosts), DT_BOOLEAN, NULL},
+ {"options", "ircumsgprefix","0", new ValueContainerBool (&ServerConfig::UndernetMsgPrefix), DT_BOOLEAN, NULL},
+ {"security", "announceinvites", "1", NULL, DT_NOTHING, ValidateInvite},
+ {"options", "hostintopic", "1", new ValueContainerBool (&ServerConfig::FullHostInTopic), DT_BOOLEAN, NULL},
+ {"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},
+ {"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},
+ {"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},
+ {"cidr", "ipv6clone", "128", new ValueContainerInt (&ServerConfig::c_ipv6_range), DT_INTEGER, NULL},
+ {"limits", "maxnick", "32", new ValueContainerLimit (&ServerLimits::NickMax), DT_LIMIT, NULL},
+ {"limits", "maxchan", "64", new ValueContainerLimit (&ServerLimits::ChanMax), DT_LIMIT, NULL},
+ {"limits", "maxmodes", "20", new ValueContainerLimit (&ServerLimits::MaxModes), DT_LIMIT, NULL},
+ {"limits", "maxident", "11", new ValueContainerLimit (&ServerLimits::IdentMax), DT_LIMIT, NULL},
+ {"limits", "maxquit", "255", new ValueContainerLimit (&ServerLimits::MaxQuit), DT_LIMIT, NULL},
+ {"limits", "maxtopic", "307", new ValueContainerLimit (&ServerLimits::MaxTopic), DT_LIMIT, NULL},
+ {"limits", "maxkick", "255", new ValueContainerLimit (&ServerLimits::MaxKick), DT_LIMIT, NULL},
+ {"limits", "maxgecos", "128", new ValueContainerLimit (&ServerLimits::MaxGecos), DT_LIMIT, NULL},
+ {"limits", "maxaway", "200", new ValueContainerLimit (&ServerLimits::MaxAway), DT_LIMIT, NULL},
+ {"options", "invitebypassmodes", "1", new ValueContainerBool (&ServerConfig::InvBypassModes), DT_BOOLEAN, NULL},
+};
+
+/* These tags can occur multiple times, and therefore they have special code to read them
+ * which is different to the code for reading the singular tags listed above.
*/
-bool DoMaxBans(ServerConfig* conf, const char*, char**, ValueList &values, int*)
+MultiConfig MultiValues[] = {
+
+ {"connect",
+ {"allow", "deny", "password", "timeout", "pingfreq",
+ "sendq", "recvq", "localmax", "globalmax", "port",
+ "name", "parent", "maxchans", "limit", "hash",
+ NULL},
+ {"", "", "", "", "120",
+ "", "", "3", "3", "0",
+ "", "", "0", "0", "",
+ NULL},
+ {DT_IPADDRESS|DT_ALLOW_WILD, DT_IPADDRESS|DT_ALLOW_WILD, DT_CHARPTR, DT_INTEGER, DT_INTEGER,
+ DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER,
+ DT_NOSPACES, DT_NOSPACES, DT_INTEGER, DT_INTEGER, DT_CHARPTR},
+ NULL,},
+
+ {"uline",
+ {"server", "silent", NULL},
+ {"", "0", NULL},
+ {DT_HOSTNAME, DT_BOOLEAN},
+ DoULine},
+
+ {"banlist",
+ {"chan", "limit", NULL},
+ {"", "", NULL},
+ {DT_CHARPTR, DT_INTEGER},
+ DoMaxBans},
+
+ {"module",
+ {"name", NULL},
+ {"", NULL},
+ {DT_CHARPTR},
+ NULL},
+
+ {"badip",
+ {"reason", "ipmask", NULL},
+ {"No reason", "", NULL},
+ {DT_CHARPTR, DT_IPADDRESS|DT_ALLOW_WILD},
+ DoZLine},
+
+ {"badnick",
+ {"reason", "nick", NULL},
+ {"No reason", "", NULL},
+ {DT_CHARPTR, DT_CHARPTR},
+ DoQLine},
+
+ {"badhost",
+ {"reason", "host", NULL},
+ {"No reason", "", NULL},
+ {DT_CHARPTR, DT_CHARPTR},
+ DoKLine},
+
+ {"exception",
+ {"reason", "host", NULL},
+ {"No reason", "", NULL},
+ {DT_CHARPTR, DT_CHARPTR},
+ DoELine},
+
+ {"type",
+ {"name", "classes", NULL},
+ {"", "", NULL},
+ {DT_NOSPACES, DT_CHARPTR},
+ DoType},
+
+ {"class",
+ {"name", "commands", "usermodes", "chanmodes", "privs", NULL},
+ {"", "", "", "", "", NULL},
+ {DT_NOSPACES, DT_CHARPTR, DT_CHARPTR, DT_CHARPTR, DT_CHARPTR},
+ DoClass},
+};
+
+/* These tags MUST occur and must ONLY occur once in the config file */
+static const char* Once[] = { "server", "admin", "files", "power", "options" };
+
+// WARNING: it is not safe to use most of the codebase in this function, as it
+// will run in the config reader thread
+void ServerConfig::Read()
{
- const char* channel = values[0].GetString();
- int limit = values[1].GetInteger();
- conf->maxbans[channel] = limit;
- return true;
-}
+ /* Load and parse the config file, if there are any errors then explode */
-/* Callback called when there are no more <banlist> tags.
- */
-bool DoneMaxBans(ServerConfig*, const char*)
-{
- return true;
+ if (!this->DoInclude(ServerInstance->ConfigFileName))
+ {
+ valid = false;
+ return;
+ }
}
-void ServerConfig::Read()
+void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
{
- static char maxkeep[MAXBUF]; /* Temporary buffer for WhoWasMaxKeep value */
- static char hidemodes[MAXBUF]; /* Modes to not allow listing from users below halfop */
- static char exemptchanops[MAXBUF]; /* Exempt channel ops from these modes */
- static char announceinvites[MAXBUF]; /* options:announceinvites setting */
- static char disabledumodes[MAXBUF]; /* Disabled usermodes */
- static char disabledcmodes[MAXBUF]; /* Disabled chanmodes */
valid = true;
/* std::ostringstream::clear() does not clear the string itself, only the error flags. */
errstr.clear();
errstr.str().clear();
include_stack.clear();
- /* These tags MUST occur and must ONLY occur once in the config file */
- static const char* Once[] = { "server", "admin", "files", "power", "options", NULL };
-
- Deprecated ChangedConfig[] = {
- {"options", "hidelinks", "has been moved to <security:hidelinks> as of 1.2a3"},
- {"options", "hidewhois", "has been moved to <security:hidewhois> as of 1.2a3"},
- {"options", "userstats", "has been moved to <security:userstats> as of 1.2a3"},
- {"options", "customversion", "has been moved to <security:customversion> as of 1.2a3"},
- {"options", "hidesplits", "has been moved to <security:hidesplits> as of 1.2a3"},
- {"options", "hidebans", "has been moved to <security:hidebans> as of 1.2a3"},
- {"options", "hidekills", "has been moved to <security:hidekills> as of 1.2a3"},
- {"options", "operspywhois", "has been moved to <security:operspywhois> as of 1.2a3"},
- {"options", "announceinvites", "has been moved to <security:announceinvites> as of 1.2a3"},
- {"options", "hidemodes", "has been moved to <security:hidemodes> as of 1.2a3"},
- {"options", "maxtargets", "has been moved to <security:maxtargets> as of 1.2a3"},
- {"options", "nouserdns", "has been moved to <performance:nouserdns> as of 1.2a3"},
- {"options", "maxwho", "has been moved to <performance:maxwho> as of 1.2a3"},
- {"options", "softlimit", "has been moved to <performance:softlimit> as of 1.2a3"},
- {"options", "somaxconn", "has been moved to <performance:somaxconn> as of 1.2a3"},
- {"options", "netbuffersize", "has been moved to <performance:netbuffersize> as of 1.2a3"},
- {"options", "maxwho", "has been moved to <performance:maxwho> as of 1.2a3"},
- {"options", "loglevel", "1.2 does not use the loglevel value. Please define <log> tags instead."},
- {NULL, NULL, NULL}
- };
-
- /* These tags can occur ONCE or not at all */
- InitialConfig Values[] = {
- {"performance", "softlimit", "0", new ValueContainerUInt (&this->SoftLimit), DT_INTEGER, ValidateSoftLimit},
- {"performance", "somaxconn", SOMAXCONN_S, new ValueContainerInt (&this->MaxConn), DT_INTEGER, ValidateMaxConn},
- {"options", "moronbanner", "Youre banned!", new ValueContainerChar (this->MoronBanner), DT_CHARPTR, NoValidation},
- {"server", "name", "", new ValueContainerChar (this->ServerName), DT_HOSTNAME, ValidateServerName},
- {"server", "description", "Configure Me", new ValueContainerChar (this->ServerDesc), DT_CHARPTR, NoValidation},
- {"server", "network", "Network", new ValueContainerChar (this->Network), DT_NOSPACES, NoValidation},
- {"server", "id", "", new ValueContainerChar (this->sid), DT_CHARPTR, ValidateSID},
- {"admin", "name", "", new ValueContainerChar (this->AdminName), DT_CHARPTR, NoValidation},
- {"admin", "email", "Mis@configu.red", new ValueContainerChar (this->AdminEmail), DT_CHARPTR, NoValidation},
- {"admin", "nick", "Misconfigured", new ValueContainerChar (this->AdminNick), DT_CHARPTR, NoValidation},
- {"files", "motd", "", new ValueContainerChar (this->motd), DT_CHARPTR, ValidateMotd},
- {"files", "rules", "", new ValueContainerChar (this->rules), DT_CHARPTR, ValidateRules},
- {"power", "diepass", "", new ValueContainerChar (this->diepass), DT_CHARPTR, ValidateNotEmpty},
- {"power", "pause", "", new ValueContainerInt (&this->DieDelay), DT_INTEGER, NoValidation},
- {"power", "hash", "", new ValueContainerChar (this->powerhash), DT_CHARPTR, NoValidation},
- {"power", "restartpass", "", new ValueContainerChar (this->restartpass), DT_CHARPTR, ValidateNotEmpty},
- {"options", "prefixquit", "", new ValueContainerChar (this->PrefixQuit), DT_CHARPTR, NoValidation},
- {"options", "suffixquit", "", new ValueContainerChar (this->SuffixQuit), DT_CHARPTR, NoValidation},
- {"options", "fixedquit", "", new ValueContainerChar (this->FixedQuit), DT_CHARPTR, NoValidation},
- {"options", "prefixpart", "", new ValueContainerChar (this->PrefixPart), DT_CHARPTR, NoValidation},
- {"options", "suffixpart", "", new ValueContainerChar (this->SuffixPart), DT_CHARPTR, NoValidation},
- {"options", "fixedpart", "", new ValueContainerChar (this->FixedPart), DT_CHARPTR, NoValidation},
- {"performance", "netbuffersize","10240", new ValueContainerInt (&this->NetBufferSize), DT_INTEGER, ValidateNetBufferSize},
- {"performance", "maxwho", "128", new ValueContainerInt (&this->MaxWhoResults), DT_INTEGER, ValidateMaxWho},
- {"options", "allowhalfop", "0", new ValueContainerBool (&this->AllowHalfop), DT_BOOLEAN, ValidateHalfOp},
- {"dns", "server", "", new ValueContainerChar (this->DNSServer), DT_IPADDRESS,DNSServerValidator},
- {"dns", "timeout", "5", new ValueContainerInt (&this->dns_timeout), DT_INTEGER, NoValidation},
- {"options", "moduledir", MOD_PATH, new ValueContainerChar (this->ModPath), DT_CHARPTR, NoValidation},
- {"disabled", "commands", "", new ValueContainerChar (this->DisabledCommands), DT_CHARPTR, NoValidation},
- {"disabled", "usermodes", "", new ValueContainerChar (disabledumodes), DT_CHARPTR, ValidateDisabledUModes},
- {"disabled", "chanmodes", "", new ValueContainerChar (disabledcmodes), DT_CHARPTR, ValidateDisabledCModes},
- {"disabled", "fakenonexistant", "0", new ValueContainerBool (&this->DisabledDontExist), DT_BOOLEAN, NoValidation},
-
- {"security", "runasuser", "", new ValueContainerChar(this->SetUser), DT_CHARPTR, NoValidation},
- {"security", "runasgroup", "", new ValueContainerChar(this->SetGroup), DT_CHARPTR, NoValidation},
- {"security", "userstats", "", new ValueContainerChar (this->UserStats), DT_CHARPTR, NoValidation},
- {"security", "customversion","", new ValueContainerChar (this->CustomVersion), DT_CHARPTR, NoValidation},
- {"security", "hidesplits", "0", new ValueContainerBool (&this->HideSplits), DT_BOOLEAN, NoValidation},
- {"security", "hidebans", "0", new ValueContainerBool (&this->HideBans), DT_BOOLEAN, NoValidation},
- {"security", "hidewhois", "", new ValueContainerChar (this->HideWhoisServer), DT_NOSPACES, NoValidation},
- {"security", "hidekills", "", new ValueContainerChar (this->HideKillsServer), DT_NOSPACES, NoValidation},
- {"security", "operspywhois", "0", new ValueContainerBool (&this->OperSpyWhois), DT_BOOLEAN, NoValidation},
- {"security", "restrictbannedusers", "1", new ValueContainerBool (&this->RestrictBannedUsers), DT_BOOLEAN, NoValidation},
- {"security", "genericoper", "0", new ValueContainerBool (&this->GenericOper), DT_BOOLEAN, NoValidation},
- {"performance", "nouserdns", "0", new ValueContainerBool (&this->NoUserDns), DT_BOOLEAN, NoValidation},
- {"options", "syntaxhints", "0", new ValueContainerBool (&this->SyntaxHints), DT_BOOLEAN, NoValidation},
- {"options", "cyclehosts", "0", new ValueContainerBool (&this->CycleHosts), DT_BOOLEAN, NoValidation},
- {"options", "ircumsgprefix","0", new ValueContainerBool (&this->UndernetMsgPrefix), DT_BOOLEAN, NoValidation},
- {"security", "announceinvites", "1", new ValueContainerChar (announceinvites), DT_CHARPTR, ValidateInvite},
- {"options", "hostintopic", "1", new ValueContainerBool (&this->FullHostInTopic), DT_BOOLEAN, NoValidation},
- {"security", "hidemodes", "", new ValueContainerChar (hidemodes), DT_CHARPTR, ValidateModeLists},
- {"options", "exemptchanops","", new ValueContainerChar (exemptchanops), DT_CHARPTR, ValidateExemptChanOps},
- {"security", "maxtargets", "20", new ValueContainerUInt (&this->MaxTargets), DT_INTEGER, ValidateMaxTargets},
- {"options", "defaultmodes", "nt", new ValueContainerChar (this->DefaultModes), DT_CHARPTR, NoValidation},
- {"pid", "file", "", new ValueContainerChar (this->PID), DT_CHARPTR, NoValidation},
- {"whowas", "groupsize", "10", new ValueContainerInt (&this->WhoWasGroupSize), DT_INTEGER, NoValidation},
- {"whowas", "maxgroups", "10240", new ValueContainerInt (&this->WhoWasMaxGroups), DT_INTEGER, NoValidation},
- {"whowas", "maxkeep", "3600", new ValueContainerChar (maxkeep), DT_CHARPTR, ValidateWhoWas},
- {"die", "value", "", new ValueContainerChar (this->DieValue), DT_CHARPTR, NoValidation},
- {"channels", "users", "20", new ValueContainerUInt (&this->MaxChans), DT_INTEGER, NoValidation},
- {"channels", "opers", "60", new ValueContainerUInt (&this->OperMaxChans), DT_INTEGER, NoValidation},
- {"cidr", "ipv4clone", "32", new ValueContainerInt (&this->c_ipv4_range), DT_INTEGER, NoValidation},
- {"cidr", "ipv6clone", "128", new ValueContainerInt (&this->c_ipv6_range), DT_INTEGER, NoValidation},
- {"limits", "maxnick", "32", new ValueContainerST (&this->Limits.NickMax), DT_INTEGER, NoValidation},
- {"limits", "maxchan", "64", new ValueContainerST (&this->Limits.ChanMax), DT_INTEGER, NoValidation},
- {"limits", "maxmodes", "20", new ValueContainerST (&this->Limits.MaxModes), DT_INTEGER, NoValidation},
- {"limits", "maxident", "11", new ValueContainerST (&this->Limits.IdentMax), DT_INTEGER, NoValidation},
- {"limits", "maxquit", "255", new ValueContainerST (&this->Limits.MaxQuit), DT_INTEGER, NoValidation},
- {"limits", "maxtopic", "307", new ValueContainerST (&this->Limits.MaxTopic), DT_INTEGER, NoValidation},
- {"limits", "maxkick", "255", new ValueContainerST (&this->Limits.MaxKick), DT_INTEGER, NoValidation},
- {"limits", "maxgecos", "128", new ValueContainerST (&this->Limits.MaxGecos), DT_INTEGER, NoValidation},
- {"limits", "maxaway", "200", new ValueContainerST (&this->Limits.MaxAway), DT_INTEGER, NoValidation},
- {"options", "invitebypassmodes", "1", new ValueContainerBool (&this->InvBypassModes), DT_BOOLEAN, NoValidation},
- {NULL, NULL, NULL, NULL, DT_NOTHING, NoValidation}
- };
-
-
- /* These tags can occur multiple times, and therefore they have special code to read them
- * which is different to the code for reading the singular tags listed above.
- */
- MultiConfig MultiValues[] = {
-
- {"connect",
- {"allow", "deny", "password", "timeout", "pingfreq",
- "sendq", "recvq", "localmax", "globalmax", "port",
- "name", "parent", "maxchans", "limit", "hash",
- NULL},
- {"", "", "", "", "120",
- "", "", "3", "3", "0",
- "", "", "0", "0", "",
- NULL},
- {DT_IPADDRESS|DT_ALLOW_WILD, DT_IPADDRESS|DT_ALLOW_WILD, DT_CHARPTR, DT_INTEGER, DT_INTEGER,
- DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER,
- DT_NOSPACES, DT_NOSPACES, DT_INTEGER, DT_INTEGER, DT_CHARPTR},
- InitConnect, DoConnect, DoneConnect},
-
- {"uline",
- {"server", "silent", NULL},
- {"", "0", NULL},
- {DT_HOSTNAME, DT_BOOLEAN},
- InitULine,DoULine,DoneULine},
-
- {"banlist",
- {"chan", "limit", NULL},
- {"", "", NULL},
- {DT_CHARPTR, DT_INTEGER},
- InitMaxBans, DoMaxBans, DoneMaxBans},
-
- {"module",
- {"name", NULL},
- {"", NULL},
- {DT_CHARPTR},
- InitModule, DoModule, DoneModule},
-
- {"badip",
- {"reason", "ipmask", NULL},
- {"No reason", "", NULL},
- {DT_CHARPTR, DT_IPADDRESS|DT_ALLOW_WILD},
- InitXLine, DoZLine, DoneConfItem},
-
- {"badnick",
- {"reason", "nick", NULL},
- {"No reason", "", NULL},
- {DT_CHARPTR, DT_CHARPTR},
- InitXLine, DoQLine, DoneConfItem},
-
- {"badhost",
- {"reason", "host", NULL},
- {"No reason", "", NULL},
- {DT_CHARPTR, DT_CHARPTR},
- InitXLine, DoKLine, DoneConfItem},
-
- {"exception",
- {"reason", "host", NULL},
- {"No reason", "", NULL},
- {DT_CHARPTR, DT_CHARPTR},
- InitXLine, DoELine, DoneELine},
-
- {"type",
- {"name", "classes", NULL},
- {"", "", NULL},
- {DT_NOSPACES, DT_CHARPTR},
- InitTypes, DoType, DoneClassesAndTypes},
-
- {"class",
- {"name", "commands", "usermodes", "chanmodes", "privs", NULL},
- {"", "", "", "", "", NULL},
- {DT_NOSPACES, DT_CHARPTR, DT_CHARPTR, DT_CHARPTR, DT_CHARPTR},
- InitClasses, DoClass, DoneClassesAndTypes},
-
- {NULL,
- {NULL},
- {NULL},
- {0},
- NULL, NULL, NULL}
- };
-
- /* Load and parse the config file, if there are any errors then explode */
-
- if (!this->DoInclude(ServerInstance->ConfigFileName))
- {
- valid = false;
- return;
- }
-
/* The stuff in here may throw CoreException, be sure we're in a position to catch it. */
try
{
/* Check we dont have more than one of singular tags, or any of them missing
*/
- for (int Index = 0; Once[Index]; Index++)
- if (!CheckOnce(Once[Index]))
- return;
+ for (int Index = 0; Index * sizeof(*Once) < sizeof(Once); Index++)
+ CheckOnce(Once[Index]);
- for (int Index = 0; ChangedConfig[Index].tag; Index++)
+ for (int Index = 0; Index * sizeof(Deprecated) < sizeof(ChangedConfig); Index++)
{
char item[MAXBUF];
*item = 0;
@@ -932,7 +939,7 @@ void ServerConfig::Read()
/* Read the values of all the tags which occur once or not at all, and call their callbacks.
*/
- for (int Index = 0; Values[Index].tag; ++Index)
+ for (int Index = 0; Index * sizeof(*Values) < sizeof(Values); ++Index)
{
char item[MAXBUF];
int dt = Values[Index].datatype;
@@ -944,7 +951,7 @@ void ServerConfig::Read()
ConfValue(Values[Index].tag, Values[Index].value, Values[Index].default_value, 0, item, MAXBUF, allow_newlines);
ValueItem vi(item);
- if (!Values[Index].validation_function(this, Values[Index].tag, Values[Index].value, vi))
+ if (Values[Index].validation_function && !Values[Index].validation_function(this, Values[Index].tag, Values[Index].value, vi))
throw CoreException("One or more values in your configuration file failed to validate. Please see your ircd.log for more information.");
switch (dt)
@@ -952,22 +959,22 @@ void ServerConfig::Read()
case DT_NOSPACES:
{
ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
- this->ValidateNoSpaces(vi.GetString(), Values[Index].tag, Values[Index].value);
- vcc->Set(vi.GetString(), strlen(vi.GetString()) + 1);
+ ValidateNoSpaces(vi.GetString(), Values[Index].tag, Values[Index].value);
+ vcc->Set(this, vi);
}
break;
case DT_HOSTNAME:
{
ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
- this->ValidateHostname(vi.GetString(), Values[Index].tag, Values[Index].value);
- vcc->Set(vi.GetString(), strlen(vi.GetString()) + 1);
+ ValidateHostname(vi.GetString(), Values[Index].tag, Values[Index].value);
+ vcc->Set(this, vi);
}
break;
case DT_IPADDRESS:
{
ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
- this->ValidateIP(vi.GetString(), Values[Index].tag, Values[Index].value, allow_wild);
- vcc->Set(vi.GetString(), strlen(vi.GetString()) + 1);
+ ValidateIP(vi.GetString(), Values[Index].tag, Values[Index].value, allow_wild);
+ vcc->Set(this, vi);
}
break;
case DT_CHANNEL:
@@ -977,33 +984,40 @@ void ServerConfig::Read()
{
throw CoreException("The value of <"+std::string(Values[Index].tag)+":"+Values[Index].value+"> is not a valid channel name");
}
- vcc->Set(vi.GetString(), strlen(vi.GetString()) + 1);
+ vcc->Set(this, vi);
}
break;
case DT_CHARPTR:
{
- ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
- /* Make sure we also copy the null terminator */
- vcc->Set(vi.GetString(), strlen(vi.GetString()) + 1);
+ 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());
}
break;
case DT_INTEGER:
{
int val = vi.GetInteger();
ValueContainerInt* vci = (ValueContainerInt*)Values[Index].val;
- vci->Set(&val, sizeof(int));
+ vci->Set(this, val);
+ }
+ break;
+ case DT_LIMIT:
+ {
+ int val = vi.GetInteger();
+ ValueContainerLimit* vci = (ValueContainerLimit*)Values[Index].val;
+ vci->Set(this, val);
}
break;
case DT_BOOLEAN:
{
bool val = vi.GetBool();
ValueContainerBool* vcb = (ValueContainerBool*)Values[Index].val;
- vcb->Set(&val, sizeof(bool));
+ vcb->Set(this, val);
}
break;
- default:
- /* You don't want to know what happens if someones bad code sends us here. */
- break;
}
/* We're done with this now */
delete Values[Index].val;
@@ -1013,10 +1027,8 @@ void ServerConfig::Read()
* and call the callbacks associated with them. We have three
* callbacks for these, a 'start', 'item' and 'end' callback.
*/
- for (int Index = 0; MultiValues[Index].tag; ++Index)
+ for (int Index = 0; Index * sizeof(MultiConfig) < sizeof(MultiValues); ++Index)
{
- MultiValues[Index].init_function(this, MultiValues[Index].tag);
-
int number_of_tags = ConfValueEnum(MultiValues[Index].tag);
for (int tagnum = 0; tagnum < number_of_tags; ++tagnum)
@@ -1039,7 +1051,7 @@ void ServerConfig::Read()
vl.push_back(ValueItem(item));
else
vl.push_back(ValueItem(""));
- this->ValidateNoSpaces(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum]);
+ ValidateNoSpaces(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum]);
}
break;
case DT_HOSTNAME:
@@ -1049,7 +1061,7 @@ void ServerConfig::Read()
vl.push_back(ValueItem(item));
else
vl.push_back(ValueItem(""));
- this->ValidateHostname(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum]);
+ ValidateHostname(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum]);
}
break;
case DT_IPADDRESS:
@@ -1059,7 +1071,7 @@ void ServerConfig::Read()
vl.push_back(ValueItem(item));
else
vl.push_back(ValueItem(""));
- this->ValidateIP(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum], allow_wild);
+ ValidateIP(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum], allow_wild);
}
break;
case DT_CHANNEL:
@@ -1097,14 +1109,11 @@ void ServerConfig::Read()
vl.push_back(ValueItem(item));
}
break;
- default:
- /* Someone was smoking craq if we got here, and we're all gonna die. */
- break;
}
}
- MultiValues[Index].validation_function(this, MultiValues[Index].tag, (char**)MultiValues[Index].items, vl, MultiValues[Index].datatype);
+ if (MultiValues[Index].validation_function)
+ MultiValues[Index].validation_function(this, MultiValues[Index].tag, MultiValues[Index].items, vl, MultiValues[Index].datatype);
}
- MultiValues[Index].finish_function(this, MultiValues[Index].tag);
}
/* Finalise the limits, increment them all by one so that we can just put assign(str, 0, val)
@@ -1112,51 +1121,16 @@ void ServerConfig::Read()
*/
Limits.Finalise();
+ // Handle special items
+ CrossCheckOperClassType();
+ CrossCheckConnectBlocks(old);
}
-
catch (CoreException &ce)
{
errstr << ce.GetReason();
valid = false;
- return;
}
- for (int i = 0; i < ConfValueEnum("type"); ++i)
- {
- char item[MAXBUF], classn[MAXBUF], classes[MAXBUF];
- std::string classname;
- ConfValue("type", "classes", "", i, classes, MAXBUF, false);
- irc::spacesepstream str(classes);
- ConfValue("type", "name", "", i, item, MAXBUF, false);
- while (str.GetToken(classname))
- {
- std::string lost;
- bool foundclass = false;
- for (int j = 0; j < ConfValueEnum("class"); ++j)
- {
- ConfValue("class", "name", "", j, classn, MAXBUF, false);
- if (!strcmp(classn, classname.c_str()))
- {
- foundclass = true;
- break;
- }
- }
- if (!foundclass)
- {
- char msg[MAXBUF];
- snprintf(msg, MAXBUF, " Warning: Oper type '%s' has a missing class named '%s', this does nothing!\n",
- item, classname.c_str());
- errstr << msg;
- }
- }
- }
-
-}
-
-void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
-{
- int rem = 0, add = 0;
- bool errors = false;
// write once here, to try it out and make sure its ok
ServerInstance->WritePID(this->PID);
@@ -1187,8 +1161,8 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
User* user = useruid.empty() ? NULL : ServerInstance->FindNick(useruid);
- errors = !errstr.str().empty();
- if (errors)
+ valid = errstr.str().empty();
+ if (!valid)
ServerInstance->Logs->Log("CONFIG",DEFAULT, "There were errors in your configuration file:");
while (errstr.good())
@@ -1216,65 +1190,82 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
/* No old configuration -> initial boot, nothing more to do here */
if (!old)
{
- if (errors)
+ if (!valid)
{
ServerInstance->Exit(EXIT_STATUS_CONFIG);
}
return;
}
-
+
// If there were errors processing configuration, don't touch modules.
- if (errors)
+ if (!valid)
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;
+ }
+}
- if (!removed_modules.empty())
+void ServerConfig::ApplyModules(User* user)
+{
+ const std::vector<std::string> v = ServerInstance->Modules->GetAllModuleNames(0);
+ std::vector<std::string> added_modules;
+ std::set<std::string> removed_modules(v.begin(), v.end());
+
+ int new_module_count = ConfValueEnum("module");
+ for(int i=0; i < new_module_count; i++)
{
- for (std::vector<std::string>::iterator removing = removed_modules.begin(); removing != removed_modules.end(); removing++)
+ std::string name;
+ if (ConfValue("module", "name", i, name, false))
{
- if (ServerInstance->Modules->Unload(removing->c_str()))
- {
- ServerInstance->SNO->WriteToSnoMask('a', "*** REHASH UNLOADED MODULE: %s",removing->c_str());
+ // if this module is already loaded, the erase will succeed, so we need do nothing
+ // otherwise, we need to add the module (which will be done later)
+ if (removed_modules.erase(name) == 0)
+ added_modules.push_back(name);
+ }
+ }
- if (user)
- user->WriteNumeric(RPL_UNLOADEDMODULE, "%s %s :Module %s successfully unloaded.",user->nick.c_str(), removing->c_str(), removing->c_str());
- else
- ServerInstance->SNO->WriteToSnoMask('a', "Module %s successfully unloaded.", removing->c_str());
+ for (std::set<std::string>::iterator removing = removed_modules.begin(); removing != removed_modules.end(); removing++)
+ {
+ if (ServerInstance->Modules->Unload(removing->c_str()))
+ {
+ ServerInstance->SNO->WriteToSnoMask('a', "*** REHASH UNLOADED MODULE: %s",removing->c_str());
- rem++;
- }
+ if (user)
+ user->WriteNumeric(RPL_UNLOADEDMODULE, "%s %s :Module %s successfully unloaded.",user->nick.c_str(), removing->c_str(), removing->c_str());
else
- {
- if (user)
- user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s %s :Failed to unload module %s: %s",user->nick.c_str(), removing->c_str(), removing->c_str(), ServerInstance->Modules->LastError().c_str());
- else
- ServerInstance->SNO->WriteToSnoMask('a', "Failed to unload module %s: %s", removing->c_str(), ServerInstance->Modules->LastError().c_str());
- }
+ ServerInstance->SNO->WriteToSnoMask('a', "Module %s successfully unloaded.", removing->c_str());
+ }
+ else
+ {
+ if (user)
+ user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s %s :Failed to unload module %s: %s",user->nick.c_str(), removing->c_str(), removing->c_str(), ServerInstance->Modules->LastError().c_str());
+ else
+ ServerInstance->SNO->WriteToSnoMask('a', "Failed to unload module %s: %s", removing->c_str(), ServerInstance->Modules->LastError().c_str());
}
}
- if (!added_modules.empty())
+ for (std::vector<std::string>::iterator adding = added_modules.begin(); adding != added_modules.end(); adding++)
{
- for (std::vector<std::string>::iterator adding = added_modules.begin(); adding != added_modules.end(); adding++)
+ if (ServerInstance->Modules->Load(adding->c_str()))
{
- if (ServerInstance->Modules->Load(adding->c_str()))
- {
- ServerInstance->SNO->WriteToSnoMask('a', "*** REHASH LOADED MODULE: %s",adding->c_str());
- if (user)
- user->WriteNumeric(RPL_LOADEDMODULE, "%s %s :Module %s successfully loaded.",user->nick.c_str(), adding->c_str(), adding->c_str());
- else
- ServerInstance->SNO->WriteToSnoMask('a', "Module %s successfully loaded.", adding->c_str());
-
- add++;
- }
+ ServerInstance->SNO->WriteToSnoMask('a', "*** REHASH LOADED MODULE: %s",adding->c_str());
+ if (user)
+ user->WriteNumeric(RPL_LOADEDMODULE, "%s %s :Module %s successfully loaded.",user->nick.c_str(), adding->c_str(), adding->c_str());
else
- {
- if (user)
- user->WriteNumeric(ERR_CANTLOADMODULE, "%s %s :Failed to load module %s: %s",user->nick.c_str(), adding->c_str(), adding->c_str(), ServerInstance->Modules->LastError().c_str());
- else
- ServerInstance->SNO->WriteToSnoMask('a', "Failed to load module %s: %s", adding->c_str(), ServerInstance->Modules->LastError().c_str());
- }
+ ServerInstance->SNO->WriteToSnoMask('a', "Module %s successfully loaded.", adding->c_str());
+ }
+ else
+ {
+ if (user)
+ user->WriteNumeric(ERR_CANTLOADMODULE, "%s %s :Failed to load module %s: %s",user->nick.c_str(), adding->c_str(), adding->c_str(), ServerInstance->Modules->LastError().c_str());
+ else
+ ServerInstance->SNO->WriteToSnoMask('a', "Failed to load module %s: %s", adding->c_str(), ServerInstance->Modules->LastError().c_str());
}
}
@@ -2036,12 +2027,7 @@ ValueItem::ValueItem(bool value)
v = n.str();
}
-ValueItem::ValueItem(const char* value)
-{
- v = value;
-}
-
-void ValueItem::Set(const char* value)
+void ValueItem::Set(const std::string& value)
{
v = value;
}
@@ -2060,9 +2046,9 @@ int ValueItem::GetInteger()
return atoi(v.c_str());
}
-char* ValueItem::GetString()
+const char* ValueItem::GetString() const
{
- return (char*)v.c_str();
+ return v.c_str();
}
bool ValueItem::GetBool()
@@ -2071,168 +2057,6 @@ bool ValueItem::GetBool()
}
-
-
-/*
- * XXX should this be in a class? -- w00t
- */
-bool InitTypes(ServerConfig* conf, const char*)
-{
- conf->opertypes.clear();
- return true;
-}
-
-/*
- * XXX should this be in a class? -- w00t
- */
-bool InitClasses(ServerConfig* conf, const char*)
-{
- if (conf->operclass.size())
- {
- for (operclass_t::iterator n = conf->operclass.begin(); n != conf->operclass.end(); n++)
- {
- if (n->second.commandlist)
- delete[] n->second.commandlist;
- if (n->second.cmodelist)
- delete[] n->second.cmodelist;
- if (n->second.umodelist)
- delete[] n->second.umodelist;
- if (n->second.privs)
- delete[] n->second.privs;
- }
- }
-
- conf->operclass.clear();
- return true;
-}
-
-/*
- * XXX should this be in a class? -- w00t
- */
-bool DoType(ServerConfig* conf, const char*, char**, ValueList &values, int*)
-{
- const char* TypeName = values[0].GetString();
- const char* Classes = values[1].GetString();
-
- conf->opertypes[TypeName] = std::string(Classes);
- return true;
-}
-
-/*
- * XXX should this be in a class? -- w00t
- */
-bool DoClass(ServerConfig* conf, const char* tag, char**, ValueList &values, int*)
-{
- const char* ClassName = values[0].GetString();
- const char* CommandList = values[1].GetString();
- const char* UModeList = values[2].GetString();
- const char* CModeList = values[3].GetString();
- const char *PrivsList = values[4].GetString();
-
- for (const char* c = UModeList; *c; ++c)
- {
- if ((*c < 'A' || *c > 'z') && *c != '*')
- {
- throw CoreException("Character " + std::string(1, *c) + " is not a valid mode in <class:usermodes>");
- }
- }
- for (const char* c = CModeList; *c; ++c)
- {
- if ((*c < 'A' || *c > 'z') && *c != '*')
- {
- throw CoreException("Character " + std::string(1, *c) + " is not a valid mode in <class:chanmodes>");
- }
- }
-
- conf->operclass[ClassName].commandlist = strnewdup(CommandList);
- conf->operclass[ClassName].umodelist = strnewdup(UModeList);
- conf->operclass[ClassName].cmodelist = strnewdup(CModeList);
- conf->operclass[ClassName].privs = strnewdup(PrivsList);
- return true;
-}
-
-/*
- * XXX should this be in a class? -- w00t
- */
-bool DoneClassesAndTypes(ServerConfig*, const char*)
-{
- return true;
-}
-
-
-
-bool InitXLine(ServerConfig* conf, const char* tag)
-{
- return true;
-}
-
-bool DoZLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
-{
- 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))
- delete zl;
-
- return true;
-}
-
-bool DoQLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
-{
- 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))
- delete ql;
-
- return true;
-}
-
-bool DoKLine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
-{
- const char* reason = values[0].GetString();
- const char* host = values[1].GetString();
-
- XLineManager* xlm = conf->GetInstance()->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());
- if (!xlm->AddLine(kl, NULL))
- delete kl;
- return true;
-}
-
-bool DoELine(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
-{
- const char* reason = values[0].GetString();
- const char* host = values[1].GetString();
-
- XLineManager* xlm = conf->GetInstance()->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());
- if (!xlm->AddLine(el, NULL))
- delete el;
- return true;
-}
-
-// this should probably be moved to configreader, but atm it relies on CheckELines above.
-bool DoneELine(ServerConfig* conf, const char* tag)
-{
- for (std::vector<User*>::const_iterator u2 = conf->GetInstance()->Users->local_users.begin(); u2 != conf->GetInstance()->Users->local_users.end(); u2++)
- {
- User* u = (User*)(*u2);
- u->exempt = false;
- }
-
- conf->GetInstance()->XLines->CheckELines();
- return true;
-}
-
void ConfigReaderThread::Run()
{
Config = new ServerConfig(ServerInstance);
@@ -2243,7 +2067,44 @@ void ConfigReaderThread::Run()
void ConfigReaderThread::Finish()
{
ServerConfig* old = ServerInstance->Config;
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"Switching to new configuration...");
+ ServerInstance->Logs->CloseLogs();
ServerInstance->Config = this->Config;
+ ServerInstance->Logs->OpenFileLogs();
Config->Apply(old, TheUserUID);
- delete old;
+
+ if (Config->valid)
+ {
+ /*
+ * Apply the changed configuration from the rehash.
+ *
+ * XXX: The order of these is IMPORTANT, do not reorder them without testing
+ * thoroughly!!!
+ */
+ ServerInstance->XLines->CheckELines();
+ ServerInstance->XLines->CheckELines();
+ ServerInstance->XLines->ApplyLines();
+ ServerInstance->Res->Rehash();
+ ServerInstance->ResetMaxBans();
+ Config->ApplyDisabledCommands(Config->DisabledCommands);
+ User* user = TheUserUID.empty() ? ServerInstance->FindNick(TheUserUID) : NULL;
+ FOREACH_MOD_I(ServerInstance, I_OnRehash, OnRehash(user));
+ ServerInstance->BuildISupport();
+
+ delete old;
+ }
+ else
+ {
+ // whoops, abort!
+ ServerInstance->Logs->CloseLogs();
+ ServerInstance->Config = old;
+ ServerInstance->Logs->OpenFileLogs();
+ delete this->Config;
+ }
+}
+
+template<>
+void ValueContainer<char[MAXBUF]>::Set(ServerConfig* conf, ValueItem const& item)
+{
+ strlcpy(conf->*vptr, item.GetString(), MAXBUF);
}
diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp
index 50a3af61f..26a5db07c 100644
--- a/src/helperfuncs.cpp
+++ b/src/helperfuncs.cpp
@@ -340,16 +340,6 @@ void InspIRCd::CheckRoot()
}
}
-void InspIRCd::CheckDie()
-{
- if (*Config->DieValue)
- {
- printf("WARNING: %s\n\n",Config->DieValue);
- this->Logs->Log("CONFIG",DEFAULT,"Died because of <die> tag: %s",Config->DieValue);
- Exit(EXIT_STATUS_DIETAG);
- }
-}
-
void InspIRCd::SendWhoisLine(User* user, User* dest, int numeric, const std::string &text)
{
std::string copy_text = text;
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 5a792b884..17fa2ce81 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -495,7 +495,7 @@ InspIRCd::InspIRCd(int argc, char** argv)
WSAStartup(MAKEWORD(2,0), &wsadata);
ChangeWindowsSpecificPointers(this);
#endif
- strlcpy(Config->MyExecutable,argv[0],MAXBUF);
+ Config->MyExecutable = argv[0];
/* Set the finished argument values */
Config->nofork = do_nofork;
@@ -536,8 +536,6 @@ InspIRCd::InspIRCd(int argc, char** argv)
printf_c("\t\033[1;32mpeavey, aquanight, psychon, dz, danieldg\033[0m\n\n");
printf_c("Others:\t\t\t\033[1;32mSee /INFO Output\033[0m\n");
- Config->ClearStack();
-
this->Modes = new ModeParser(this);
if (!do_root)
@@ -613,7 +611,6 @@ InspIRCd::InspIRCd(int argc, char** argv)
this->XLines->CheckELines();
this->XLines->ApplyLines();
- CheckDie();
int bounditems = BindPorts(pl);
printf("\n");
@@ -622,7 +619,7 @@ InspIRCd::InspIRCd(int argc, char** argv)
/* Just in case no modules were loaded - fix for bug #101 */
this->BuildISupport();
- InitializeDisabledCommands(Config->DisabledCommands, this);
+ Config->ApplyDisabledCommands(Config->DisabledCommands);
if (!pl.empty())
{
@@ -767,26 +764,7 @@ int InspIRCd::Run()
/* Rehash has completed */
this->Logs->Log("CONFIG",DEBUG,"Detected ConfigThread exiting, tidying up...");
- /* Switch over logfiles */
- Logs->CloseLogs();
- Logs->OpenFileLogs();
-
- /*
- * Apply the changed configuration from the rehash. This is not done within the
- * configuration thread becasuse they may invoke functions that are not threadsafe.
- *
- * XXX: The order of these is IMPORTANT, do not reorder them without testing
- * thoroughly!!!
- */
this->ConfigThread->Finish();
- this->XLines->CheckELines();
- this->XLines->ApplyLines();
- this->Res->Rehash();
- this->ResetMaxBans();
- InitializeDisabledCommands(Config->DisabledCommands, this);
- User* user = ConfigThread->TheUserUID.empty() ? FindNick(ConfigThread->TheUserUID) : NULL;
- FOREACH_MOD_I(this, I_OnRehash, OnRehash(user));
- this->BuildISupport();
ConfigThread->join();
delete ConfigThread;
diff --git a/src/modules.cpp b/src/modules.cpp
index 66134e3bc..fbede2c0a 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -379,7 +379,7 @@ bool ModuleManager::Load(const char* filename)
if (strchr(filename,'*') || (strchr(filename,'?')))
{
int n_match = 0;
- DIR* library = opendir(Instance->Config->ModPath);
+ DIR* library = opendir(Instance->Config->ModPath.c_str());
if (library)
{
/* Try and locate and load all modules matching the pattern */
@@ -402,7 +402,7 @@ bool ModuleManager::Load(const char* filename)
}
char modfile[MAXBUF];
- snprintf(modfile,MAXBUF,"%s/%s",Instance->Config->ModPath,filename);
+ snprintf(modfile,MAXBUF,"%s/%s",Instance->Config->ModPath.c_str(),filename);
std::string filename_str = filename;
if (!ServerConfig::FileExists(modfile))
diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp
index 7e6610901..86b035522 100644
--- a/src/modules/m_check.cpp
+++ b/src/modules/m_check.cpp
@@ -87,7 +87,7 @@ class CommandCheck : public Command
if (IS_LOCAL(targuser))
{
user->WriteServ(checkstr + " onport " + ConvToStr(targuser->GetPort()));
- std::string classname = targuser->GetClass()->GetName();
+ std::string classname = targuser->GetClass()->name;
if (!classname.empty())
user->WriteServ(checkstr + " connectclass " + classname);
}
diff --git a/src/users.cpp b/src/users.cpp
index 26a790dfa..cbc59a49c 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -245,6 +245,8 @@ User::~User()
{
this->MyClass->RefCount--;
ServerInstance->Logs->Log("USERS", DEBUG, "User destructor -- connect refcount now: %lu", this->MyClass->RefCount);
+ if (MyClass->RefCount == 0)
+ delete MyClass;
}
if (this->AllowedOperCommands)
@@ -901,7 +903,7 @@ void User::CheckClass()
{
ConnectClass* a = this->MyClass;
- if ((!a) || (a->GetType() == CC_DENY))
+ if ((!a) || (a->type == CC_DENY))
{
ServerInstance->Users->QuitUser(this, "Unauthorised connection");
return;
@@ -1839,10 +1841,7 @@ ConnectClass* User::SetClass(const std::string &explicit_name)
{
ConnectClass* c = *i;
- if (c->GetDisabled())
- continue; // can't possibly match, removed from conf
-
- if (explicit_name == c->GetName())
+ if (explicit_name == c->name)
{
ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Explicitly set to %s", explicit_name.c_str());
found = c;
@@ -1855,22 +1854,15 @@ ConnectClass* User::SetClass(const std::string &explicit_name)
{
ConnectClass* c = *i;
- if (c->GetType() == CC_ALLOW)
+ if (c->type == CC_ALLOW)
{
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "ALLOW %s %d %s", c->GetHost().c_str(), c->GetPort(), c->GetName().c_str());
+ ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "ALLOW %s %d %s", c->host.c_str(), c->GetPort(), c->GetName().c_str());
}
else
{
ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "DENY %s %d %s", c->GetHost().c_str(), c->GetPort(), c->GetName().c_str());
}
- /* if it's disabled, we can't match this one. */
- if (c->GetDisabled())
- {
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Class disabled");
- continue;
- }
-
/* check if host matches.. */
if (c->GetHost().length() && !InspIRCd::MatchCIDR(this->GetIPString(), c->GetHost(), NULL) &&
!InspIRCd::MatchCIDR(this->host, c->GetHost(), NULL))
@@ -1883,7 +1875,7 @@ ConnectClass* User::SetClass(const std::string &explicit_name)
* deny change if change will take class over the limit check it HERE, not after we found a matching class,
* because we should attempt to find another class if this one doesn't match us. -- w00t
*/
- if (c->limit && (c->RefCount + 1 >= c->limit))
+ if (c->limit && (c->RefCount >= c->limit))
{
ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "OOPS: Connect class limit (%lu) hit, denying", c->limit);
continue;
@@ -1920,6 +1912,8 @@ ConnectClass* User::SetClass(const std::string &explicit_name)
return this->MyClass;
this->MyClass->RefCount--;
ServerInstance->Logs->Log("USERS", DEBUG, "Untying user from connect class -- refcount: %lu", this->MyClass->RefCount);
+ if (MyClass->RefCount == 0)
+ delete MyClass;
}
this->MyClass = found;
@@ -2084,3 +2078,29 @@ bool VisData::VisibleTo(User* user)
{
return true;
}
+
+
+ConnectClass::ConnectClass(char t, const std::string& mask)
+ : type(t), name("unnamed"), registration_timeout(0), host(mask), pingtime(0), pass(""), hash(""), sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), limit(0), RefCount(1)
+{
+}
+
+ConnectClass::ConnectClass(char t, const std::string& mask, const ConnectClass& parent)
+ : type(t), name("unnamed"), registration_timeout(parent.registration_timeout), host(mask), pingtime(parent.pingtime), pass(parent.pass), hash(parent.hash), sendqmax(parent.sendqmax), recvqmax(parent.recvqmax), maxlocal(parent.maxlocal), maxglobal(parent.maxglobal), limit(parent.limit), RefCount(1)
+{
+}
+
+void ConnectClass::Update(const ConnectClass* src)
+{
+ name = src->name;
+ registration_timeout = src->registration_timeout;
+ host = src->host;
+ pingtime = src->pingtime;
+ pass = src->pass;
+ hash = src->hash;
+ sendqmax = src->sendqmax;
+ recvqmax = src->recvqmax;
+ maxlocal = src->maxlocal;
+ maxglobal = src->maxglobal;
+ limit = src->limit;
+}
diff --git a/win/inspircd_win32wrapper.cpp b/win/inspircd_win32wrapper.cpp
index 9d75fd2ea..1008cb838 100644
--- a/win/inspircd_win32wrapper.cpp
+++ b/win/inspircd_win32wrapper.cpp
@@ -416,7 +416,6 @@ void ClearConsole()
void ChangeWindowsSpecificPointers(InspIRCd* Instance)
{
Instance->Logs->Log("win32",DEBUG,"Changing to windows specific pointer and functor set");
- Instance->Config->DNSServerValidator = &ValidateWindowsDnsServer;
}
DWORD WindowsForkStart(InspIRCd* Instance)
@@ -518,7 +517,7 @@ void WindowsForkKillOwner(InspIRCd * Instance)
CloseHandle(hProcess);
}
-bool ValidateWindowsDnsServer(ServerConfig* conf, const char* tag, const char* value, ValueItem &data)
+bool ValidateDnsServer(ServerConfig* conf, const char* tag, const char* value, ValueItem &data)
{
if (!*(data.GetString()))
{