diff options
-rw-r--r-- | include/protocol.h | 16 | ||||
-rw-r--r-- | modules/protocol/inspircd.cpp | 35 | ||||
-rw-r--r-- | src/process.cpp | 14 | ||||
-rw-r--r-- | src/protocol.cpp | 5 |
4 files changed, 39 insertions, 31 deletions
diff --git a/include/protocol.h b/include/protocol.h index 612593c89..aeac6a069 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -16,6 +16,17 @@ #include "service.h" #include "modes.h" +/** Thrown when a protocol error happens. */ +class CoreExport ProtocolException final + : public ModuleException +{ +public: + ProtocolException(const Anope::string &message) + : ModuleException(message) + { + } +}; + /* Encapsulates the IRCd protocol we are speaking. */ class CoreExport IRCDProto : public Service @@ -109,6 +120,11 @@ public: virtual Anope::string UID_Retrieve(); virtual Anope::string SID_Retrieve(); + /** Sends an error to the uplink before disconnecting. + * @param reason The error message. + */ + virtual void SendError(const Anope::string &reason); + /** Sets the server in NOOP mode. If NOOP mode is enabled, no users * will be able to oper on the server. * @param s The server diff --git a/modules/protocol/inspircd.cpp b/modules/protocol/inspircd.cpp index 191ea5368..f8b0c35eb 100644 --- a/modules/protocol/inspircd.cpp +++ b/modules/protocol/inspircd.cpp @@ -1139,12 +1139,7 @@ struct IRCDMessageCapab final spanningtree_proto_ver = Anope::Convert<size_t>(params[1], 0); if (spanningtree_proto_ver < 1205) - { - Uplink::Send("ERROR", "Protocol mismatch, no or invalid protocol version given in CAPAB START."); - Anope::QuitReason = "Protocol mismatch, no or invalid protocol version given in CAPAB START"; - Anope::Quitting = true; - return; - } + throw ProtocolException("Protocol mismatch, no or invalid protocol version given in CAPAB START."); Servers::Capab.clear(); IRCD->CanClearBans = false; @@ -1566,39 +1561,19 @@ struct IRCDMessageCapab final if (spanningtree_proto_ver < 1206) { if (!Servers::Capab.count("ACCOUNT") || !Servers::Capab.count("SERVICES")) - { - Uplink::Send("ERROR", "The services_account module is not loaded. This is required by Anope."); - Anope::QuitReason = "ERROR: Remote server does not have the services_account module loaded, and this is required."; - Anope::Quitting = true; - return; - } + throw ProtocolException("The services_account module is not loaded. This is required by Anope."); } else { if (!Servers::Capab.count("ACCOUNT")) - { - Uplink::Send("ERROR", "The account module is not loaded. This is required by Anope."); - Anope::QuitReason = "ERROR: Remote server does not have the account module loaded, and this is required."; - Anope::Quitting = true; - return; - } + throw ProtocolException("The account module is not loaded. This is required by Anope."); if (!Servers::Capab.count("SERVICES")) - { - Uplink::Send("ERROR", "The services module is not loaded. This is required by Anope."); - Anope::QuitReason = "ERROR: Remote server does not have the services module loaded, and this is required."; - Anope::Quitting = true; - return; - } + throw ProtocolException("The services module is not loaded. This is required by Anope."); } if (!ModeManager::FindUserModeByName("PRIV")) - { - Uplink::Send("ERROR", "The hidechans module is not loaded. This is required by Anope."); - Anope::QuitReason = "ERROR: Remote server does not have the hidechans module loaded, and this is required."; - Anope::Quitting = true; - return; - } + throw ProtocolException("The hidechans module is not loaded. This is required by Anope."); if (!IRCD->CanSVSHold) Log() << "The remote server does not have the svshold module; fake users will be used for nick protection until the module is loaded."; diff --git a/src/process.cpp b/src/process.cpp index eea5bcfe6..f045bc970 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -77,7 +77,19 @@ void Anope::Process(const Anope::string &buffer) else if (m->HasFlag(IRCDMessage::FLAG_REQUIRE_SERVER) && !source.empty() && !src.GetServer()) Log(LOG_DEBUG) << "unexpected non-server source " << source << " for " << command; else - m->Run(src, params, tags); + { + try + { + m->Run(src, params, tags); + } + catch (const ProtocolException &err) + { + IRCD->SendError(err.GetReason()); + Anope::QuitReason = "Protocol error: " + err.GetReason(); + Anope::Quitting = true; + Anope::ReturnValue = EXIT_FAILURE; + } + } } bool IRCDProto::Parse(const Anope::string &buffer, Anope::map<Anope::string> &tags, Anope::string &source, Anope::string &command, std::vector<Anope::string> ¶ms) diff --git a/src/protocol.cpp b/src/protocol.cpp index 4893173af..5699a2d48 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -86,6 +86,11 @@ Anope::string IRCDProto::SID_Retrieve() return current_sid; } +void IRCDProto::SendError(const Anope::string &reason) +{ + Uplink::Send("ERROR", reason); +} + void IRCDProto::SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason) { Uplink::Send(source, "KILL", target, reason); |