# quitmsg="Throttled" bootwait="10">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
- # Custom prefixes: allows for channel prefixes to be added.
+ # Custom prefixes: allows for channel prefixes to be added.
-# This replaces m_chanprotect and m_halfop.
#<module name="m_customprefix.so">
#
# name The name of the mode, must be unique from other modes
# specify below the path to the helpop.conf file, or if you like to #
# make a mess, define your helpop tags in this conf. #
# #
-#<include file="conf/examples/inspircd.helpop-full.example">
+#<include file="examples/inspircd.helpop-full.example">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
- # HIDECHANS module: Allows opers to hide their channels list from non-
+ # HIDECHANS module: Allows users to hide their channels list from non-
# opers by setting user mode +I on themselves.
#<module name="m_hidechans.so">
#
user->WriteNumeric(379, "%s %s :was connecting from *@%s",
user->nick.c_str(), parameters[0].c_str(), u->host.c_str());
- if (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"))
- user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(),parameters[0].c_str(), ServerInstance->Config->HideWhoisServer.c_str(), signon.c_str());
- else
- user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(),parameters[0].c_str(), u->server.c_str(), signon.c_str());
+ std::string signon = ServerInstance->TimeString(u->signon);
- user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(), parameters[0].c_str(), (hide_server ? ServerInstance->Config->HideWhoisServer.c_str() : u->server.c_str()), b);
+ bool hide_server = (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"));
++ user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(), parameters[0].c_str(), (hide_server ? ServerInstance->Config->HideWhoisServer.c_str() : u->server.c_str()), signon.c_str());
}
}
else
std::string InspIRCd::TimeString(time_t curtime)
{
- return std::string(ctime(&curtime),24);
+ #ifdef _WIN32
+ if (curtime < 0)
+ curtime = 0;
+ #endif
+
+ struct tm* timeinfo = localtime(&curtime);
+ if (!timeinfo)
+ {
+ curtime = 0;
+ timeinfo = localtime(&curtime);
+ }
+
+ // If the calculated year exceeds four digits or is less than the year 1000,
+ // the behavior of asctime() is undefined
+ if (timeinfo->tm_year + 1900 > 9999)
+ timeinfo->tm_year = 9999 - 1900;
+ else if (timeinfo->tm_year + 1900 < 1000)
+ timeinfo->tm_year = 0;
+
+ return std::string(asctime(timeinfo),24);
}
-// You should only pass a single character to this.
-void InspIRCd::AddExtBanChar(char c)
-{
- std::string &tok = Config->data005;
- std::string::size_type ebpos = tok.find(" EXTBAN=,");
-
- if (ebpos == std::string::npos)
- {
- tok.append(" EXTBAN=,");
- tok.push_back(c);
- }
- else
- {
- ebpos += 9;
- while (isalpha(tok[ebpos]) && tok[ebpos] < c)
- ebpos++;
- tok.insert(ebpos, 1, c);
- }
-}
-
std::string InspIRCd::GenRandomStr(int length, bool printable)
{
char* buf = new char[length];
# pragma comment(lib, "gdi32.lib")
#endif
-/* $ModDesc: Provides SSL support for clients */
-/* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") exec("libgcrypt-config --cflags") */
+/* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") exec("libgcrypt-config --cflags") -Wno-pedantic */
/* $LinkerFlags: rpath("pkg-config --libs gnutls") pkgconflibs("gnutls","/libgnutls.so","-lgnutls") exec("libgcrypt-config --libs") */
-/* $NoPedantic */
+ #ifndef GNUTLS_VERSION_MAJOR
+ #define GNUTLS_VERSION_MAJOR LIBGNUTLS_VERSION_MAJOR
+ #define GNUTLS_VERSION_MINOR LIBGNUTLS_VERSION_MINOR
+ #define GNUTLS_VERSION_PATCH LIBGNUTLS_VERSION_PATCH
+ #endif
+
// These don't exist in older GnuTLS versions
- #if ((GNUTLS_VERSION_MAJOR > 2) || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR > 1) || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR == 1 && GNUTLS_VERSION_MICRO >= 7))
+ #if ((GNUTLS_VERSION_MAJOR > 2) || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR > 1) || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR == 1 && GNUTLS_VERSION_PATCH >= 7))
#define GNUTLS_NEW_PRIO_API
#endif
issl_session() : socket(NULL), sess(NULL) {}
};
-class CommandStartTLS : public SplitCommand
+class GnuTLSIOHook : public SSLIOHook
{
- public:
- bool enabled;
- CommandStartTLS (Module* mod) : SplitCommand(mod, "STARTTLS")
+ private:
+ void InitSession(StreamSocket* user, bool me_server)
{
- enabled = true;
- works_before_reg = true;
+ issl_session* session = &sessions[user->GetFd()];
+
+ gnutls_init(&session->sess, me_server ? GNUTLS_SERVER : GNUTLS_CLIENT);
+ session->socket = user;
+
+ #ifdef GNUTLS_NEW_PRIO_API
+ gnutls_priority_set(session->sess, priority);
++ #else
++ gnutls_set_default_priority(session->sess);
+ #endif
+ gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred);
+ gnutls_dh_set_prime_bits(session->sess, dh_bits);
+ gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(session));
+ gnutls_transport_set_push_function(session->sess, gnutls_push_wrapper);
+ gnutls_transport_set_pull_function(session->sess, gnutls_pull_wrapper);
+
+ if (me_server)
+ gnutls_certificate_server_set_request(session->sess, GNUTLS_CERT_REQUEST); // Request client certificate if any.
+
+ Handshake(session, user);
}
- CmdResult HandleLocal(const std::vector<std::string> ¶meters, LocalUser *user)
+ void CloseSession(issl_session* session)
{
- if (!enabled)
+ if (session->sess)
{
- user->WriteNumeric(691, "%s :STARTTLS is not enabled", user->nick.c_str());
- return CMD_FAILURE;
+ gnutls_bye(session->sess, GNUTLS_SHUT_WR);
+ gnutls_deinit(session->sess);
}
+ session->socket = NULL;
+ session->sess = NULL;
+ session->cert = NULL;
+ session->status = ISSL_NONE;
+ }
- if (user->registered == REG_ALL)
- {
- user->WriteNumeric(691, "%s :STARTTLS is not permitted after client registration is complete", user->nick.c_str());
- }
- else
+ bool Handshake(issl_session* session, StreamSocket* user)
+ {
+ int ret = gnutls_handshake(session->sess);
+
+ if (ret < 0)
{
- if (!user->eh.GetIOHook())
+ if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
{
- user->WriteNumeric(670, "%s :STARTTLS successful, go ahead with TLS handshake", user->nick.c_str());
- /* We need to flush the write buffer prior to adding the IOHook,
- * otherwise we'll be sending this line inside the SSL session - which
- * won't start its handshake until the client gets this line. Currently,
- * we assume the write will not block here; this is usually safe, as
- * STARTTLS is sent very early on in the registration phase, where the
- * user hasn't built up much sendq. Handling a blocked write here would
- * be very annoying.
- */
- user->eh.DoWrite();
- user->eh.AddIOHook(creator);
- creator->OnStreamSocketAccept(&user->eh, NULL, NULL);
+ // Handshake needs resuming later, read() or write() would have blocked.
+
+ if(gnutls_record_get_direction(session->sess) == 0)
+ {
+ // gnutls_handshake() wants to read() again.
+ session->status = ISSL_HANDSHAKING_READ;
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
+ }
+ else
+ {
+ // gnutls_handshake() wants to write() again.
+ session->status = ISSL_HANDSHAKING_WRITE;
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE);
+ }
}
else
- user->WriteNumeric(691, "%s :STARTTLS failure", user->nick.c_str());
+ {
+ user->SetError("Handshake Failed - " + std::string(gnutls_strerror(ret)));
+ CloseSession(session);
+ session->status = ISSL_CLOSING;
+ }
+
+ return false;
}
+ else
+ {
+ // Change the seesion state
+ session->status = ISSL_HANDSHAKEN;
- return CMD_FAILURE;
+ VerifyCertificate(session,user);
+
+ // Finish writing, if any left
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE);
+
+ return true;
+ }
}
-};
-class ModuleSSLGnuTLS : public Module
-{
- issl_session* sessions;
+ void VerifyCertificate(issl_session* session, StreamSocket* user)
+ {
+ if (!session->sess || !user)
+ return;
- gnutls_certificate_credentials_t x509_cred;
- gnutls_dh_params_t dh_params;
- gnutls_digest_algorithm_t hash;
- #ifdef GNUTLS_NEW_PRIO_API
- gnutls_priority_t priority;
- #endif
+ unsigned int status;
+ const gnutls_datum_t* cert_list;
+ int ret;
+ unsigned int cert_list_size;
+ gnutls_x509_crt_t cert;
+ char str[512];
+ unsigned char digest[512];
+ size_t digest_size = sizeof(digest);
+ size_t name_size = sizeof(str);
+ ssl_cert* certinfo = new ssl_cert;
+ session->cert = certinfo;
- std::string sslports;
- int dh_bits;
+ /* This verification function uses the trusted CAs in the credentials
+ * structure. So you must have installed one or more CA certificates.
+ */
+ ret = gnutls_certificate_verify_peers2(session->sess, &status);
- bool cred_alloc;
- bool dh_alloc;
+ if (ret < 0)
+ {
+ certinfo->error = std::string(gnutls_strerror(ret));
+ return;
+ }
- RandGen randhandler;
- CommandStartTLS starttls;
+ certinfo->invalid = (status & GNUTLS_CERT_INVALID);
+ certinfo->unknownsigner = (status & GNUTLS_CERT_SIGNER_NOT_FOUND);
+ certinfo->revoked = (status & GNUTLS_CERT_REVOKED);
+ certinfo->trusted = !(status & GNUTLS_CERT_SIGNER_NOT_CA);
- GenericCap capHandler;
- ServiceProvider iohook;
+ /* Up to here the process is the same for X.509 certificates and
+ * OpenPGP keys. From now on X.509 certificates are assumed. This can
+ * be easily extended to work with openpgp keys as well.
+ */
+ if (gnutls_certificate_type_get(session->sess) != GNUTLS_CRT_X509)
+ {
+ certinfo->error = "No X509 keys sent";
+ return;
+ }
+
+ ret = gnutls_x509_crt_init(&cert);
+ if (ret < 0)
+ {
+ certinfo->error = gnutls_strerror(ret);
+ return;
+ }
+
+ cert_list_size = 0;
+ cert_list = gnutls_certificate_get_peers(session->sess, &cert_list_size);
+ if (cert_list == NULL)
+ {
+ certinfo->error = "No certificate was found";
+ goto info_done_dealloc;
+ }
+
+ /* This is not a real world example, since we only check the first
+ * certificate in the given chain.
+ */
+
+ ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
+ if (ret < 0)
+ {
+ certinfo->error = gnutls_strerror(ret);
+ goto info_done_dealloc;
+ }
+
+ gnutls_x509_crt_get_dn(cert, str, &name_size);
+ certinfo->dn = str;
+
+ gnutls_x509_crt_get_issuer_dn(cert, str, &name_size);
+ certinfo->issuer = str;
+
+ if ((ret = gnutls_x509_crt_get_fingerprint(cert, hash, digest, &digest_size)) < 0)
+ {
+ certinfo->error = gnutls_strerror(ret);
+ }
+ else
+ {
+ certinfo->fingerprint = BinToHex(digest, digest_size);
+ }
+
+ /* Beware here we do not check for errors.
+ */
+ if ((gnutls_x509_crt_get_expiration_time(cert) < ServerInstance->Time()) || (gnutls_x509_crt_get_activation_time(cert) > ServerInstance->Time()))
+ {
+ certinfo->error = "Not activated, or expired certificate";
+ }
+
+info_done_dealloc:
+ gnutls_x509_crt_deinit(cert);
+ }
- inline static const char* UnknownIfNULL(const char* str)
+ static const char* UnknownIfNULL(const char* str)
{
return str ? str : "UNKNOWN";
}
return 1;
}
-class ModuleSSLOpenSSL : public Module
+class OpenSSLIOHook : public SSLIOHook
{
- issl_session* sessions;
-
- SSL_CTX* ctx;
- SSL_CTX* clictx;
-
- std::string sslports;
- bool use_sha;
-
- ServiceProvider iohook;
- public:
-
- ModuleSSLOpenSSL() : iohook(this, "ssl/openssl", SERVICE_IOHOOK)
+ private:
+ bool Handshake(StreamSocket* user, issl_session* session)
{
- sessions = new issl_session[ServerInstance->SE->GetMaxFds()];
+ int ret;
- /* Global SSL library initialization*/
- SSL_library_init();
- SSL_load_error_strings();
+ if (session->outbound)
+ ret = SSL_connect(session->sess);
+ else
+ ret = SSL_accept(session->sess);
- /* Build our SSL contexts:
- * NOTE: OpenSSL makes us have two contexts, one for servers and one for clients. ICK.
- */
- ctx = SSL_CTX_new( SSLv23_server_method() );
- clictx = SSL_CTX_new( SSLv23_client_method() );
+ if (ret < 0)
+ {
+ int err = SSL_get_error(session->sess, ret);
- SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
- SSL_CTX_set_mode(clictx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+ if (err == SSL_ERROR_WANT_READ)
+ {
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
+ session->status = ISSL_HANDSHAKING;
+ return true;
+ }
+ else if (err == SSL_ERROR_WANT_WRITE)
+ {
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE);
+ session->status = ISSL_HANDSHAKING;
+ return true;
+ }
+ else
+ {
+ CloseSession(session);
+ }
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
- SSL_CTX_set_verify(clictx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
- }
+ return false;
+ }
+ else if (ret > 0)
+ {
+ // Handshake complete.
+ VerifyCertificate(session, user);
- void init()
- {
- // Needs the flag as it ignores a plain /rehash
- OnModuleRehash(NULL,"ssl");
- Implementation eventlist[] = { I_On005Numeric, I_OnRehash, I_OnModuleRehash, I_OnHookIO, I_OnUserConnect };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
- ServerInstance->Modules->AddService(iohook);
- }
+ session->status = ISSL_OPEN;
- void OnHookIO(StreamSocket* user, ListenSocket* lsb)
- {
- if (!user->GetIOHook() && lsb->bind_tag->getString("ssl") == "openssl")
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE);
+
+ return true;
+ }
+ else if (ret == 0)
{
- /* Hook the user with our module */
- user->AddIOHook(this);
+ CloseSession(session);
+ return true;
}
+
+ return true;
}
- void OnRehash(User* user)
+ void CloseSession(issl_session* session)
{
- sslports.clear();
-
- ConfigTag* Conf = ServerInstance->Config->ConfValue("openssl");
-
- if (Conf->getBool("showports", true))
+ if (session->sess)
{
- sslports = Conf->getString("advertisedports");
- if (!sslports.empty())
- return;
-
- for (size_t i = 0; i < ServerInstance->ports.size(); i++)
- {
- ListenSocket* port = ServerInstance->ports[i];
- if (port->bind_tag->getString("ssl") != "openssl")
- continue;
-
- const std::string& portid = port->bind_desc;
- ServerInstance->Logs->Log("m_ssl_openssl", DEFAULT, "m_ssl_openssl.so: Enabling SSL for port %s", portid.c_str());
-
- if (port->bind_tag->getString("type", "clients") == "clients" && port->bind_addr != "127.0.0.1")
- {
- /*
- * Found an SSL port for clients that is not bound to 127.0.0.1 and handled by us, display
- * the IP:port in ISUPPORT.
- *
- * We used to advertise all ports seperated by a ';' char that matched the above criteria,
- * but this resulted in too long ISUPPORT lines if there were lots of ports to be displayed.
- * To solve this by default we now only display the first IP:port found and let the user
- * configure the exact value for the 005 token, if necessary.
- */
- sslports = portid;
- break;
- }
- }
+ SSL_shutdown(session->sess);
+ SSL_free(session->sess);
}
+
+ session->sess = NULL;
+ session->status = ISSL_NONE;
+ errno = EIO;
}
- void OnModuleRehash(User* user, const std::string ¶m)
+ void VerifyCertificate(issl_session* session, StreamSocket* user)
{
- if (param != "ssl")
+ if (!session->sess || !user)
return;
- std::string keyfile;
- std::string certfile;
- std::string cafile;
- std::string dhfile;
- OnRehash(user);
-
- ConfigTag* conf = ServerInstance->Config->ConfValue("openssl");
-
- cafile = conf->getString("cafile", CONFIG_PATH "/ca.pem");
- certfile = conf->getString("certfile", CONFIG_PATH "/cert.pem");
- keyfile = conf->getString("keyfile", CONFIG_PATH "/key.pem");
- dhfile = conf->getString("dhfile", CONFIG_PATH "/dhparams.pem");
- std::string hash = conf->getString("hash", "md5");
- if (hash != "sha1" && hash != "md5")
- throw ModuleException("Unknown hash type " + hash);
- use_sha = (hash == "sha1");
+ X509* cert;
+ ssl_cert* certinfo = new ssl_cert;
+ session->cert = certinfo;
+ unsigned int n;
+ unsigned char md[EVP_MAX_MD_SIZE];
- std::string ciphers = conf->getString("ciphers", "");
+ cert = SSL_get_peer_certificate((SSL*)session->sess);
- if (!ciphers.empty())
+ if (!cert)
{
- if ((!SSL_CTX_set_cipher_list(ctx, ciphers.c_str())) || (!SSL_CTX_set_cipher_list(clictx, ciphers.c_str())))
- {
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't set cipher list to %s.", ciphers.c_str());
- ERR_print_errors_cb(error_callback, this);
- }
+ certinfo->error = "Could not get peer certificate: "+std::string(get_error());
+ return;
}
- /* Load our keys and certificates
- * NOTE: OpenSSL's error logging API sucks, don't blame us for this clusterfuck.
- */
- if ((!SSL_CTX_use_certificate_chain_file(ctx, certfile.c_str())) || (!SSL_CTX_use_certificate_chain_file(clictx, certfile.c_str())))
- {
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read certificate file %s. %s", certfile.c_str(), strerror(errno));
- ERR_print_errors_cb(error_callback, this);
- }
+ certinfo->invalid = (SSL_get_verify_result(session->sess) != X509_V_OK);
- if (SelfSigned)
- if (((!SSL_CTX_use_PrivateKey_file(ctx, keyfile.c_str(), SSL_FILETYPE_PEM))) || (!SSL_CTX_use_PrivateKey_file(clictx, keyfile.c_str(), SSL_FILETYPE_PEM)))
++ if (!SelfSigned)
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read key file %s. %s", keyfile.c_str(), strerror(errno));
- ERR_print_errors_cb(error_callback, this);
+ certinfo->unknownsigner = false;
+ certinfo->trusted = true;
}
-
- /* Load the CAs we trust*/
- if (((!SSL_CTX_load_verify_locations(ctx, cafile.c_str(), 0))) || (!SSL_CTX_load_verify_locations(clictx, cafile.c_str(), 0)))
+ else
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read CA list from %s. This is only a problem if you want to verify client certificates, otherwise it's safe to ignore this message. Error: %s", cafile.c_str(), strerror(errno));
- ERR_print_errors_cb(error_callback, this);
+ certinfo->unknownsigner = true;
+ certinfo->trusted = false;
}
- FILE* dhpfile = fopen(dhfile.c_str(), "r");
- DH* ret;
+ certinfo->dn = X509_NAME_oneline(X509_get_subject_name(cert),0,0);
+ certinfo->issuer = X509_NAME_oneline(X509_get_issuer_name(cert),0,0);
- if (dhpfile == NULL)
+ if (!X509_digest(cert, digest, md, &n))
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so Couldn't open DH file %s: %s", dhfile.c_str(), strerror(errno));
- throw ModuleException("Couldn't open DH file " + dhfile + ": " + strerror(errno));
+ certinfo->error = "Out of memory generating fingerprint";
}
else
{
#include "inspircd.h"
#include "xline.h"
-
-/* $ModDesc: Provides handling of DNS blacklists */
+#include "modules/dns.h"
/* Class holding data for a single entry */
- class DNSBLConfEntry
+ class DNSBLConfEntry : public refcountbase
{
public:
enum EnumBanaction { I_UNKNOWN, I_KILL, I_ZLINE, I_KLINE, I_GLINE, I_MARK };
public:
- DNSBLResolver(DNS::Manager *mgr, Module *me, LocalStringExt& match, LocalIntExt& ctr, const std::string &hostname, LocalUser* u, DNSBLConfEntry *conf)
- DNSBLResolver(Module *me, LocalStringExt& match, LocalIntExt& ctr, const std::string &hostname, LocalUser* u, reference<DNSBLConfEntry> conf, bool &cached)
- : Resolver(hostname, DNS_QUERY_A, cached, me), theiruid(u->uuid), nameExt(match), countExt(ctr), ConfEntry(conf)
++ DNSBLResolver(DNS::Manager *mgr, Module *me, LocalStringExt& match, LocalIntExt& ctr, const std::string &hostname, LocalUser* u, reference<DNSBLConfEntry> conf)
+ : DNS::Request(mgr, me, hostname, DNS::QUERY_A, true), theiruid(u->uuid), nameExt(match), countExt(ctr), ConfEntry(conf)
{
}
class ModuleDNSBL : public Module
{
- std::vector<DNSBLConfEntry *> DNSBLConfEntries;
+ std::vector<reference<DNSBLConfEntry> > DNSBLConfEntries;
+ dynamic_reference<DNS::Manager> DNS;
LocalStringExt nameExt;
LocalIntExt countExt;
ReadConf();
ServerInstance->Modules->AddService(nameExt);
ServerInstance->Modules->AddService(countExt);
- Implementation eventlist[] = { I_OnRehash, I_OnSetUserIP, I_OnStats, I_OnSetConnectClass, I_OnCheckReady };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ~ModuleDNSBL()
- {
- ClearEntries();
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides handling of DNS blacklists", VF_VENDOR);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
- Implementation eventlist[] = { I_OnUserJoin, I_OnPostJoin, I_OnSetAway, I_OnEvent, I_OnRehash };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* conf = ServerInstance->Config->ConfValue("ircv3");
- accountnotify = conf->getBool("accoutnotify", true);
- accountnotify = conf->getBool("accountnotify", conf->getBool("accoutnotify", true));
++ accountnotify = conf->getBool("accountnotify", true);
awaynotify = conf->getBool("awaynotify", true);
extendedjoin = conf->getBool("extendedjoin", true);
}
#include "inspircd.h"
++#include "listmode.h"
+#include <fstream>
-/* $ModDesc: Provides support for channel mode +P to provide permanent channels */
-// Not in a class due to circular dependancy hell.
-static std::string permchannelsconf;
-static bool WriteDatabase(Module* mod, bool save_listmodes)
+ struct ListModeData
+ {
+ std::string modes;
+ std::string params;
+ };
+
+/** Handles the +P channel mode
+ */
+class PermChannel : public ModeHandler
{
- FILE *f;
-
- if (permchannelsconf.empty())
+ public:
+ PermChannel(Module* Creator)
+ : ModeHandler(Creator, "permanent", 'P', PARAM_NONE, MODETYPE_CHANNEL)
{
- // Fake success.
- return true;
+ oper = true;
}
- std::string tempname = permchannelsconf + ".tmp";
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding)
+ {
+ if (adding == channel->IsModeSet(this))
+ return MODEACTION_DENY;
+
+ channel->SetMode(this, adding);
+ if (!adding)
+ channel->CheckDestroy();
+
+ return MODEACTION_ALLOW;
+ }
+};
- static bool WriteDatabase(PermChannel& permchanmode)
+// Not in a class due to circular dependancy hell.
+static std::string permchannelsconf;
++static bool WriteDatabase(PermChannel& permchanmode, Module* mod, bool save_listmodes)
+{
++ ChanModeReference ban(mod, "ban");
/*
* We need to perform an atomic write so as not to fuck things up.
- * So, let's write to a temporary file, flush and sync the FD, then rename the file..
- * -- w00t
+ * So, let's write to a temporary file, flush it, then rename the file..
+ * -- w00t
*/
- f = fopen(tempname.c_str(), "w");
- if (!f)
+
+ // If the user has not specified a configuration file then we don't write one.
+ if (permchannelsconf.empty())
+ return true;
+
+ std::string permchannelsnewconf = permchannelsconf + ".tmp";
+ std::ofstream stream(permchannelsnewconf.c_str());
+ if (!stream.is_open())
{
- ServerInstance->Logs->Log("m_permchannels",DEFAULT, "permchannels: Cannot create database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Cannot create database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot create new db: %s (%d)", strerror(errno), errno);
return false;
}
for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
{
Channel* chan = i->second;
- if (!chan->IsModeSet('P'))
+ if (!chan->IsModeSet(permchanmode))
continue;
- lm.modes = std::string(chan->bans.size(), 'b');
- for (BanList::const_iterator j = chan->bans.begin(); j != chan->bans.end(); ++j)
- {
- lm.params += j->data;
- lm.params += ' ';
- }
+ std::string chanmodes = chan->ChanModes(true);
+ if (save_listmodes)
+ {
+ ListModeData lm;
+
+ // Bans are managed by the core, so we have to process them separately
- FOREACH_MOD(I_OnSyncChannel, OnSyncChannel(chan, mod, &lm));
++ static_cast<ListModeBase*>(*ban)->DoSyncChannel(chan, mod, &lm);
+
+ // All other listmodes are managed by modules, so we need to ask them (call their
+ // OnSyncChannel() handler) to give our ProtoSendMode() a list of modes that are
+ // set on the channel. The ListModeData struct is passed as an opaque pointer
+ // that will be passed back to us by the module handling the mode.
- std::string chants = ConvToStr(chan->age);
- std::string topicts = ConvToStr(chan->topicset);
- const char* items[] =
- {
- "<permchannels channel=",
- chan->name.c_str(),
- " ts=",
- chants.c_str(),
- " topic=",
- chan->topic.c_str(),
- " topicts=",
- topicts.c_str(),
- " topicsetby=",
- chan->setby.c_str(),
- " modes=",
- chanmodes.c_str(),
- ">\n"
- };
-
- line.clear();
- int item = 0, ipos = 0;
- while (item < 13)
- {
- char c = items[item][ipos++];
- if (c == 0)
- {
- // end of this string; hop to next string, insert a quote
- item++;
- ipos = 0;
- c = '"';
- }
- else if (c == '\\' || c == '"')
- {
- line += '\\';
- }
- line += c;
- }
-
- // Erase last '"'
- line.erase(line.end()-1);
- fputs(line.c_str(), f);
++ FOREACH_MOD(OnSyncChannel, (chan, mod, &lm));
+
+ if (!lm.modes.empty())
+ {
+ // Remove the last space
+ lm.params.erase(lm.params.end()-1);
+
+ // If there is at least a space in chanmodes (that is, a non-listmode has a parameter)
+ // insert the listmode mode letters before the space. Otherwise just append them.
+ std::string::size_type p = chanmodes.find(' ');
+ if (p == std::string::npos)
+ chanmodes += lm.modes;
+ else
+ chanmodes.insert(p, lm.modes);
+
+ // Append the listmode parameters (the masks themselves)
+ chanmodes += ' ';
+ chanmodes += lm.params;
+ }
+ }
+
- << "\" modes=\"" << ServerConfig::Escape(chan->ChanModes(true))
+ stream << "<permchannels channel=\"" << ServerConfig::Escape(chan->name)
++ << "\" ts=\"" << chan->age
+ << "\" topic=\"" << ServerConfig::Escape(chan->topic)
++ << "\" topicts=\"" << chan->topicset
++ << "\" topicsetby=\"" << ServerConfig::Escape(chan->setby)
++ << "\" modes=\"" << ServerConfig::Escape(chanmodes)
+ << "\">" << std::endl;
}
- int write_error = 0;
- write_error = ferror(f);
- write_error |= fclose(f);
- if (write_error)
+ if (stream.fail())
{
- ServerInstance->Logs->Log("m_permchannels",DEFAULT, "permchannels: Cannot write to new database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Cannot write to new database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot write to new db: %s (%d)", strerror(errno), errno);
return false;
}
return Module::cull();
}
- virtual void OnRehash(User *user)
+ void OnRehash(User *user) CXX11_OVERRIDE
{
- permchannelsconf = ServerInstance->Config->ConfValue("permchanneldb")->getString("filename");
+ ConfigTag* tag = ServerInstance->Config->ConfValue("permchanneldb");
+ permchannelsconf = tag->getString("filename");
+ save_listmodes = tag->getBool("listmodes");
}
void LoadDatabase()
{
ConfigTag* tag = i->second;
std::string channel = tag->getString("channel");
-- std::string topic = tag->getString("topic");
std::string modes = tag->getString("modes");
- if (channel.empty())
+ if ((channel.empty()) || (channel.length() > ServerInstance->Config->Limits.ChanMax))
{
- ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Malformed permchannels tag with empty channel name.");
- ServerInstance->Logs->Log("m_permchannels", DEFAULT, "Ignoring permchannels tag with empty or too long channel name (\"" + channel + "\")");
++ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Ignoring permchannels tag with empty or too long channel name (\"" + channel + "\")");
continue;
}
if (!c)
{
- c = new Channel(channel, ServerInstance->Time());
- if (!topic.empty())
- time_t TS = tag->getInt("ts");
- c = new Channel(channel, ((TS > 0) ? TS : ServerInstance->Time()));
++ time_t TS = tag->getInt("ts", ServerInstance->Time(), 1);
++ c = new Channel(channel, TS);
+
- c->SetTopic(NULL, topic, true);
- c->setby = tag->getString("topicsetby");
- if (c->setby.empty())
- c->setby = ServerInstance->Config->ServerName;
+ unsigned int topicset = tag->getInt("topicts");
- // SetTopic() sets the topic TS to now, if there was no topicts saved then don't overwrite that with a 0
- if (topicset > 0)
++ c->topic = tag->getString("topic");
++
++ if ((topicset != 0) || (!c->topic.empty()))
+ {
- c->SetTopic(ServerInstance->FakeClient, topic);
-
- /*
- * Due to the way protocol works in 1.2, we need to hack the topic TS in such a way that this
- * topic will always win over others.
- *
- * This is scheduled for (proper) fixing in a later release, and can be removed at a later date.
- */
- c->topicset = 42;
++ if (topicset == 0)
++ topicset = ServerInstance->Time();
+ c->topicset = topicset;
++ c->setby = tag->getString("topicsetby");
++ if (c->setby.empty())
++ c->setby = ServerInstance->Config->ServerName;
+ }
- ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Added %s with topic %s", channel.c_str(), topic.c_str());
+
- ServerInstance->Logs->Log("m_permchannels", DEBUG, "Added %s with topic %s", channel.c_str(), topic.c_str());
++ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Added %s with topic %s", channel.c_str(), c->topic.c_str());
if (modes.empty())
continue;
dirty = true;
}
- void OnBackgroundTimer(time_t)
+ void OnBackgroundTimer(time_t) CXX11_OVERRIDE
{
if (dirty)
- WriteDatabase(p);
- WriteDatabase(this, save_listmodes);
++ WriteDatabase(p, this, save_listmodes);
dirty = false;
}
}
}
- virtual Version GetVersion()
+ void ProtoSendMode(void* opaque, TargetTypeFlags type, void* target, const std::vector<std::string>& modes, const std::vector<TranslateType>& translate)
+ {
+ // We never pass an empty modelist but better be sure
+ if (modes.empty())
+ return;
+
+ ListModeData* lm = static_cast<ListModeData*>(opaque);
+
+ // Append the mode letters without the trailing '+' (for example "IIII", "gg")
+ lm->modes.append(modes[0].begin()+1, modes[0].end());
+
+ // Append the parameters
+ for (std::vector<std::string>::const_iterator i = modes.begin()+1; i != modes.end(); ++i)
+ {
+ lm->params += *i;
+ lm->params += ' ';
+ }
+ }
+
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for channel mode +P to provide permanent channels",VF_VENDOR);
}
else
{
time_t ourTS = chan->age;
-
if (TS != ourTS)
+ {
ServerInstance->SNO->WriteToSnoMask('d', "Merge FJOIN received for %s, ourTS: %lu, TS: %lu, difference: %lu",
chan->name.c_str(), (unsigned long)ourTS, (unsigned long)TS, (unsigned long)(ourTS - TS));
- /* If our TS is less than theirs, we dont accept their modes */
- if (ourTS < TS)
- {
- ServerInstance->SNO->WriteToSnoMask('d', "NOT Applying modes from other side");
- apply_other_sides_modes = false;
- }
- else if (ourTS > TS)
- {
- /* Our TS greater than theirs, clear all our modes from the channel, accept theirs. */
- ServerInstance->SNO->WriteToSnoMask('d', "Removing our modes, accepting remote");
- parameterlist param_list;
- if (Utils->AnnounceTSChange)
- chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :TS for %s changed from %lu to %lu", chan->name.c_str(), channel.c_str(), (unsigned long) ourTS, (unsigned long) TS);
- // while the name is equal in case-insensitive compare, it might differ in case; use the remote version
- chan->name = channel;
- chan->age = TS;
- chan->ClearInvites();
- param_list.push_back(channel);
- this->RemoveStatus(ServerInstance->FakeClient, param_list);
-
- // XXX: If the channel does not exist in the chan hash at this point, create it so the remote modes can be applied on it.
- // This happens to 0-user permanent channels on the losing side, because those are removed (from the chan hash, then
- // deleted later) as soon as the permchan mode is removed from them.
- if (ServerInstance->FindChan(channel) == NULL)
+ /* If our TS is less than theirs, we dont accept their modes */
+ if (ourTS < TS)
{
- chan = new Channel(channel, TS);
+ apply_other_sides_modes = false;
+ }
+ else if (ourTS > TS)
+ {
+ /* Our TS greater than theirs, clear all our modes from the channel, accept theirs. */
+ if (Utils->AnnounceTSChange)
+ chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :TS for %s changed from %lu to %lu", chan->name.c_str(), channel.c_str(), (unsigned long) ourTS, (unsigned long) TS);
+
+ // while the name is equal in case-insensitive compare, it might differ in case; use the remote version
+ chan->name = channel;
+ chan->age = TS;
+ chan->ClearInvites();
+
+ CommandFJoin::RemoveStatus(chan);
+
+ // XXX: If the channel does not exist in the chan hash at this point, create it so the remote modes can be applied on it.
+ // This happens to 0-user permanent channels on the losing side, because those are removed (from the chan hash, then
+ // deleted later) as soon as the permchan mode is removed from them.
+ if (ServerInstance->FindChan(channel) == NULL)
+ {
+ chan = new Channel(channel, TS);
+ }
}
}
- // The silent case here is ourTS == TS, we don't need to remove modes here, just to merge them later on.
}
- /* First up, apply their modes if they won the TS war */
+ /* First up, apply their channel modes if they won the TS war */
if (apply_other_sides_modes)
{
+ // Need to use a modestacker here due to maxmodes
+ irc::modestacker stack(true);
+ std::vector<std::string>::const_iterator paramit = params.begin() + 3;
+ const std::vector<std::string>::const_iterator lastparamit = ((params.size() > 3) ? (params.end() - 1) : params.end());
+ for (std::string::const_iterator i = params[2].begin(); i != params[2].end(); ++i)
+ {
+ ModeHandler* mh = ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL);
+ if (!mh)
+ continue;
+
+ std::string modeparam;
+ if ((paramit != lastparamit) && (mh->GetNumParams(true)))
+ {
+ modeparam = *paramit;
+ ++paramit;
+ }
+
+ stack.Push(*i, modeparam);
+ }
+
std::vector<std::string> modelist;
- modelist.push_back(channel);
- /* Remember, params[params.size() - 1] is userlist, and we don't want to apply *that* */
- modelist.insert(modelist.end(), params.begin()+2, params.end()-1);
- ServerInstance->Modes->Process(modelist, srcuser, ModeParser::MODE_LOCALONLY | ModeParser::MODE_MERGE);
+ // Mode parser needs to know what channel to act on.
+ modelist.push_back(params[0]);
+
+ while (stack.GetStackedLine(modelist))
+ {
- ServerInstance->Modes->Process(modelist, srcuser, true);
++ ServerInstance->Modes->Process(modelist, srcuser, ModeParser::MODE_LOCALONLY | ModeParser::MODE_MERGE);
+ modelist.erase(modelist.begin() + 1, modelist.end());
+ }
-
- ServerInstance->Modes->Process(modelist, srcuser, true);
}
- /* Now, process every 'modes,nick' pair */
+ irc::modestacker modestack(true);
+ TreeSocket* src_socket = Utils->FindServer(srcuser->server)->GetSocket();
+
+ /* Now, process every 'modes,uuid' pair */
+ irc::tokenstream users(*params.rbegin());
+ std::string item;
+ irc::modestacker* modestackptr = (apply_other_sides_modes ? &modestack : NULL);
while (users.GetToken(item))
{
- const char* usr = item.c_str();
- if (usr && *usr)
- {
- const char* unparsedmodes = usr;
- std::string modes;
-
-
- /* Iterate through all modes for this user and check they are valid. */
- while ((*unparsedmodes) && (*unparsedmodes != ','))
- {
- ModeHandler *mh = ServerInstance->Modes->FindMode(*unparsedmodes, MODETYPE_CHANNEL);
- if (!mh)
- {
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Unrecognised mode %c, dropping link", *unparsedmodes);
- return CMD_INVALID;
- }
-
- modes += *unparsedmodes;
- usr++;
- unparsedmodes++;
- }
+ if (!ProcessModeUUIDPair(item, src_socket, chan, modestackptr))
+ return CMD_INVALID;
+ }
- /* Advance past the comma, to the nick */
- usr++;
+ /* Flush mode stacker if we lost the FJOIN or had equal TS */
+ if (apply_other_sides_modes)
+ CommandFJoin::ApplyModeStack(srcuser, chan, modestack);
- /* Check the user actually exists */
- who = ServerInstance->FindUUID(usr);
- if (who)
- {
- /* Check that the user's 'direction' is correct */
- TreeServer* route_back_again = Utils->BestRouteTo(who->server);
- if ((!route_back_again) || (route_back_again->GetSocket() != src_socket))
- continue;
+ return CMD_SUCCESS;
+}
- /* Add any modes this user had to the mode stack */
- for (std::string::iterator x = modes.begin(); x != modes.end(); ++x)
- modestack.Push(*x, who->nick);
+bool CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack)
+{
+ std::string::size_type comma = item.find(',');
- Channel::JoinUser(who, channel.c_str(), true, "", route_back_again->bursting, TS);
- }
- else
- {
- ServerInstance->Logs->Log("m_spanningtree",SPARSE, "Ignored nonexistant user %s in fjoin to %s (probably quit?)", usr, channel.c_str());
- continue;
- }
- }
+ // Comma not required anymore if the user has no modes
+ std::string uuid = ((comma == std::string::npos) ? item : item.substr(comma+1));
+ User* who = ServerInstance->FindUUID(uuid);
+ if (!who)
+ {
+ // Probably KILLed, ignore
+ return true;
}
- /* Flush mode stacker if we lost the FJOIN or had equal TS */
- if (apply_other_sides_modes)
+ /* Check that the user's 'direction' is correct */
+ TreeServer* route_back_again = Utils->BestRouteTo(who->server);
+ if ((!route_back_again) || (route_back_again->GetSocket() != src_socket))
{
- parameterlist stackresult;
- stackresult.push_back(channel);
+ return true;
+ }
- while (modestack.GetStackedLine(stackresult))
+ /* Check if the user received at least one mode */
+ if ((modestack) && (comma > 0) && (comma != std::string::npos))
+ {
+ /* Iterate through the modes and see if they are valid here, if so, apply */
+ std::string::const_iterator commait = item.begin()+comma;
+ for (std::string::const_iterator i = item.begin(); i != commait; ++i)
{
- ServerInstance->SendMode(stackresult, srcuser);
- stackresult.erase(stackresult.begin() + 1, stackresult.end());
+ if (!ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL))
+ {
+ ServerInstance->SNO->WriteToSnoMask('d', "Unrecognised mode '%c' for a user in FJOIN, dropping link", *i);
+ return false;
+ }
+
+ /* Add any modes this user had to the mode stack */
+ modestack->Push(*i, who->nick);
}
}
- return CMD_SUCCESS;
+
+ chan->ForceJoin(who, NULL, route_back_again->bursting);
+ return true;
}
-void CommandFJoin::RemoveStatus(User* srcuser, parameterlist ¶ms)
+void CommandFJoin::RemoveStatus(Channel* c)
{
- if (params.size() < 1)
- return;
-
- Channel* c = ServerInstance->FindChan(params[0]);
+ irc::modestacker stack(false);
- if (c)
+ for (char modeletter = 'A'; modeletter <= 'z'; ++modeletter)
{
- irc::modestacker stack(false);
- parameterlist stackresult;
- stackresult.push_back(c->name);
+ ModeHandler* mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
+
+ /* Passing a pointer to a modestacker here causes the mode to be put onto the mode stack,
+ * rather than applied immediately. Module unloads require this to be done immediately,
+ * for this function we require tidyness instead. Fixes bug #493
+ */
+ if (mh)
+ mh->RemoveMode(c, stack);
+ }
- for (char modeletter = 'A'; modeletter <= 'z'; ++modeletter)
- {
- ModeHandler* mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
+ ApplyModeStack(ServerInstance->FakeClient, c, stack);
+}
- /* Passing a pointer to a modestacker here causes the mode to be put onto the mode stack,
- * rather than applied immediately. Module unloads require this to be done immediately,
- * for this function we require tidyness instead. Fixes bug #493
- */
- if (mh)
- mh->RemoveMode(c, &stack);
- }
+void CommandFJoin::ApplyModeStack(User* srcuser, Channel* c, irc::modestacker& stack)
+{
+ parameterlist stackresult;
+ stackresult.push_back(c->name);
- while (stack.GetStackedLine(stackresult))
- {
- ServerInstance->SendMode(stackresult, srcuser);
- stackresult.erase(stackresult.begin() + 1, stackresult.end());
- }
+ while (stack.GetStackedLine(stackresult))
+ {
+ ServerInstance->Modes->Process(stackresult, srcuser, ModeParser::MODE_LOCALONLY);
+ stackresult.erase(stackresult.begin() + 1, stackresult.end());
}
}
-
sock->Close();
}
}
- if (sock->GetIOHook() == mod)
+
+ for (SpanningTreeUtilities::TimeoutList::const_iterator i = Utils->timeoutlist.begin(); i != Utils->timeoutlist.end(); ++i)
+ {
+ TreeSocket* sock = i->first;
++ if (sock->GetIOHook() && sock->GetIOHook()->creator == mod)
+ sock->Close();
+ }
}
// note: the protocol does not allow direct umode +o except
*/
class SpanningTreeUtilities : public classbase
{
+ CacheRefreshTimer RefreshTimer;
+
public:
+ typedef std::set<TreeSocket*> TreeSocketSet;
+ typedef std::map<TreeSocket*, std::pair<std::string, int> > TimeoutList;
/** Creator module
*/
}
else
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl;
- ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
+ ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
// This is not a maximum, just a hint at the eventual number of sockets that may be polled.
if (EngineHandle == -1)
{
- ServerInstance->Logs->Log("SOCKET",DEFAULT, "ERROR: Could not initialize socket engine: %s", strerror(errno));
- ServerInstance->Logs->Log("SOCKET",DEFAULT, "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now.");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Could not initialize socket engine: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now.");
std::cout << "ERROR: Could not initialize epoll socket engine: " << strerror(errno) << std::endl;
std::cout << "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now." << std::endl;
- ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
+ ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
ref = new EventHandler* [GetMaxFds()];
sysctl(mib, 2, &MAX_DESCRIPTORS, &len, NULL, 0);
if (MAX_DESCRIPTORS <= 0)
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl;
- ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
+ ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
this->RecoverFromFork();
EngineHandle = kqueue();
if (EngineHandle == -1)
{
- ServerInstance->Logs->Log("SOCKET",DEFAULT, "ERROR: Could not initialize socket engine. Your kernel probably does not have the proper features.");
- ServerInstance->Logs->Log("SOCKET",DEFAULT, "ERROR: this is a fatal error, exiting now.");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Could not initialize socket engine. Your kernel probably does not have the proper features.");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: this is a fatal error, exiting now.");
std::cout << "ERROR: Could not initialize socket engine. Your kernel probably does not have the proper features." << std::endl;
std::cout << "ERROR: this is a fatal error, exiting now." << std::endl;
- ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
+ ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
CurrentSetSize = 0;
}
}
else
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets: %s", strerror(errno));
std::cout << "ERROR: Can't determine maximum number of open sockets: " << strerror(errno) << std::endl;
- ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
+ ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
- #endif
ref = new EventHandler* [GetMaxFds()];
events = new struct pollfd[GetMaxFds()];
}
else
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl;
- ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
+ ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
EngineHandle = port_create();
if (EngineHandle == -1)
{
- ServerInstance->Logs->Log("SOCKET",SPARSE,"ERROR: Could not initialize socket engine: %s", strerror(errno));
- ServerInstance->Logs->Log("SOCKET",SPARSE,"ERROR: This is a fatal error, exiting now.");
+ ServerInstance->Logs->Log("SOCKET", LOG_SPARSE, "ERROR: Could not initialize socket engine: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_SPARSE, "ERROR: This is a fatal error, exiting now.");
std::cout << "ERROR: Could not initialize socket engine: " << strerror(errno) << std::endl;
std::cout << "ERROR: This is a fatal error, exiting now." << std::endl;
- ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
+ ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
CurrentSetSize = 0;