mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-09 10:39:02 -04:00
Merge branch 'insp3' into master.
This commit is contained in:
commit
7b68936321
@ -1,10 +1,15 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a non-security issue with InspIRCd.
|
||||
---
|
||||
|
||||
<!--
|
||||
---------------------------------------------------
|
||||
GENERAL SUPPORT INFORMATION
|
||||
---------------------------------------------------
|
||||
|
||||
The GitHub issue tracker is for bug reports and feature requests.
|
||||
General support can be found at the following locations:
|
||||
The GitHub issue tracker is for bug reports ONLY. General support can
|
||||
be found at the following locations:
|
||||
|
||||
Docs: https://docs.inspircd.org
|
||||
IRC: irc.inspircd.org #inspircd
|
34
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
Normal file
34
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Request that a new feature is added to InspIRCd.
|
||||
---
|
||||
|
||||
<!--
|
||||
---------------------------------------------------
|
||||
GENERAL SUPPORT INFORMATION
|
||||
---------------------------------------------------
|
||||
|
||||
The GitHub issue tracker is for feature requests ONLY. General support
|
||||
can be found at the following locations:
|
||||
|
||||
Docs: https://docs.inspircd.org
|
||||
IRC: irc.inspircd.org #inspircd
|
||||
|
||||
Example configs:
|
||||
3.0 (stable) - https://github.com/inspircd/inspircd/tree/insp3/docs/conf
|
||||
2.0 (old stable) - https://github.com/inspircd/inspircd/tree/insp20/docs/conf
|
||||
|
||||
-->
|
||||
|
||||
**Description**
|
||||
|
||||
<!--
|
||||
Briefly describe the problem you are having in a few paragraphs.
|
||||
-->
|
||||
|
||||
**Why this would be useful**
|
||||
|
||||
|
||||
<!--
|
||||
Briefly describe why the feature would be useful.
|
||||
-->
|
39
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
39
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
Please fill in the template below. Pull requests that do not use this
|
||||
template will be closed without warning.
|
||||
-->
|
||||
|
||||
## Summary
|
||||
|
||||
<!--
|
||||
Briefly describe what this pull request changes.
|
||||
-->
|
||||
|
||||
## Rationale
|
||||
|
||||
<!--
|
||||
Describe why you have made this change.
|
||||
-->
|
||||
|
||||
## Testing Environment
|
||||
|
||||
<!--
|
||||
Describe the environment in which you have tested this change:
|
||||
-->
|
||||
|
||||
I have tested this pull request on:
|
||||
|
||||
**Operating system name and version:** <!-- e.g. Linux 3.11 -->
|
||||
**Compiler name and version:** <!-- e.g. GCC 4.2.0 -->
|
||||
|
||||
## Checks
|
||||
|
||||
<!--
|
||||
Tick the boxes for the checks you have made.
|
||||
-->
|
||||
|
||||
I have ensured that:
|
||||
|
||||
- [ ] This pull request does not introduce any incompatible API changes.
|
||||
- [ ] If ABI changes have been made I have incremented INSPIRCD_VERSION_API.
|
||||
- [ ] I have documented any features added by this pull request.
|
22
.github/SECURITY.md
vendored
Normal file
22
.github/SECURITY.md
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Currently the v2 (old stable) and v3 (stable) branches are actively receiving security fixes. Support for v2 will end on 2020-06-01.
|
||||
|
||||
The v4 branch is still early in development and only receives security fixes when they are synced from the v3 branch.
|
||||
|
||||
Version | Supported
|
||||
------- | ---------
|
||||
4.x.y | :warning:
|
||||
3.x.y | :white_check_mark:
|
||||
2.0.x | :white_check_mark:
|
||||
1.2.y | :x:
|
||||
1.1.y | :x:
|
||||
1.0.y | :x:
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please do not report security vulnerabilities on GitHub. Instead, get the attention of a developer in our [development IRC channel](https://kiwiirc.com/nextclient/irc.inspircd.org:+6697/#inspircd.dev) at irc.inspircd.org #inspircd.dev and PM them the details.
|
||||
|
||||
We will triage your issue as soon as possible and try to release a fixed version within a week of receiving your report.
|
@ -16,7 +16,7 @@ InspIRCd is supported on on the following platforms:
|
||||
|
||||
Alternate platforms and toolchains may also work but are not officially supported by the InspIRCd team. Generally speaking if you are using a reasonably modern UNIX-like system you should be able to build InspIRCd on it.
|
||||
|
||||
If you encounter any bugs then [please file an issue](https://github.com/inspircd/inspircd/issues/new).
|
||||
If you encounter any bugs then [please file an issue](https://github.com/inspircd/inspircd/issues/new/choose).
|
||||
|
||||
## Installation
|
||||
|
||||
|
1
configure
vendored
1
configure
vendored
@ -323,6 +323,7 @@ if (prompt_bool $interactive, $question, 0) {
|
||||
$config{MANUAL_DIR} = prompt_dir $interactive, 'In what directory are manual pages to be placed?', $config{MANUAL_DIR};
|
||||
$config{MODULE_DIR} = prompt_dir $interactive, 'In what directory are modules to be placed?', $config{MODULE_DIR};
|
||||
$config{SCRIPT_DIR} = prompt_dir $interactive, 'In what directory are scripts to be placed?', $config{SCRIPT_DIR};
|
||||
$config{EXAMPLE_DIR} = $config{CONFIG_DIR} . '/examples';
|
||||
}
|
||||
|
||||
# Configure module settings.
|
||||
|
@ -1000,6 +1000,7 @@ using their cloak when they quit.">
|
||||
nonick Channel mode +N
|
||||
nonotice Channel mode +T
|
||||
regmoderated Channel mode +M
|
||||
repeat Channel mode +E
|
||||
stripcolor Channel mode +S
|
||||
topiclock Channel mode +t
|
||||
|
||||
|
@ -630,7 +630,7 @@
|
||||
# the throttling when the server just booted.
|
||||
#
|
||||
#<connflood period="30" maxconns="3" timeout="30"
|
||||
# quitmsg="Throttled" bootwait="10">
|
||||
# quitmsg="Throttled" bootwait="2m">
|
||||
|
||||
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
|
||||
# Custom prefixes: Allows for channel prefixes to be configured.
|
||||
|
@ -3,7 +3,10 @@
|
||||
# https://www.irccloud.com/networks for more information on supporting
|
||||
# IRCloud on your network.
|
||||
|
||||
<connect name="IRCCloud" parent="main" globalmax="100" localmax="100">
|
||||
<connect name="IRCCloud"
|
||||
parent="main"
|
||||
globalmax="100"
|
||||
localmax="100">
|
||||
|
||||
<connect name="IRCCloud-Brockwell" parent="IRCCloud" allow="192.184.10.118">
|
||||
<connect name="IRCCloud-Charlton" parent="IRCCloud" allow="192.184.9.112">
|
||||
|
@ -1,8 +1,19 @@
|
||||
# This file contains connect classes which are used by KiwiIRC.com users.
|
||||
# See https://kiwiirc.com for more information on KiwiIRC.com.
|
||||
|
||||
<connect name="KiwiIRC.com" parent="main" globalmax="100" localmax="100" registered="no">
|
||||
<connect name="KiwiIRC.com"
|
||||
parent="main"
|
||||
globalmax="100"
|
||||
localmax="100"
|
||||
registered="no"
|
||||
resolvehostnames="no"
|
||||
usednsbl="no"
|
||||
useident="no">
|
||||
|
||||
<connect name="KiwiIRC.com-1" parent="KiwiIRC.com" allow="107.161.19.10">
|
||||
<connect name="KiwiIRC.com-2" parent="KiwiIRC.com" allow="107.161.19.53">
|
||||
<connect name="KiwiIRC.com-1" parent="KiwiIRC.com" allow="107.161.19.53">
|
||||
<connect name="KiwiIRC.com-2" parent="KiwiIRC.com" allow="107.161.19.109">
|
||||
<connect name="KiwiIRC.com-3" parent="KiwiIRC.com" allow="109.169.31.4">
|
||||
|
||||
<exception host="*@107.161.19.53" reason="KiwiIRC.com WebIRC Gateway">
|
||||
<exception host="*@107.161.19.109" reason="KiwiIRC.com WebIRC Gateway">
|
||||
<exception host="*@107.169.31.4" reason="KiwiIRC.com WebIRC Gateway">
|
||||
|
@ -57,7 +57,23 @@ class Events::ModuleEventProvider : public ServiceProvider, private dynamic_refe
|
||||
*/
|
||||
const SubscriberList& GetSubscribers() const { return prov->subscribers; }
|
||||
|
||||
friend class ModuleEventListener;
|
||||
/** Subscribes a listener to this event.
|
||||
* @param subscriber The listener to subscribe.
|
||||
*/
|
||||
void Subscribe(ModuleEventListener* subscriber)
|
||||
{
|
||||
subscribers.insert(subscriber);
|
||||
OnSubscribe(subscriber);
|
||||
}
|
||||
|
||||
/** Unsubscribes a listener from this event.
|
||||
* @param subscriber The listener to unsubscribe.
|
||||
*/
|
||||
void Unsubscribe(ModuleEventListener* subscriber)
|
||||
{
|
||||
subscribers.erase(subscriber);
|
||||
OnUnsubscribe(subscriber);
|
||||
}
|
||||
|
||||
private:
|
||||
void OnCapture() override
|
||||
@ -67,6 +83,16 @@ class Events::ModuleEventProvider : public ServiceProvider, private dynamic_refe
|
||||
subscribers.clear();
|
||||
}
|
||||
|
||||
/** Called when a listener subscribes to this event.
|
||||
* @param subscriber The listener which subscribed.
|
||||
*/
|
||||
virtual void OnSubscribe(ModuleEventListener* subscriber) { }
|
||||
|
||||
/** Called when a listener unsubscribes from this event.
|
||||
* @param subscriber The listener which unsubscribed.
|
||||
*/
|
||||
virtual void OnUnsubscribe(ModuleEventListener* subscriber) { }
|
||||
|
||||
/** Reference to the active provider for this event. In case multiple event providers
|
||||
* exist for the same event, only one of them contains the list of subscribers.
|
||||
* To handle the case when we are not the ones with the list, we get it from the provider
|
||||
@ -95,7 +121,7 @@ class Events::ModuleEventListener : private dynamic_reference_base::CaptureHook
|
||||
*/
|
||||
void OnCapture() override
|
||||
{
|
||||
prov->subscribers.insert(this);
|
||||
prov->Subscribe(this);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -119,7 +145,7 @@ class Events::ModuleEventListener : private dynamic_reference_base::CaptureHook
|
||||
~ModuleEventListener()
|
||||
{
|
||||
if (prov)
|
||||
prov->subscribers.erase(this);
|
||||
prov->Unsubscribe(this);
|
||||
}
|
||||
|
||||
/** Retrieves the module which created this listener. */
|
||||
|
@ -119,7 +119,9 @@ class CoreExport ExtensionItem : public ServiceProvider, public usecountbase
|
||||
* a flags variable, and each module defining bits within the flag as 'theirs' as it is less prone to conflict and
|
||||
* supports arbitary data storage).
|
||||
*/
|
||||
class CoreExport Extensible : public classbase
|
||||
class CoreExport Extensible
|
||||
: public classbase
|
||||
, public Serializable
|
||||
{
|
||||
public:
|
||||
typedef insp::flat_map<reference<ExtensionItem>, void*> ExtensibleStore;
|
||||
@ -151,6 +153,12 @@ class CoreExport Extensible : public classbase
|
||||
* Free all extension items attached to this Extensible
|
||||
*/
|
||||
void FreeAllExtItems();
|
||||
|
||||
/** @copydoc Serializable::Deserialize. */
|
||||
bool Deserialize(Data& data) override;
|
||||
|
||||
/** @copydoc Serializable::Deserialize. */
|
||||
bool Serialize(Serializable::Data& data) override;
|
||||
};
|
||||
|
||||
class CoreExport ExtensionManager
|
||||
|
@ -64,6 +64,7 @@ CoreExport extern InspIRCd* ServerInstance;
|
||||
#include "dynref.h"
|
||||
#include "consolecolors.h"
|
||||
#include "cull_list.h"
|
||||
#include "serialize.h"
|
||||
#include "extensible.h"
|
||||
#include "fileutils.h"
|
||||
#include "ctables.h"
|
||||
|
@ -120,6 +120,9 @@ class CoreExport ListModeBase : public ModeHandler
|
||||
*/
|
||||
ListModeBase(Module* Creator, const std::string& Name, char modechar, const std::string& eolstr, unsigned int lnum, unsigned int eolnum, bool autotidy);
|
||||
|
||||
/** Determines whether some channels have longer lists than others. */
|
||||
bool HasVariableLength() const { return chanlimits.size() > 1; }
|
||||
|
||||
/** Get limit of this mode on a channel
|
||||
* @param channel The channel to inspect
|
||||
* @return Maximum number of modes of this type that can be placed on the given channel
|
||||
|
@ -217,7 +217,7 @@ enum Implementation
|
||||
I_OnUserConnect, I_OnUserPreQuit, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart,
|
||||
I_OnSendSnotice, I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper,
|
||||
I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNick,
|
||||
I_OnUserPostMessage, I_OnUserMessageBlocked, I_OnMode,
|
||||
I_OnUserPostMessage, I_OnUserMessageBlocked, I_OnMode, I_OnShutdown,
|
||||
I_OnDecodeMetaData, I_OnAcceptConnection, I_OnUserInit, I_OnUserPostInit,
|
||||
I_OnChangeHost, I_OnChangeRealName, I_OnAddLine, I_OnDelLine, I_OnExpireLine,
|
||||
I_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, I_OnLoadModule,
|
||||
@ -950,6 +950,12 @@ class CoreExport Module : public classbase, public usecountbase
|
||||
* disconnect the user, or MOD_RES_PASSTHRU to let another module handle the event.
|
||||
*/
|
||||
virtual ModResult OnConnectionFail(LocalUser* user, BufferedSocketError error);
|
||||
|
||||
/** Called before a server shuts down.
|
||||
* @param reason The reason the server is shutting down.
|
||||
* @param restart Whether the server is restarting.
|
||||
*/
|
||||
virtual void OnShutdown(const std::string& reason);
|
||||
};
|
||||
|
||||
/** ModuleManager takes care of all things module-related
|
||||
|
@ -146,6 +146,7 @@ namespace DNS
|
||||
virtual void Process(Request* req) = 0;
|
||||
virtual void RemoveRequest(Request* req) = 0;
|
||||
virtual std::string GetErrorStr(Error) = 0;
|
||||
virtual std::string GetTypeStr(QueryType) = 0;
|
||||
};
|
||||
|
||||
/** A DNS query.
|
||||
|
@ -56,15 +56,21 @@ class ServerProtocol::LinkEventListener
|
||||
{
|
||||
}
|
||||
|
||||
/** Fired when a server finishes burst
|
||||
* @param server Server that recently linked and finished burst
|
||||
/** Fired when a server has linked to the network.
|
||||
* @param server Server that recently linked.
|
||||
*/
|
||||
virtual void OnServerLink(const Server* server) { }
|
||||
|
||||
/** Fired when a server splits
|
||||
* @param server Server that split
|
||||
*/
|
||||
virtual void OnServerSplit(const Server* server) { }
|
||||
/** Fired when a server has finished bursting.
|
||||
* @param server Server that recently finished bursting.
|
||||
*/
|
||||
virtual void OnServerBurst(const Server* server) { }
|
||||
|
||||
/** Fired when a server splits
|
||||
* @param server Server that split
|
||||
* @param error Whether the server split because of an error.
|
||||
*/
|
||||
virtual void OnServerSplit(const Server* server, bool error) { }
|
||||
};
|
||||
|
||||
class ServerProtocol::MessageEventListener
|
||||
|
@ -228,12 +228,19 @@ class SQL::Query : public classbase
|
||||
*/
|
||||
class SQL::Provider : public DataProvider
|
||||
{
|
||||
private:
|
||||
/** The name of the database tag in the config. */
|
||||
const std::string dbid;
|
||||
|
||||
public:
|
||||
Provider(Module* Creator, const std::string& Name)
|
||||
: DataProvider(Creator, Name)
|
||||
: DataProvider(Creator, "SQL/" + Name)
|
||||
{
|
||||
}
|
||||
|
||||
/** Retrieves the name of the database tag in the config. */
|
||||
const std::string& GetId() const { return dbid; }
|
||||
|
||||
/** Submit an asynchronous SQL query.
|
||||
* @param callback The result reporting point
|
||||
* @param query The hardcoded query string. If you have parameters to substitute, see below.
|
||||
|
117
include/serialize.h
Normal file
117
include/serialize.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* InspIRCd -- Internet Relay Chat Daemon
|
||||
*
|
||||
* Copyright (C) 2019 Peter Powell <petpow@saberuk.com>
|
||||
*
|
||||
* This file is part of InspIRCd. InspIRCd is free software: you can
|
||||
* redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
/** Base class for serializable elements. */
|
||||
class CoreExport Serializable
|
||||
{
|
||||
protected:
|
||||
Serializable() { }
|
||||
|
||||
public:
|
||||
/** Encapsulates a chunk of serialised data. */
|
||||
class CoreExport Data
|
||||
{
|
||||
public:
|
||||
/** Maps keys to serialised data. */
|
||||
typedef insp::flat_map<std::string, Data> ChildMap;
|
||||
|
||||
/** Maps keys to simple values. */
|
||||
typedef insp::flat_map<std::string, std::string> EntryMap;
|
||||
|
||||
private:
|
||||
/** A mapping of keys to serialised data. */
|
||||
ChildMap children;
|
||||
|
||||
/** A mapping of keys to values. */
|
||||
EntryMap entries;
|
||||
|
||||
public:
|
||||
/** Retrieves the child elements. */
|
||||
const ChildMap& GetChildren() const { return children; }
|
||||
ChildMap& GetChildren() { return children; }
|
||||
|
||||
/** Retrieves the key/value map. */
|
||||
const EntryMap& GetEntries() const { return entries; }
|
||||
EntryMap& GetEntries() { return entries; }
|
||||
|
||||
/** Loads the serialised data with the specified key.
|
||||
* @param key The key by which this serialised data is identified.
|
||||
* @param out The location to store the serialised data for this key.
|
||||
*/
|
||||
Data& Load(const std::string& key, Data& out);
|
||||
|
||||
/** Loads the value with the specified key.
|
||||
* @param key The key by which this data is identified.
|
||||
* @param out The location to store the value for this keu
|
||||
*/
|
||||
Data& Load(const std::string& key, std::string& out);
|
||||
|
||||
/** Loads the value with the specified key. The value will be converted to the specified type.
|
||||
* @param key The key by which this data is identified.
|
||||
* @param out The location to store the value for this key.
|
||||
*/
|
||||
template <typename T>
|
||||
Data& Load(const std::string& key, T& out)
|
||||
{
|
||||
// Attempt to load as a string.
|
||||
std::string str;
|
||||
Load(key, str);
|
||||
|
||||
std::stringstream ss(str);
|
||||
ss >> out;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Stores the serialised data against the specified key.
|
||||
* @param key The key by which this serialised data should be stored against.
|
||||
* @param out The serialised data to store.
|
||||
*/
|
||||
Data& Store(const std::string& key, const Data& value);
|
||||
|
||||
/** Stores the value against the specified key.
|
||||
* @param key The key by which this value should be stored against.
|
||||
* @param out The value to store.
|
||||
*/
|
||||
Data& Store(const std::string& key, const std::string& value);
|
||||
|
||||
/** Stores the value against the specified key. The value will be converted to a string using ConvToStr.
|
||||
* @param key The key by which this value should be stored against.
|
||||
* @param out The value to store.
|
||||
*/
|
||||
template <typename T>
|
||||
Data& Store(const std::string& key, const T& value)
|
||||
{
|
||||
return Store(key, ConvToStr(value));
|
||||
}
|
||||
};
|
||||
|
||||
/** Deserializes the specified Data instance into this object.
|
||||
* @param data The Data object to deserialize from.
|
||||
* @return True if the deserialisation succeeded; otherwise, false.
|
||||
*/
|
||||
virtual bool Deserialize(Data& data) = 0;
|
||||
|
||||
/** Serializes the this object into the specified Data obect.
|
||||
* @param data The Data object to serialize to.
|
||||
* @return True if the serialisation succeeded; otherwise, false.
|
||||
*/
|
||||
virtual bool Serialize(Data& data) = 0;
|
||||
};
|
@ -22,6 +22,9 @@
|
||||
class CoreExport Server : public classbase
|
||||
{
|
||||
protected:
|
||||
/** The unique identifier for this server. */
|
||||
const std::string id;
|
||||
|
||||
/** The name of this server
|
||||
*/
|
||||
const std::string name;
|
||||
@ -44,8 +47,17 @@ class CoreExport Server : public classbase
|
||||
friend class ConfigReaderThread;
|
||||
|
||||
public:
|
||||
Server(const std::string& srvname, const std::string& srvdesc)
|
||||
: name(srvname), description(srvdesc), uline(false), silentuline(false) { }
|
||||
Server(const std::string& srvid, const std::string& srvname, const std::string& srvdesc)
|
||||
: id(srvid)
|
||||
, name(srvname)
|
||||
, description(srvdesc)
|
||||
, uline(false)
|
||||
, silentuline(false)
|
||||
{
|
||||
}
|
||||
|
||||
/** Retrieves the unique identifier for this server (e.g. 36C). */
|
||||
const std::string& GetId() const { return id; }
|
||||
|
||||
/**
|
||||
* Returns the name of this server
|
||||
|
@ -592,6 +592,12 @@ class CoreExport User : public Extensible
|
||||
*/
|
||||
virtual ~User();
|
||||
CullResult cull() override;
|
||||
|
||||
/** @copydoc Serializable::Deserialize. */
|
||||
bool Deserialize(Data& data) override;
|
||||
|
||||
/** @copydoc Serializable::Deserialize. */
|
||||
bool Serialize(Serializable::Data& data) override;
|
||||
};
|
||||
|
||||
class CoreExport UserIOHandler : public StreamSocket
|
||||
@ -645,6 +651,8 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local
|
||||
|
||||
public:
|
||||
LocalUser(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server);
|
||||
LocalUser(int fd, const std::string& uuid, Serializable::Data& data);
|
||||
|
||||
CullResult cull() override;
|
||||
|
||||
UserIOHandler eh;
|
||||
@ -788,6 +796,12 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local
|
||||
* @param msg Message to send.
|
||||
*/
|
||||
void Send(ClientProtocol::EventProvider& protoevprov, ClientProtocol::Message& msg);
|
||||
|
||||
/** @copydoc Serializable::Deserialize. */
|
||||
bool Deserialize(Data& data) override;
|
||||
|
||||
/** @copydoc Serializable::Deserialize. */
|
||||
bool Serialize(Serializable::Data& data) override;
|
||||
};
|
||||
|
||||
class RemoteUser : public User
|
||||
@ -801,13 +815,14 @@ class RemoteUser : public User
|
||||
class CoreExport FakeUser : public User
|
||||
{
|
||||
public:
|
||||
FakeUser(const std::string& uid, Server* srv) : User(uid, srv, USERTYPE_SERVER)
|
||||
FakeUser(const std::string& uid, Server* srv)
|
||||
: User(uid, srv, USERTYPE_SERVER)
|
||||
{
|
||||
nick = srv->GetName();
|
||||
}
|
||||
|
||||
FakeUser(const std::string& uid, const std::string& sname, const std::string& sdesc)
|
||||
: User(uid, new Server(sname, sdesc), USERTYPE_SERVER)
|
||||
: User(uid, new Server(uid, sname, sdesc), USERTYPE_SERVER)
|
||||
{
|
||||
nick = sname;
|
||||
}
|
||||
@ -821,17 +836,17 @@ class CoreExport FakeUser : public User
|
||||
/** Is a local user */
|
||||
inline LocalUser* IS_LOCAL(User* u)
|
||||
{
|
||||
return u->usertype == USERTYPE_LOCAL ? static_cast<LocalUser*>(u) : NULL;
|
||||
return (u != NULL && u->usertype == USERTYPE_LOCAL) ? static_cast<LocalUser*>(u) : NULL;
|
||||
}
|
||||
/** Is a remote user */
|
||||
inline RemoteUser* IS_REMOTE(User* u)
|
||||
{
|
||||
return u->usertype == USERTYPE_REMOTE ? static_cast<RemoteUser*>(u) : NULL;
|
||||
return (u != NULL && u->usertype == USERTYPE_REMOTE) ? static_cast<RemoteUser*>(u) : NULL;
|
||||
}
|
||||
/** Is a server fakeuser */
|
||||
inline FakeUser* IS_SERVER(User* u)
|
||||
{
|
||||
return u->usertype == USERTYPE_SERVER ? static_cast<FakeUser*>(u) : NULL;
|
||||
return (u != NULL && u->usertype == USERTYPE_SERVER) ? static_cast<FakeUser*>(u) : NULL;
|
||||
}
|
||||
|
||||
inline bool User::IsModeSet(const ModeHandler* mh) const
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
|
||||
BEGIN {
|
||||
push @INC, $ENV{SOURCEPATH};
|
||||
require 5.10.0;
|
||||
unless (-f 'configure') {
|
||||
print "Error: $0 must be run from the main source directory!\n";
|
||||
@ -32,6 +33,8 @@ use warnings FATAL => qw(all);
|
||||
|
||||
use File::Basename qw(basename);
|
||||
|
||||
use make::common;
|
||||
|
||||
use constant {
|
||||
BUILDPATH => $ENV{BUILDPATH},
|
||||
SOURCEPATH => $ENV{SOURCEPATH}
|
||||
@ -50,7 +53,7 @@ run;
|
||||
exit 0;
|
||||
|
||||
sub run() {
|
||||
mkdir BUILDPATH;
|
||||
create_directory(BUILDPATH, 0770) or die "Could not create build directory: $!";
|
||||
chdir BUILDPATH or die "Could not open build directory: $!";
|
||||
unlink 'include';
|
||||
symlink "${\SOURCEPATH}/include", 'include';
|
||||
|
@ -32,7 +32,7 @@
|
||||
CXX = @CXX@ -std=c++14
|
||||
COMPILER = @COMPILER_NAME@
|
||||
SYSTEM = @SYSTEM_NAME@
|
||||
BUILDPATH ?= $(dir $(realpath $(firstword $(MAKEFILE_LIST))))/build
|
||||
BUILDPATH ?= $(dir $(realpath $(firstword $(MAKEFILE_LIST))))/build/@COMPILER_NAME@-@COMPILER_VERSION@
|
||||
SOCKETENGINE = @SOCKETENGINE@
|
||||
CORECXXFLAGS = -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -pipe -Iinclude -Wall -Wextra -Wfatal-errors -Wno-unused-parameter -Wshadow
|
||||
LDLIBS = -lstdc++
|
||||
|
@ -202,16 +202,22 @@ class CoreModChannel : public Module, public CheckExemption::EventListener
|
||||
{
|
||||
tokens["KEYLEN"] = ConvToStr(ModeChannelKey::maxkeylen);
|
||||
|
||||
// Build a map of limits to their mode character.
|
||||
insp::flat_map<int, std::string> limits;
|
||||
std::string vlist;
|
||||
const ModeParser::ListModeList& listmodes = ServerInstance->Modes.GetListModes();
|
||||
for (ModeParser::ListModeList::const_iterator iter = listmodes.begin(); iter != listmodes.end(); ++iter)
|
||||
{
|
||||
const unsigned int limit = (*iter)->GetLowerLimit();
|
||||
limits[limit].push_back((*iter)->GetModeChar());
|
||||
}
|
||||
ListModeBase* lm = *iter;
|
||||
|
||||
const unsigned int limit = lm->GetLowerLimit();
|
||||
limits[limit].push_back(lm->GetModeChar());
|
||||
|
||||
if (lm->HasVariableLength())
|
||||
vlist.push_back(lm->GetModeChar());
|
||||
}
|
||||
if (!vlist.empty())
|
||||
tokens["VLIST"] = vlist;
|
||||
|
||||
// Generate the MAXLIST token from the limits map.
|
||||
std::string& buffer = tokens["MAXLIST"];
|
||||
for (insp::flat_map<int, std::string>::const_iterator iter = limits.begin(); iter != limits.end(); ++iter)
|
||||
{
|
||||
|
@ -538,6 +538,25 @@ class MyManager : public Manager, public Timer, public EventHandler
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetTypeStr(QueryType qt) override
|
||||
{
|
||||
switch (qt)
|
||||
{
|
||||
case QUERY_A:
|
||||
return "A";
|
||||
case QUERY_AAAA:
|
||||
return "AAAA";
|
||||
case QUERY_CNAME:
|
||||
return "CNAME";
|
||||
case QUERY_PTR:
|
||||
return "PTR";
|
||||
case QUERY_TXT:
|
||||
return "TXT";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void OnEventHandlerError(int errcode) override
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "UDP socket got an error event");
|
||||
|
@ -23,19 +23,26 @@
|
||||
namespace
|
||||
{
|
||||
IntExtItem* dl;
|
||||
StringExtItem* ph;
|
||||
}
|
||||
|
||||
/** Derived from Resolver, and performs user forward/reverse lookups.
|
||||
*/
|
||||
class UserResolver : public DNS::Request
|
||||
{
|
||||
private:
|
||||
/** UUID we are looking up */
|
||||
const std::string uuid;
|
||||
|
||||
/** True if the lookup is forward, false if is a reverse lookup
|
||||
*/
|
||||
const bool fwd;
|
||||
/** Handles errors which happen during DNS resolution. */
|
||||
static void HandleError(LocalUser* user, const std::string& message)
|
||||
{
|
||||
user->WriteNotice("*** " + message + "; using your IP address (" + user->GetIPString() + ") instead.");
|
||||
|
||||
bool display_is_real = user->GetDisplayedHost() == user->GetRealHost();
|
||||
user->ChangeRealHost(user->GetIPString(), display_is_real);
|
||||
|
||||
dl->unset(user);
|
||||
}
|
||||
|
||||
public:
|
||||
/** Create a resolver.
|
||||
@ -48,7 +55,6 @@ class UserResolver : public DNS::Request
|
||||
UserResolver(DNS::Manager* mgr, Module* me, LocalUser* user, const std::string& to_resolve, DNS::QueryType qt)
|
||||
: DNS::Request(mgr, me, to_resolve, qt)
|
||||
, uuid(user->uuid)
|
||||
, fwd(qt == DNS::QUERY_A || qt == DNS::QUERY_AAAA)
|
||||
{
|
||||
}
|
||||
|
||||
@ -58,7 +64,7 @@ class UserResolver : public DNS::Request
|
||||
*/
|
||||
void OnLookupComplete(const DNS::Query* r) override
|
||||
{
|
||||
LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid);
|
||||
LocalUser* bound_user = IS_LOCAL(ServerInstance->FindUUID(uuid));
|
||||
if (!bound_user)
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Resolution finished for user '%s' who is gone", uuid.c_str());
|
||||
@ -68,17 +74,17 @@ class UserResolver : public DNS::Request
|
||||
const DNS::ResourceRecord* ans_record = r->FindAnswerOfType(this->question.type);
|
||||
if (ans_record == NULL)
|
||||
{
|
||||
OnError(r);
|
||||
HandleError(bound_user, "Could not resolve your hostname: No " + this->manager->GetTypeStr(this->question.type) + " records found");
|
||||
return;
|
||||
}
|
||||
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "DNS result for %s: '%s' -> '%s'", uuid.c_str(), ans_record->name.c_str(), ans_record->rdata.c_str());
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "DNS %s result for %s: '%s' -> '%s'%s",
|
||||
this->manager->GetTypeStr(question.type).c_str(), uuid.c_str(),
|
||||
ans_record->name.c_str(), ans_record->rdata.c_str(),
|
||||
r->cached ? " (cached)" : "");
|
||||
|
||||
if (!fwd)
|
||||
if (this->question.type == DNS::QUERY_PTR)
|
||||
{
|
||||
// first half of resolution is done. We now need to verify that the host matches.
|
||||
ph->set(bound_user, ans_record->rdata);
|
||||
|
||||
UserResolver* res_forward;
|
||||
if (bound_user->client_sa.family() == AF_INET6)
|
||||
{
|
||||
@ -99,11 +105,10 @@ class UserResolver : public DNS::Request
|
||||
delete res_forward;
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Error in resolver: " + e.GetReason());
|
||||
|
||||
bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead.");
|
||||
dl->set(bound_user, 0);
|
||||
HandleError(bound_user, "There was an internal error resolving your host");
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (this->question.type == DNS::QUERY_A || this->question.type == DNS::QUERY_AAAA)
|
||||
{
|
||||
/* Both lookups completed */
|
||||
|
||||
@ -126,37 +131,15 @@ class UserResolver : public DNS::Request
|
||||
}
|
||||
}
|
||||
|
||||
dl->set(bound_user, 0);
|
||||
|
||||
if (rev_match)
|
||||
{
|
||||
std::string* hostname = ph->get(bound_user);
|
||||
|
||||
if (hostname == NULL)
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "ERROR: User has no hostname attached when doing a forward lookup");
|
||||
bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead.");
|
||||
return;
|
||||
}
|
||||
else if (hostname->length() <= ServerInstance->Config->Limits.MaxHost)
|
||||
{
|
||||
/* Hostnames starting with : are not a good thing (tm) */
|
||||
if ((*hostname)[0] == ':')
|
||||
hostname->insert(0, "0");
|
||||
|
||||
bound_user->WriteNotice("*** Found your hostname (" + *hostname + (r->cached ? ") -- cached" : ")"));
|
||||
bound_user->ChangeRealHost(hostname->substr(0, ServerInstance->Config->Limits.MaxHost), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
bound_user->WriteNotice("*** Your hostname is longer than the maximum of " + ConvToStr(ServerInstance->Config->Limits.MaxHost) + " characters, using your IP address (" + bound_user->GetIPString() + ") instead.");
|
||||
}
|
||||
|
||||
ph->unset(bound_user);
|
||||
bound_user->WriteNotice("*** Found your hostname (" + this->question.name + (r->cached ? ") -- cached" : ")"));
|
||||
bound_user->ChangeRealHost(this->question.name, true);
|
||||
dl->unset(bound_user);
|
||||
}
|
||||
else
|
||||
{
|
||||
bound_user->WriteNotice("*** Your hostname does not match up with your IP address. Sorry, using your IP address (" + bound_user->GetIPString() + ") instead.");
|
||||
HandleError(bound_user, "Your hostname does not match up with your IP address");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,29 +149,24 @@ class UserResolver : public DNS::Request
|
||||
*/
|
||||
void OnError(const DNS::Query* query) override
|
||||
{
|
||||
LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid);
|
||||
LocalUser* bound_user = IS_LOCAL(ServerInstance->FindUUID(uuid));
|
||||
if (bound_user)
|
||||
{
|
||||
bound_user->WriteNotice("*** Could not resolve your hostname: " + this->manager->GetErrorStr(query->error) + "; using your IP address (" + bound_user->GetIPString() + ") instead.");
|
||||
dl->set(bound_user, 0);
|
||||
}
|
||||
HandleError(bound_user, "Could not resolve your hostname: " + this->manager->GetErrorStr(query->error));
|
||||
}
|
||||
};
|
||||
|
||||
class ModuleHostnameLookup : public Module
|
||||
{
|
||||
private:
|
||||
IntExtItem dnsLookup;
|
||||
StringExtItem ptrHosts;
|
||||
dynamic_reference<DNS::Manager> DNS;
|
||||
|
||||
public:
|
||||
ModuleHostnameLookup()
|
||||
: dnsLookup(this, "dnsLookup", ExtensionItem::EXT_USER)
|
||||
, ptrHosts(this, "ptrHosts", ExtensionItem::EXT_USER)
|
||||
, DNS(this, "DNS")
|
||||
{
|
||||
dl = &dnsLookup;
|
||||
ph = &ptrHosts;
|
||||
}
|
||||
|
||||
void OnSetUserIP(LocalUser* user) override
|
||||
|
@ -93,8 +93,11 @@ void InspIRCd::Cleanup()
|
||||
}
|
||||
ports.clear();
|
||||
|
||||
// Disconnect all local users
|
||||
// Tell modules that we're shutting down.
|
||||
const std::string quitmsg = "Server shutting down";
|
||||
FOREACH_MOD(OnShutdown, (quitmsg));
|
||||
|
||||
// Disconnect all local users
|
||||
const UserManager::LocalList& list = Users.GetLocalUsers();
|
||||
while (!list.empty())
|
||||
ServerInstance->Users.QuitUser(list.front(), quitmsg);
|
||||
|
@ -141,6 +141,7 @@ void Module::OnServiceAdd(ServiceProvider&) { DetachEvent(I_OnServiceAdd); }
|
||||
void Module::OnServiceDel(ServiceProvider&) { DetachEvent(I_OnServiceDel); }
|
||||
ModResult Module::OnUserWrite(LocalUser*, ClientProtocol::Message&) { DetachEvent(I_OnUserWrite); return MOD_RES_PASSTHRU; }
|
||||
ModResult Module::OnConnectionFail(LocalUser*, BufferedSocketError) { DetachEvent(I_OnConnectionFail); return MOD_RES_PASSTHRU; }
|
||||
void Module::OnShutdown(const std::string& reason) { DetachEvent(I_OnShutdown); }
|
||||
|
||||
ServiceProvider::ServiceProvider(Module* Creator, const std::string& Name, ServiceType Type)
|
||||
: creator(Creator), name(Name), service(Type)
|
||||
|
@ -247,6 +247,17 @@ class LDAPService : public LDAPProvider, public SocketThread
|
||||
Connect();
|
||||
}
|
||||
|
||||
int SetOption(int option, const void* value)
|
||||
{
|
||||
int ret = ldap_set_option(this->con, option, value);
|
||||
if (ret != LDAP_OPT_SUCCESS)
|
||||
{
|
||||
ldap_unbind_ext(this->con, NULL, NULL);
|
||||
this->con = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void QueueRequest(LDAPRequest* r)
|
||||
{
|
||||
this->LockQueue();
|
||||
@ -318,22 +329,14 @@ class LDAPService : public LDAPProvider, public SocketThread
|
||||
throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i));
|
||||
|
||||
const int version = LDAP_VERSION3;
|
||||
i = ldap_set_option(this->con, LDAP_OPT_PROTOCOL_VERSION, &version);
|
||||
i = SetOption(LDAP_OPT_PROTOCOL_VERSION, &version);
|
||||
if (i != LDAP_OPT_SUCCESS)
|
||||
{
|
||||
ldap_unbind_ext(this->con, NULL, NULL);
|
||||
this->con = NULL;
|
||||
throw LDAPException("Unable to set protocol version for " + this->name + ": " + ldap_err2string(i));
|
||||
}
|
||||
|
||||
const struct timeval tv = { 0, 0 };
|
||||
i = ldap_set_option(this->con, LDAP_OPT_NETWORK_TIMEOUT, &tv);
|
||||
i = SetOption(LDAP_OPT_NETWORK_TIMEOUT, &tv);
|
||||
if (i != LDAP_OPT_SUCCESS)
|
||||
{
|
||||
ldap_unbind_ext(this->con, NULL, NULL);
|
||||
this->con = NULL;
|
||||
throw LDAPException("Unable to set timeout for " + this->name + ": " + ldap_err2string(i));
|
||||
}
|
||||
}
|
||||
|
||||
void BindAsManager(LDAPInterface* i) override
|
||||
|
@ -277,8 +277,10 @@ class SQLConnection : public SQL::Provider
|
||||
std::mutex lock;
|
||||
|
||||
// This constructor creates an SQLConnection object with the given credentials, but does not connect yet.
|
||||
SQLConnection(Module* p, ConfigTag* tag) : SQL::Provider(p, "SQL/" + tag->getString("id")),
|
||||
config(tag), connection(NULL)
|
||||
SQLConnection(Module* p, ConfigTag* tag)
|
||||
: SQL::Provider(p, tag->getString("id"))
|
||||
, config(tag)
|
||||
, connection(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -291,28 +293,43 @@ class SQLConnection : public SQL::Provider
|
||||
// true upon success.
|
||||
bool Connect()
|
||||
{
|
||||
unsigned int timeout = 1;
|
||||
connection = mysql_init(connection);
|
||||
mysql_options(connection,MYSQL_OPT_CONNECT_TIMEOUT,(char*)&timeout);
|
||||
std::string host = config->getString("host");
|
||||
std::string user = config->getString("user");
|
||||
std::string pass = config->getString("pass");
|
||||
std::string dbname = config->getString("name");
|
||||
unsigned int port = config->getUInt("port", 3306);
|
||||
bool rv = mysql_real_connect(connection, host.c_str(), user.c_str(), pass.c_str(), dbname.c_str(), port, NULL, 0);
|
||||
if (!rv)
|
||||
return rv;
|
||||
|
||||
// Enable character set settings
|
||||
std::string charset = config->getString("charset");
|
||||
if ((!charset.empty()) && (mysql_set_character_set(connection, charset.c_str())))
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "WARNING: Could not set character set to \"%s\"", charset.c_str());
|
||||
// Set the connection timeout.
|
||||
unsigned int timeout = config->getDuration("timeout", 5, 1, 30);
|
||||
mysql_options(connection, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
|
||||
std::string initquery;
|
||||
if (config->readString("initialquery", initquery))
|
||||
// Attempt to connect to the database.
|
||||
const std::string host = config->getString("host");
|
||||
const std::string user = config->getString("user");
|
||||
const std::string pass = config->getString("pass");
|
||||
const std::string dbname = config->getString("name");
|
||||
unsigned int port = config->getUInt("port", 3306, 1, 65535);
|
||||
if (!mysql_real_connect(connection, host.c_str(), user.c_str(), pass.c_str(), dbname.c_str(), port, NULL, CLIENT_IGNORE_SIGPIPE))
|
||||
{
|
||||
mysql_query(connection,initquery.c_str());
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Unable to connect to the %s MySQL server: %s",
|
||||
GetId().c_str(), mysql_error(connection));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the default character set.
|
||||
const std::string charset = config->getString("charset");
|
||||
if (!charset.empty() && mysql_set_character_set(connection, charset.c_str()))
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Could not set character set for %s to \"%s\": %s",
|
||||
GetId().c_str(), charset.c_str(), mysql_error(connection));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Execute the initial SQL query.
|
||||
const std::string initialquery = config->getString("initialquery");
|
||||
if (!initialquery.empty() && mysql_real_query(connection, initialquery.data(), initialquery.length()))
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Could not execute initial query \"%s\" for %s: %s",
|
||||
initialquery.c_str(), name.c_str(), mysql_error(connection));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,11 @@ class SQLConn : public SQL::Provider, public EventHandler
|
||||
QueueItem qinprog; /* If there is currently a query in progress */
|
||||
|
||||
SQLConn(Module* Creator, ConfigTag* tag)
|
||||
: SQL::Provider(Creator, "SQL/" + tag->getString("id")), conf(tag), sql(NULL), status(CWRITE), qinprog(NULL, "")
|
||||
: SQL::Provider(Creator, tag->getString("id"))
|
||||
, conf(tag)
|
||||
, sql(NULL)
|
||||
, status(CWRITE)
|
||||
, qinprog(NULL, "")
|
||||
{
|
||||
if (!DoConnect())
|
||||
{
|
||||
|
@ -97,7 +97,9 @@ class SQLConn : public SQL::Provider
|
||||
reference<ConfigTag> config;
|
||||
|
||||
public:
|
||||
SQLConn(Module* Parent, ConfigTag* tag) : SQL::Provider(Parent, "SQL/" + tag->getString("id")), config(tag)
|
||||
SQLConn(Module* Parent, ConfigTag* tag)
|
||||
: SQL::Provider(Parent, tag->getString("id"))
|
||||
, config(tag)
|
||||
{
|
||||
std::string host = tag->getString("hostname");
|
||||
if (sqlite3_open_v2(host.c_str(), &conn, SQLITE_OPEN_READWRITE, 0) != SQLITE_OK)
|
||||
|
@ -1193,7 +1193,7 @@ class ModuleSSLGnuTLS : public Module
|
||||
|
||||
void OnModuleRehash(User* user, const std::string ¶m) override
|
||||
{
|
||||
if(param != "ssl")
|
||||
if (!irc::equals(param, "ssl"))
|
||||
return;
|
||||
|
||||
try
|
||||
|
@ -926,7 +926,7 @@ class ModuleSSLmbedTLS : public Module
|
||||
|
||||
void OnModuleRehash(User* user, const std::string ¶m) override
|
||||
{
|
||||
if (param != "ssl")
|
||||
if (!irc::equals(param, "ssl"))
|
||||
return;
|
||||
|
||||
try
|
||||
|
@ -980,7 +980,7 @@ class ModuleSSLOpenSSL : public Module
|
||||
|
||||
void OnModuleRehash(User* user, const std::string ¶m) override
|
||||
{
|
||||
if (param != "ssl")
|
||||
if (!irc::equals(param, "ssl"))
|
||||
return;
|
||||
|
||||
try
|
||||
|
@ -375,12 +375,14 @@ class ModuleCloaking : public Module
|
||||
{
|
||||
u->SetMode(cu, false);
|
||||
|
||||
if (!IS_LOCAL(u))
|
||||
LocalUser* luser = IS_LOCAL(u);
|
||||
if (!luser)
|
||||
return;
|
||||
|
||||
Modes::ChangeList modechangelist;
|
||||
modechangelist.push_remove(&cu);
|
||||
ClientProtocol::Events::Mode modeevent(ServerInstance->FakeClient, NULL, u, modechangelist);
|
||||
static_cast<LocalUser*>(u)->Send(modeevent);
|
||||
luser->Send(modeevent);
|
||||
}
|
||||
cu.active = false;
|
||||
}
|
||||
|
@ -19,8 +19,11 @@
|
||||
|
||||
#include "inspircd.h"
|
||||
#include "xline.h"
|
||||
#include "modules/webirc.h"
|
||||
|
||||
class ModuleConnectBan : public Module
|
||||
class ModuleConnectBan
|
||||
: public Module
|
||||
, public WebIRC::EventListener
|
||||
{
|
||||
typedef std::map<irc::sockets::cidr_mask, unsigned int> ConnectMap;
|
||||
ConnectMap connects;
|
||||
@ -30,7 +33,33 @@ class ModuleConnectBan : public Module
|
||||
unsigned int ipv6_cidr;
|
||||
std::string banmessage;
|
||||
|
||||
unsigned char GetRange(LocalUser* user)
|
||||
{
|
||||
int family = user->client_sa.family();
|
||||
switch (family)
|
||||
{
|
||||
case AF_INET:
|
||||
return ipv4_cidr;
|
||||
|
||||
case AF_INET6:
|
||||
return ipv6_cidr;
|
||||
|
||||
case AF_UNIX:
|
||||
// Ranges for UNIX sockets are ignored entirely.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If we have reached this point then we have encountered a bug.
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "BUG: ModuleConnectBan::GetRange(): socket type %d is unknown!", family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
ModuleConnectBan()
|
||||
: WebIRC::EventListener(this)
|
||||
{
|
||||
}
|
||||
|
||||
Version GetVersion() override
|
||||
{
|
||||
return Version("Throttles the connections of IP ranges who try to connect flood", VF_VENDOR);
|
||||
@ -47,24 +76,26 @@ class ModuleConnectBan : public Module
|
||||
banmessage = tag->getString("banmessage", "Your IP range has been attempting to connect too many times in too short a duration. Wait a while, and you will be able to connect.");
|
||||
}
|
||||
|
||||
void OnWebIRCAuth(LocalUser* user, const WebIRC::FlagMap* flags) override
|
||||
{
|
||||
if (user->exempt)
|
||||
return;
|
||||
|
||||
// HACK: Lower the connection attempts for the gateway IP address. The user
|
||||
// will be rechecked for connect spamming shortly after when their IP address
|
||||
// is changed and OnSetUserIP is called.
|
||||
irc::sockets::cidr_mask mask(user->client_sa, GetRange(user));
|
||||
ConnectMap::iterator iter = connects.find(mask);
|
||||
if (iter != connects.end() && iter->second)
|
||||
iter->second--;
|
||||
}
|
||||
|
||||
void OnSetUserIP(LocalUser* u) override
|
||||
{
|
||||
if (u->exempt)
|
||||
return;
|
||||
|
||||
unsigned char range = 32;
|
||||
|
||||
switch (u->client_sa.family())
|
||||
{
|
||||
case AF_INET6:
|
||||
range = ipv6_cidr;
|
||||
break;
|
||||
case AF_INET:
|
||||
range = ipv4_cidr;
|
||||
break;
|
||||
}
|
||||
|
||||
irc::sockets::cidr_mask mask(u->client_sa, range);
|
||||
irc::sockets::cidr_mask mask(u->client_sa, GetRange(u));
|
||||
ConnectMap::iterator i = connects.find(mask);
|
||||
|
||||
if (i != connects.end())
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
quitmsg = tag->getString("quitmsg");
|
||||
|
||||
/* seconds to wait when the server just booted */
|
||||
boot_wait = tag->getDuration("bootwait", 10);
|
||||
boot_wait = tag->getDuration("bootwait", 60*2);
|
||||
|
||||
first = ServerInstance->Time();
|
||||
}
|
||||
|
@ -47,15 +47,21 @@ class DNSBLConfEntry : public refcountbase
|
||||
*/
|
||||
class DNSBLResolver : public DNS::Request
|
||||
{
|
||||
private:
|
||||
irc::sockets::sockaddrs theirsa;
|
||||
std::string theiruid;
|
||||
StringExtItem& nameExt;
|
||||
IntExtItem& countExt;
|
||||
reference<DNSBLConfEntry> ConfEntry;
|
||||
|
||||
public:
|
||||
|
||||
DNSBLResolver(DNS::Manager *mgr, Module *me, StringExtItem& match, IntExtItem& 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)
|
||||
: DNS::Request(mgr, me, hostname, DNS::QUERY_A, true)
|
||||
, theirsa(u->client_sa)
|
||||
, theiruid(u->uuid)
|
||||
, nameExt(match)
|
||||
, countExt(ctr)
|
||||
, ConfEntry(conf)
|
||||
{
|
||||
}
|
||||
|
||||
@ -63,8 +69,8 @@ class DNSBLResolver : public DNS::Request
|
||||
void OnLookupComplete(const DNS::Query *r) override
|
||||
{
|
||||
/* Check the user still exists */
|
||||
LocalUser* them = (LocalUser*)ServerInstance->FindUUID(theiruid);
|
||||
if (!them)
|
||||
LocalUser* them = IS_LOCAL(ServerInstance->FindUUID(theiruid));
|
||||
if (!them || them->client_sa != theirsa)
|
||||
return;
|
||||
|
||||
const DNS::ResourceRecord* const ans_record = r->FindAnswerOfType(DNS::QUERY_A);
|
||||
@ -209,8 +215,8 @@ class DNSBLResolver : public DNS::Request
|
||||
|
||||
void OnError(const DNS::Query *q) override
|
||||
{
|
||||
LocalUser* them = (LocalUser*)ServerInstance->FindUUID(theiruid);
|
||||
if (!them)
|
||||
LocalUser* them = IS_LOCAL(ServerInstance->FindUUID(theiruid));
|
||||
if (!them || them->client_sa != theirsa)
|
||||
return;
|
||||
|
||||
int i = countExt.get(them);
|
||||
|
@ -130,6 +130,9 @@ class ModeHook : public ClientProtocol::EventHook
|
||||
if (!chan)
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
||||
if (user->HasPrivPermission("channels/auspex"))
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
||||
Membership* const memb = chan->GetUser(user);
|
||||
if (!memb)
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
@ -216,7 +216,7 @@ class SearchInterface : public LDAPInterface
|
||||
|
||||
void OnResult(const LDAPResult& r) override
|
||||
{
|
||||
LocalUser* user = static_cast<LocalUser*>(ServerInstance->FindUUID(uid));
|
||||
LocalUser* user = IS_LOCAL(ServerInstance->FindUUID(uid));
|
||||
dynamic_reference<LDAPProvider> LDAP(me, provider);
|
||||
if (!LDAP || r.empty() || !user)
|
||||
{
|
||||
|
@ -113,8 +113,9 @@ class DummyZ : public ModeHandler
|
||||
// Handle /MODE #chan Z
|
||||
void DisplayList(User* user, Channel* chan) override
|
||||
{
|
||||
if (IS_LOCAL(user))
|
||||
::DisplayList(static_cast<LocalUser*>(user), chan);
|
||||
LocalUser* luser = IS_LOCAL(user);
|
||||
if (luser)
|
||||
::DisplayList(luser, chan);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -58,6 +58,14 @@ class ModuleNoCTCP : public Module
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
||||
Channel* c = target.Get<Channel>();
|
||||
const Channel::MemberMap& members = c->GetUsers();
|
||||
for (Channel::MemberMap::const_iterator member = members.begin(); member != members.end(); ++member)
|
||||
{
|
||||
User* u = member->first;
|
||||
if (u->IsModeSet(ncu))
|
||||
details.exemptions.insert(u);
|
||||
}
|
||||
|
||||
ModResult res = CheckExemption::Call(exemptionprov, user, c, "noctcp");
|
||||
if (res == MOD_RES_ALLOW)
|
||||
return MOD_RES_PASSTHRU;
|
||||
@ -67,14 +75,6 @@ class ModuleNoCTCP : public Module
|
||||
user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, "Can't send CTCP to channel (+C is set)");
|
||||
return MOD_RES_DENY;
|
||||
}
|
||||
|
||||
const Channel::MemberMap& members = c->GetUsers();
|
||||
for (Channel::MemberMap::const_iterator member = members.begin(); member != members.end(); ++member)
|
||||
{
|
||||
User* u = member->first;
|
||||
if (u->IsModeSet(ncu))
|
||||
details.exemptions.insert(u);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MessageTarget::TYPE_USER:
|
||||
|
@ -59,7 +59,7 @@ class ServerTracker
|
||||
Update(server, true);
|
||||
}
|
||||
|
||||
void OnServerSplit(const Server* server) override
|
||||
void OnServerSplit(const Server* server, bool error) override
|
||||
{
|
||||
Update(server, false);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class CmdBuilder
|
||||
: content(1, ':')
|
||||
, tagsize(0)
|
||||
{
|
||||
content.append(src->GetID());
|
||||
content.append(src->GetId());
|
||||
push(cmd);
|
||||
FireEvent(src, cmd, tags);
|
||||
}
|
||||
|
@ -381,7 +381,7 @@ bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, Comm
|
||||
return false;
|
||||
}
|
||||
|
||||
params[0] = server->GetID();
|
||||
params[0] = server->GetId();
|
||||
}
|
||||
}
|
||||
else if ((cmd == "GLINE") || (cmd == "KLINE") || (cmd == "ELINE") || (cmd == "ZLINE") || (cmd == "QLINE"))
|
||||
@ -564,7 +564,7 @@ bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, Comm
|
||||
// Second parameter becomes the target uuid
|
||||
params[0].swap(params[1]);
|
||||
// Replace first param (now the PUSH payload, not needed) with the source sid
|
||||
params[0] = numericsource->GetID();
|
||||
params[0] = numericsource->GetId();
|
||||
|
||||
params.push_back(InspIRCd::Format("%03u", numeric_number));
|
||||
|
||||
|
@ -689,7 +689,7 @@ void ModuleSpanningTree::OnUnloadModule(Module* mod)
|
||||
{
|
||||
TreeServer* server = i->second;
|
||||
if (!server->IsRoot())
|
||||
FOREACH_MOD_CUSTOM(GetLinkEventProvider(), ServerProtocol::LinkEventListener, OnServerSplit, (server));
|
||||
FOREACH_MOD_CUSTOM(GetLinkEventProvider(), ServerProtocol::LinkEventListener, OnServerSplit, (server, false));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -793,6 +793,13 @@ void ModuleSpanningTree::OnMode(User* source, User* u, Channel* c, const Modes::
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleSpanningTree::OnShutdown(const std::string& reason)
|
||||
{
|
||||
const TreeServer::ChildServers& children = Utils->TreeRoot->GetChildren();
|
||||
while (!children.empty())
|
||||
children.front()->SQuit(reason, true);
|
||||
}
|
||||
|
||||
CullResult ModuleSpanningTree::cull()
|
||||
{
|
||||
if (Utils)
|
||||
@ -804,7 +811,7 @@ ModuleSpanningTree::~ModuleSpanningTree()
|
||||
{
|
||||
ServerInstance->PI = &ServerInstance->DefaultProtocolInterface;
|
||||
|
||||
Server* newsrv = new Server(ServerInstance->Config->ServerName, ServerInstance->Config->ServerDesc);
|
||||
Server* newsrv = new Server(ServerInstance->Config->GetSID(), ServerInstance->Config->ServerName, ServerInstance->Config->ServerDesc);
|
||||
SetLocalUsersServer(newsrv);
|
||||
|
||||
delete Utils;
|
||||
|
@ -212,6 +212,7 @@ class ModuleSpanningTree
|
||||
void OnUnloadModule(Module* mod) override;
|
||||
ModResult OnAcceptConnection(int newsock, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) override;
|
||||
void OnMode(User* source, User* u, Channel* c, const Modes::ChangeList& modes, ModeParser::ModeProcessFlag processflags) override;
|
||||
void OnShutdown(const std::string& reason) override;
|
||||
CullResult cull() override;
|
||||
~ModuleSpanningTree();
|
||||
Version GetVersion() override;
|
||||
|
@ -51,7 +51,7 @@ CommandNum::Builder::Builder(SpanningTree::RemoteUser* target, const Numeric::Nu
|
||||
: CmdBuilder("NUM")
|
||||
{
|
||||
TreeServer* const server = (numeric.GetServer() ? (static_cast<TreeServer*>(numeric.GetServer())) : Utils->TreeRoot);
|
||||
push(server->GetID()).push(target->uuid).push(InspIRCd::Format("%03u", numeric.GetNumeric()));
|
||||
push(server->GetId()).push(target->uuid).push(InspIRCd::Format("%03u", numeric.GetNumeric()));
|
||||
const CommandBase::Params& params = numeric.GetParams();
|
||||
if (!params.empty())
|
||||
{
|
||||
|
@ -76,7 +76,7 @@ static std::vector<std::string> GetMap(User* user, TreeServer* current, unsigned
|
||||
std::string buffer = current->GetName();
|
||||
if (user->IsOper())
|
||||
{
|
||||
buffer += " (" + current->GetID();
|
||||
buffer += " (" + current->GetId();
|
||||
|
||||
const std::string& cur_vers = current->GetRawVersion();
|
||||
if (!cur_vers.empty())
|
||||
|
@ -36,7 +36,7 @@ PingTimer::State PingTimer::TickInternal()
|
||||
if (state == PS_SENDPING)
|
||||
{
|
||||
// Last ping was answered, send next ping
|
||||
server->GetSocket()->WriteLine(CmdBuilder("PING").push(server->GetID()));
|
||||
server->GetSocket()->WriteLine(CmdBuilder("PING").push(server->GetId()));
|
||||
LastPingMsec = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
|
||||
// Warn next unless warnings are disabled. If they are, jump straight to timeout.
|
||||
if (Utils->PingWarnTime)
|
||||
|
@ -64,7 +64,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
|
||||
|
||||
if (encap)
|
||||
{
|
||||
params.push(sdest->GetID());
|
||||
params.push(sdest->GetId());
|
||||
params.push(command);
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ bool SpanningTreeProtocolInterface::SendEncapsulatedData(const std::string& targ
|
||||
return false;
|
||||
|
||||
// Use the SID of the target in the message instead of the server name
|
||||
encap.push(server->GetID()).push(cmd).insert(params).Unicast(server->ServerUser);
|
||||
encap.push(server->GetId()).push(cmd).insert(params).Unicast(server->ServerUser);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -188,8 +188,8 @@ bool TreeSocket::CheckDuplicate(const std::string& sname, const std::string& sid
|
||||
|
||||
if (CheckDupe)
|
||||
{
|
||||
this->SendError("Server ID "+CheckDupe->GetID()+" already exists on server "+CheckDupe->GetName()+"! You may want to specify the server ID for the server manually with <server:id> so they do not conflict.");
|
||||
ServerInstance->SNO.WriteToSnoMask('l', "Server connection from \002"+sname+"\002 denied, server ID '"+CheckDupe->GetID()+
|
||||
this->SendError("Server ID "+CheckDupe->GetId()+" already exists on server "+CheckDupe->GetName()+"! You may want to specify the server ID for the server manually with <server:id> so they do not conflict.");
|
||||
ServerInstance->SNO.WriteToSnoMask('l', "Server connection from \002"+sname+"\002 denied, server ID '"+CheckDupe->GetId()+
|
||||
"' already exists on server "+CheckDupe->GetName());
|
||||
return false;
|
||||
}
|
||||
@ -228,7 +228,7 @@ CommandServer::Builder::Builder(TreeServer* server)
|
||||
: CmdBuilder(server->GetParent(), "SERVER")
|
||||
{
|
||||
push(server->GetName());
|
||||
push(server->GetID());
|
||||
push(server->GetId());
|
||||
if (server->IsBursting())
|
||||
push_property("burst", ConvToStr(server->StartBurst));
|
||||
push_property("hidden", ConvToStr(server->Hidden));
|
||||
|
@ -32,16 +32,22 @@
|
||||
* no socket associated with it. Its version string is our own local version.
|
||||
*/
|
||||
TreeServer::TreeServer()
|
||||
: Server(ServerInstance->Config->ServerName, ServerInstance->Config->ServerDesc)
|
||||
: Server(ServerInstance->Config->GetSID(), ServerInstance->Config->ServerName, ServerInstance->Config->ServerDesc)
|
||||
, Parent(NULL), Route(NULL)
|
||||
, VersionString(ServerInstance->GetVersionString())
|
||||
, fullversion(ServerInstance->GetVersionString(true))
|
||||
, rawversion(INSPIRCD_VERSION)
|
||||
, Socket(NULL), sid(ServerInstance->Config->GetSID()), behind_bursting(0), isdead(false)
|
||||
, Socket(NULL)
|
||||
, behind_bursting(0)
|
||||
, isdead(false)
|
||||
, pingtimer(this)
|
||||
, ServerUser(ServerInstance->FakeClient)
|
||||
, age(ServerInstance->Time()), UserCount(ServerInstance->Users.LocalUserCount())
|
||||
, OperCount(0), rtt(0), StartBurst(0), Hidden(false)
|
||||
, age(ServerInstance->Time())
|
||||
, UserCount(ServerInstance->Users.LocalUserCount())
|
||||
, OperCount(0)
|
||||
, rtt(0)
|
||||
, StartBurst(0)
|
||||
, Hidden(false)
|
||||
{
|
||||
AddHashEntry();
|
||||
}
|
||||
@ -50,12 +56,20 @@ TreeServer::TreeServer()
|
||||
* This constructor initializes the server's Route and Parent, and sets up
|
||||
* the ping timer for the server.
|
||||
*/
|
||||
TreeServer::TreeServer(const std::string& Name, const std::string& Desc, const std::string& id, TreeServer* Above, TreeSocket* Sock, bool Hide)
|
||||
: Server(Name, Desc)
|
||||
, Parent(Above), Socket(Sock), sid(id), behind_bursting(Parent->behind_bursting), isdead(false)
|
||||
TreeServer::TreeServer(const std::string& Name, const std::string& Desc, const std::string& Sid, TreeServer* Above, TreeSocket* Sock, bool Hide)
|
||||
: Server(Sid, Name, Desc)
|
||||
, Parent(Above)
|
||||
, Socket(Sock)
|
||||
, behind_bursting(Parent->behind_bursting)
|
||||
, isdead(false)
|
||||
, pingtimer(this)
|
||||
, ServerUser(new FakeUser(id, this))
|
||||
, age(ServerInstance->Time()), UserCount(0), OperCount(0), rtt(0), StartBurst(0), Hidden(Hide)
|
||||
, age(ServerInstance->Time())
|
||||
, UserCount(0)
|
||||
, OperCount(0)
|
||||
, rtt(0)
|
||||
, StartBurst(0)
|
||||
, Hidden(Hide)
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "New server %s behind_bursting %u", GetName().c_str(), behind_bursting);
|
||||
CheckULine();
|
||||
@ -128,7 +142,7 @@ void TreeServer::BeginBurst(uint64_t startms)
|
||||
if ((!startms) || (startms > now))
|
||||
startms = now;
|
||||
this->StartBurst = startms;
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Server %s started bursting at time %s behind_bursting %u", sid.c_str(), ConvToStr(startms).c_str(), behind_bursting);
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Server %s started bursting at time %s behind_bursting %u", GetId().c_str(), ConvToStr(startms).c_str(), behind_bursting);
|
||||
}
|
||||
|
||||
void TreeServer::FinishBurstInternal()
|
||||
@ -153,12 +167,13 @@ void TreeServer::FinishBurst()
|
||||
unsigned long bursttime = ts - this->StartBurst;
|
||||
ServerInstance->SNO.WriteToSnoMask(Parent == Utils->TreeRoot ? 'l' : 'L', "Received end of netburst from \002%s\002 (burst time: %lu %s)",
|
||||
GetName().c_str(), (bursttime > 10000 ? bursttime / 1000 : bursttime), (bursttime > 10000 ? "secs" : "msecs"));
|
||||
FOREACH_MOD_CUSTOM(Utils->Creator->GetLinkEventProvider(), ServerProtocol::LinkEventListener, OnServerBurst, (this));
|
||||
|
||||
StartBurst = 0;
|
||||
FinishBurstInternal();
|
||||
}
|
||||
|
||||
void TreeServer::SQuitChild(TreeServer* server, const std::string& reason)
|
||||
void TreeServer::SQuitChild(TreeServer* server, const std::string& reason, bool error)
|
||||
{
|
||||
stdalgo::erase(Children, server);
|
||||
|
||||
@ -166,7 +181,7 @@ void TreeServer::SQuitChild(TreeServer* server, const std::string& reason)
|
||||
{
|
||||
// Server split from us, generate a SQUIT message and broadcast it
|
||||
ServerInstance->SNO.WriteGlobalSno('l', "Server \002" + server->GetName() + "\002 split: " + reason);
|
||||
CmdBuilder("SQUIT").push(server->GetID()).push_last(reason).Broadcast();
|
||||
CmdBuilder("SQUIT").push(server->GetId()).push_last(reason).Broadcast();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -174,7 +189,7 @@ void TreeServer::SQuitChild(TreeServer* server, const std::string& reason)
|
||||
}
|
||||
|
||||
unsigned int num_lost_servers = 0;
|
||||
server->SQuitInternal(num_lost_servers);
|
||||
server->SQuitInternal(num_lost_servers, error);
|
||||
|
||||
const std::string quitreason = GetName() + " " + server->GetName();
|
||||
unsigned int num_lost_users = QuitUsers(quitreason);
|
||||
@ -190,14 +205,14 @@ void TreeServer::SQuitChild(TreeServer* server, const std::string& reason)
|
||||
ServerInstance->GlobalCulls.AddItem(server);
|
||||
}
|
||||
|
||||
void TreeServer::SQuitInternal(unsigned int& num_lost_servers)
|
||||
void TreeServer::SQuitInternal(unsigned int& num_lost_servers, bool error)
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Server %s lost in split", GetName().c_str());
|
||||
|
||||
for (ChildServers::const_iterator i = Children.begin(); i != Children.end(); ++i)
|
||||
{
|
||||
TreeServer* server = *i;
|
||||
server->SQuitInternal(num_lost_servers);
|
||||
server->SQuitInternal(num_lost_servers, error);
|
||||
}
|
||||
|
||||
// Mark server as dead
|
||||
@ -206,7 +221,7 @@ void TreeServer::SQuitInternal(unsigned int& num_lost_servers)
|
||||
RemoveHash();
|
||||
|
||||
if (!Utils->Creator->dying)
|
||||
FOREACH_MOD_CUSTOM(Utils->Creator->GetLinkEventProvider(), ServerProtocol::LinkEventListener, OnServerSplit, (this));
|
||||
FOREACH_MOD_CUSTOM(Utils->Creator->GetLinkEventProvider(), ServerProtocol::LinkEventListener, OnServerSplit, (this, error));
|
||||
}
|
||||
|
||||
unsigned int TreeServer::QuitUsers(const std::string& reason)
|
||||
@ -258,7 +273,7 @@ void TreeServer::CheckULine()
|
||||
void TreeServer::AddHashEntry()
|
||||
{
|
||||
Utils->serverlist[GetName()] = this;
|
||||
Utils->sidlist[sid] = this;
|
||||
Utils->sidlist[GetId()] = this;
|
||||
}
|
||||
|
||||
CullResult TreeServer::cull()
|
||||
@ -288,6 +303,6 @@ TreeServer::~TreeServer()
|
||||
|
||||
void TreeServer::RemoveHash()
|
||||
{
|
||||
Utils->sidlist.erase(sid);
|
||||
Utils->sidlist.erase(GetId());
|
||||
Utils->serverlist.erase(GetName());
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ class TreeServer : public Server
|
||||
std::string rawversion;
|
||||
|
||||
TreeSocket* Socket; /* Socket used to communicate with this server */
|
||||
std::string sid; /* Server ID */
|
||||
|
||||
/** Counter counting how many servers are bursting in front of this server, including
|
||||
* this server. Set to parents' value on construction then it is increased if the
|
||||
@ -75,7 +74,7 @@ class TreeServer : public Server
|
||||
|
||||
/** Used by SQuit logic to recursively remove servers
|
||||
*/
|
||||
void SQuitInternal(unsigned int& num_lost_servers);
|
||||
void SQuitInternal(unsigned int& num_lost_servers, bool error);
|
||||
|
||||
/** Remove the reference to this server from the hash maps
|
||||
*/
|
||||
@ -104,15 +103,17 @@ class TreeServer : public Server
|
||||
/** SQuit a server connected to this server, removing the given server and all servers behind it
|
||||
* @param server Server to squit, must be directly below this server
|
||||
* @param reason Reason for quitting the server, sent to opers and other servers
|
||||
* @param error Whether the server is being squit because of an error.
|
||||
*/
|
||||
void SQuitChild(TreeServer* server, const std::string& reason);
|
||||
void SQuitChild(TreeServer* server, const std::string& reason, bool error = false);
|
||||
|
||||
/** SQuit this server, removing this server and all servers behind it
|
||||
* @param reason Reason for quitting the server, sent to opers and other servers
|
||||
* @param error Whether the server is being squit because of an error.
|
||||
*/
|
||||
void SQuit(const std::string& reason)
|
||||
void SQuit(const std::string& reason, bool error = false)
|
||||
{
|
||||
GetParent()->SQuitChild(this, reason);
|
||||
GetParent()->SQuitChild(this, reason, error);
|
||||
}
|
||||
|
||||
static unsigned int QuitUsers(const std::string& reason);
|
||||
@ -194,10 +195,6 @@ class TreeServer : public Server
|
||||
*/
|
||||
const ChildServers& GetChildren() const { return Children; }
|
||||
|
||||
/** Get server ID
|
||||
*/
|
||||
const std::string& GetID() const { return sid; }
|
||||
|
||||
/** Marks a server as having finished bursting and performs appropriate actions.
|
||||
*/
|
||||
void FinishBurst();
|
||||
|
@ -415,7 +415,7 @@ void TreeSocket::Close()
|
||||
// If the connection is fully up (state CONNECTED)
|
||||
// then propogate a netsplit to all peers.
|
||||
if (MyRoot)
|
||||
MyRoot->SQuit(getError());
|
||||
MyRoot->SQuit(getError(), true);
|
||||
|
||||
ServerInstance->SNO.WriteGlobalSno('l', "Connection to '\002%s\002' failed.", linkID.c_str());
|
||||
|
||||
|
@ -38,7 +38,7 @@ CmdResult CommandUID::HandleServer(TreeServer* remoteserver, CommandBase::Params
|
||||
const std::string& modestr = params[8];
|
||||
|
||||
// Check if the length of the uuid is correct and confirm the sid portion of the uuid matches the sid of the server introducing the user
|
||||
if (params[0].length() != UIDGenerator::UUID_LENGTH || params[0].compare(0, 3, remoteserver->GetID()))
|
||||
if (params[0].length() != UIDGenerator::UUID_LENGTH || params[0].compare(0, 3, remoteserver->GetId()))
|
||||
throw ProtocolException("Bogus UUID");
|
||||
// Sanity check on mode string: must begin with '+'
|
||||
if (modestr[0] != '+')
|
||||
|
@ -49,7 +49,7 @@ class AuthQuery : public SQL::Query
|
||||
|
||||
void OnResult(SQL::Result& res) override
|
||||
{
|
||||
LocalUser* user = static_cast<LocalUser*>(ServerInstance->FindUUID(uid));
|
||||
LocalUser* user = IS_LOCAL(ServerInstance->FindUUID(uid));
|
||||
if (!user)
|
||||
return;
|
||||
|
||||
|
@ -23,12 +23,12 @@
|
||||
#include "inspircd.h"
|
||||
#include "listmode.h"
|
||||
|
||||
/** Holds a timed ban
|
||||
*/
|
||||
// Holds a timed ban
|
||||
class TimedBan
|
||||
{
|
||||
public:
|
||||
std::string mask;
|
||||
std::string setter;
|
||||
time_t expire;
|
||||
Channel* chan;
|
||||
};
|
||||
@ -36,8 +36,7 @@ class TimedBan
|
||||
typedef std::vector<TimedBan> timedbans;
|
||||
timedbans TimedBanList;
|
||||
|
||||
/** Handle /TBAN
|
||||
*/
|
||||
// Handle /TBAN
|
||||
class CommandTban : public Command
|
||||
{
|
||||
ChanModeReference banmode;
|
||||
@ -47,6 +46,7 @@ class CommandTban : public Command
|
||||
ListModeBase* banlm = static_cast<ListModeBase*>(*banmode);
|
||||
if (!banlm)
|
||||
return false;
|
||||
|
||||
const ListModeBase::ModeList* bans = banlm->GetList(chan);
|
||||
if (bans)
|
||||
{
|
||||
@ -62,7 +62,8 @@ class CommandTban : public Command
|
||||
}
|
||||
|
||||
public:
|
||||
CommandTban(Module* Creator) : Command(Creator,"TBAN", 3)
|
||||
CommandTban(Module* Creator)
|
||||
: Command(Creator,"TBAN", 3)
|
||||
, banmode(Creator, "ban")
|
||||
{
|
||||
syntax = "<channel> <duration> <banmask>";
|
||||
@ -76,6 +77,7 @@ class CommandTban : public Command
|
||||
user->WriteNumeric(Numerics::NoSuchChannel(parameters[0]));
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
unsigned int cm = channel->GetPrefixValue(user);
|
||||
if (cm < HALFOP_VALUE)
|
||||
{
|
||||
@ -91,6 +93,7 @@ class CommandTban : public Command
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
unsigned long expire = duration + ServerInstance->Time();
|
||||
|
||||
std::string mask = parameters[2];
|
||||
bool isextban = ((mask.size() > 2) && (mask[1] == ':'));
|
||||
if (!isextban && !InspIRCd::IsValidMask(mask))
|
||||
@ -114,18 +117,20 @@ class CommandTban : public Command
|
||||
}
|
||||
|
||||
T.mask = mask;
|
||||
T.setter = user->nick;
|
||||
T.expire = expire + (IS_REMOTE(user) ? 5 : 0);
|
||||
T.chan = channel;
|
||||
TimedBanList.push_back(T);
|
||||
|
||||
const std::string addban = user->nick + " added a timed ban on " + mask + " lasting for " + InspIRCd::DurationString(duration) + ".";
|
||||
const std::string message = InspIRCd::Format("Timed ban %s added by %s on %s lasting for %s.",
|
||||
mask.c_str(), user->nick.c_str(), channel->name.c_str(), InspIRCd::DurationString(duration).c_str());
|
||||
// If halfop is loaded, send notice to halfops and above, otherwise send to ops and above
|
||||
PrefixMode* mh = ServerInstance->Modes.FindPrefixMode('h');
|
||||
char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@';
|
||||
|
||||
ClientProtocol::Messages::Privmsg notice(ServerInstance->FakeClient, channel, addban, MSG_NOTICE);
|
||||
ClientProtocol::Messages::Privmsg notice(ServerInstance->FakeClient, channel, message, MSG_NOTICE);
|
||||
channel->Write(ServerInstance->GetRFCEvents().privmsg, notice, pfxchar);
|
||||
ServerInstance->PI->SendChannelNotice(channel, pfxchar, addban);
|
||||
ServerInstance->PI->SendChannelNotice(channel, pfxchar, message);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -207,22 +212,22 @@ class ModuleTimedBans : public Module
|
||||
|
||||
for (timedbans::iterator i = expired.begin(); i != expired.end(); i++)
|
||||
{
|
||||
std::string mask = i->mask;
|
||||
const std::string mask = i->mask;
|
||||
Channel* cr = i->chan;
|
||||
{
|
||||
const std::string expiry = "*** Timed ban on " + cr->name + " expired.";
|
||||
// If halfop is loaded, send notice to halfops and above, otherwise send to ops and above
|
||||
PrefixMode* mh = ServerInstance->Modes.FindPrefixMode('h');
|
||||
char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@';
|
||||
|
||||
ClientProtocol::Messages::Privmsg notice(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, cr, expiry, MSG_NOTICE);
|
||||
cr->Write(ServerInstance->GetRFCEvents().privmsg, notice, pfxchar);
|
||||
ServerInstance->PI->SendChannelNotice(cr, pfxchar, expiry);
|
||||
const std::string message = InspIRCd::Format("Timed ban %s set by %s on %s has expired.",
|
||||
mask.c_str(), i->setter.c_str(), cr->name.c_str());
|
||||
// If halfop is loaded, send notice to halfops and above, otherwise send to ops and above
|
||||
PrefixMode* mh = ServerInstance->Modes.FindPrefixMode('h');
|
||||
char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@';
|
||||
|
||||
Modes::ChangeList setban;
|
||||
setban.push_remove(ServerInstance->Modes.FindMode('b', MODETYPE_CHANNEL), mask);
|
||||
ServerInstance->Modes.Process(ServerInstance->FakeClient, cr, NULL, setban);
|
||||
}
|
||||
ClientProtocol::Messages::Privmsg notice(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, cr, message, MSG_NOTICE);
|
||||
cr->Write(ServerInstance->GetRFCEvents().privmsg, notice, pfxchar);
|
||||
ServerInstance->PI->SendChannelNotice(cr, pfxchar, message);
|
||||
|
||||
Modes::ChangeList setban;
|
||||
setban.push_remove(ServerInstance->Modes.FindMode('b', MODETYPE_CHANNEL), mask);
|
||||
ServerInstance->Modes.Process(ServerInstance->FakeClient, cr, NULL, setban);
|
||||
}
|
||||
}
|
||||
|
||||
|
282
src/serializable.cpp
Normal file
282
src/serializable.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* InspIRCd -- Internet Relay Chat Daemon
|
||||
*
|
||||
* Copyright (C) 2019 Peter Powell <petpow@saberuk.com>
|
||||
*
|
||||
* This file is part of InspIRCd. InspIRCd is free software: you can
|
||||
* redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "inspircd.h"
|
||||
|
||||
Serializable::Data& Serializable::Data::Load(const std::string& key, std::string& out)
|
||||
{
|
||||
EntryMap::iterator iter = this->entries.find(key);
|
||||
if (iter == this->entries.end())
|
||||
{
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Unable to load missing kv %s!", key.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
out = iter->second;
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Loaded kv %s: %s", key.c_str(), out.c_str());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Serializable::Data& Serializable::Data::Load(const std::string& key, Serializable::Data& out)
|
||||
{
|
||||
ChildMap::iterator iter = this->children.find(key);
|
||||
if (iter == this->children.end())
|
||||
{
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Unable to load missing data %s!", key.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
out = iter->second;
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Loaded data: %s", key.c_str());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Serializable::Data& Serializable::Data::Store(const std::string& key, const std::string& value)
|
||||
{
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Stored kv %s: %s", key.c_str(), value.c_str());
|
||||
this->entries[key] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Serializable::Data& Serializable::Data::Store(const std::string& key, const Serializable::Data& value)
|
||||
{
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Stored data: %s", key.c_str());
|
||||
this->children[key] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Extensible::Deserialize(Serializable::Data& data)
|
||||
{
|
||||
// If the extensible has been culled then it shouldn't be deserialized.
|
||||
if (culled)
|
||||
return false;
|
||||
|
||||
const Serializable::Data::EntryMap& entries = data.GetEntries();
|
||||
for (Serializable::Data::EntryMap::const_iterator iter = entries.begin(); iter != entries.end(); ++iter)
|
||||
{
|
||||
const std::string& name = iter->first;
|
||||
ExtensionItem* item = ServerInstance->Extensions.GetItem(name);
|
||||
if (item)
|
||||
{
|
||||
item->FromInternal(this, iter->second);
|
||||
continue;
|
||||
}
|
||||
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Tried to deserialize the %s extension item but it doesn't exist",
|
||||
name.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Extensible::Serialize(Serializable::Data& data)
|
||||
{
|
||||
// If the extensible has been culled then it shouldn't be serialized.
|
||||
if (culled)
|
||||
{
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Tried to serialize an extensible which has been culled");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Extensible::ExtensibleStore::const_iterator iter = extensions.begin(); iter != extensions.end(); ++iter)
|
||||
{
|
||||
ExtensionItem* item = iter->first;
|
||||
const std::string value = item->ToInternal(this, iter->second);
|
||||
if (!value.empty())
|
||||
data.Store(item->name, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool User::Deserialize(Serializable::Data& data)
|
||||
{
|
||||
// If the user is quitting they shouldn't be deserialized.
|
||||
if (quitting)
|
||||
{
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Tried to deserialize %s who is in the process of quitting",
|
||||
uuid.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check we're actually deserialising data for this user.
|
||||
std::string client_uuid;
|
||||
data.Load("uuid", client_uuid);
|
||||
if (!client_uuid.empty() && client_uuid != uuid)
|
||||
{
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Tried to deserialize %s into %s",
|
||||
client_uuid.c_str(), uuid.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deserialize the extensions first.
|
||||
Serializable::Data exts;
|
||||
data.Load("extensions", exts);
|
||||
if (!Extensible::Deserialize(exts))
|
||||
return false;
|
||||
|
||||
long client_port;
|
||||
std::string client_addr;
|
||||
std::string user_modes;
|
||||
std::string user_oper;
|
||||
std::string user_snomasks;
|
||||
|
||||
// Apply the members which can be applied directly.
|
||||
data.Load("age", age)
|
||||
.Load("awaymsg", awaymsg)
|
||||
.Load("awaytime", awaytime)
|
||||
.Load("client_sa.addr", client_addr)
|
||||
.Load("client_sa.port", client_port)
|
||||
.Load("displayhost", displayhost)
|
||||
.Load("ident", ident)
|
||||
.Load("modes", user_modes)
|
||||
.Load("nick", nick)
|
||||
.Load("oper", user_oper)
|
||||
.Load("realhost", realhost)
|
||||
.Load("realname", realname)
|
||||
.Load("signon", signon)
|
||||
.Load("snomasks", user_snomasks);
|
||||
|
||||
// Apply the rest of the members.
|
||||
modes = std::bitset<ModeParser::MODEID_MAX>(user_modes);
|
||||
snomasks = std::bitset<64>(user_snomasks);
|
||||
|
||||
ServerConfig::OperIndex::const_iterator iter = ServerInstance->Config->OperTypes.find(user_oper);
|
||||
if (iter != ServerInstance->Config->OperTypes.end())
|
||||
oper = iter->second;
|
||||
else
|
||||
oper = new OperInfo(user_oper);
|
||||
|
||||
irc::sockets::sockaddrs sa;
|
||||
if (irc::sockets::aptosa(client_addr, client_port, sa) || irc::sockets::untosa(client_addr, sa))
|
||||
client_sa = sa;
|
||||
|
||||
InvalidateCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool User::Serialize(Serializable::Data& data)
|
||||
{
|
||||
// If the user is quitting they shouldn't be serialized.
|
||||
if (quitting)
|
||||
{
|
||||
ServerInstance->Logs.Log("SERIALIZE", LOG_DEBUG, "Tried to serialize %s who is in the process of quitting",
|
||||
uuid.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the user is unregistered they shouldn't be serialised.
|
||||
if (registered != REG_ALL)
|
||||
return false;
|
||||
|
||||
// Serialize the extensions first.
|
||||
Serializable::Data exts;
|
||||
if (!Extensible::Serialize(exts))
|
||||
return false;
|
||||
data.Store("extensions", exts);
|
||||
|
||||
// The following member variables not checked above are not serialised:
|
||||
// * cached_fullhost (serialising cache variables is unnecessary)
|
||||
// * cached_fullrealhost (serialising cache variables is unnecessary)
|
||||
// * cached_hostip (serialising cache variables is unnecessary)
|
||||
// * cached_makehost (serialising cache variables is unnecessary)
|
||||
// * cachedip (serialising cache variables is unnecessary)
|
||||
// * server (specific to the origin server)
|
||||
// * usertype (can't be networked reliably)
|
||||
data.Store("age", age)
|
||||
.Store("awaymsg", awaymsg)
|
||||
.Store("awaytime", awaytime)
|
||||
.Store("client_sa.addr", client_sa.addr())
|
||||
.Store("client_sa.port", client_sa.port())
|
||||
.Store("displayhost", displayhost)
|
||||
.Store("ident", ident)
|
||||
.Store("modes", modes.to_string())
|
||||
.Store("nick", nick)
|
||||
.Store("oper", oper ? oper->name : "")
|
||||
.Store("realhost", realhost)
|
||||
.Store("realname", realname)
|
||||
.Store("signon", signon)
|
||||
.Store("snomasks", snomasks.to_string())
|
||||
.Store("uuid", uuid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalUser::Deserialize(Serializable::Data& data)
|
||||
{
|
||||
|
||||
// Deserialize the base class first.
|
||||
if (!User::Deserialize(data))
|
||||
return false;
|
||||
|
||||
bool user_exempt;
|
||||
bool user_lastping;
|
||||
long server_port;
|
||||
std::string server_addr;
|
||||
|
||||
// Apply the members which can be applied directly.
|
||||
data.Load("bytes_in", bytes_in)
|
||||
.Load("bytes_out", bytes_out)
|
||||
.Load("cmds_in", cmds_in)
|
||||
.Load("cmds_out", cmds_out)
|
||||
.Load("CommandFloodPenalty", CommandFloodPenalty)
|
||||
.Load("exempt", user_exempt)
|
||||
.Load("idle_lastmsg", idle_lastmsg)
|
||||
.Load("lastping", user_lastping)
|
||||
.Load("nextping", nextping)
|
||||
.Load("password", password)
|
||||
.Load("server_sa.addr", server_addr)
|
||||
.Load("server_sa.port", server_port);
|
||||
|
||||
// Apply the rest of the members.
|
||||
irc::sockets::sockaddrs sa;
|
||||
if (irc::sockets::aptosa(server_addr, server_port, sa) || irc::sockets::untosa(server_addr, sa))
|
||||
server_sa = sa;
|
||||
|
||||
// These are bitfields so we need to ensure they only get the appropriate bits.
|
||||
exempt = user_exempt ? 1 : 0;
|
||||
lastping = user_lastping ? 1 : 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalUser::Serialize(Serializable::Data& data)
|
||||
{
|
||||
// Serialize the base class first.
|
||||
if (!User::Serialize(data))
|
||||
return false;
|
||||
|
||||
// The following member variables not checked above are not serialised:
|
||||
// * already_sent (can't be networked reliably)
|
||||
// * eh (shouldn't be networked)
|
||||
// * MyClass (might not be the same on a different server)
|
||||
// * serializer (might not be the same on a different connection)
|
||||
data.Store("bytes_in", bytes_in)
|
||||
.Store("bytes_out", bytes_out)
|
||||
.Store("cmds_in", cmds_in)
|
||||
.Store("cmds_out", cmds_out)
|
||||
.Store("CommandFloodPenalty", CommandFloodPenalty)
|
||||
.Store("exempt", exempt)
|
||||
.Store("idle_lastmsg", idle_lastmsg)
|
||||
.Store("lastping", lastping)
|
||||
.Store("nextping", nextping)
|
||||
.Store("password", password)
|
||||
.Store("server_sa.addr", server_sa.addr())
|
||||
.Store("server_sa.port", server_sa.port());
|
||||
return true;
|
||||
}
|
@ -200,7 +200,6 @@ void ISupportManager::Build()
|
||||
tokens["STATUSMSG"] = ServerInstance->Modes.BuildPrefixes(false);
|
||||
tokens["TOPICLEN"] = ConvToStr(ServerInstance->Config->Limits.MaxTopic);
|
||||
tokens["USERLEN"] = ConvToStr(ServerInstance->Config->Limits.IdentMax);
|
||||
tokens["VBANLIST"];
|
||||
|
||||
// Modules can add new tokens and also edit or remove existing tokens
|
||||
FOREACH_MOD(On005Numeric, (tokens));
|
||||
|
@ -40,10 +40,10 @@ namespace
|
||||
*/
|
||||
std::vector<struct kevent> changelist(8);
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#if defined __NetBSD__ && __NetBSD_Version__ <= 999001400
|
||||
inline intptr_t udata_cast(EventHandler* eh)
|
||||
{
|
||||
// On NetBSD the last parameter of EV_SET is intptr_t.
|
||||
// On NetBSD <10 the last parameter of EV_SET is intptr_t.
|
||||
return reinterpret_cast<intptr_t>(eh);
|
||||
}
|
||||
#else
|
||||
|
@ -112,6 +112,15 @@ LocalUser::LocalUser(int myfd, irc::sockets::sockaddrs* client, irc::sockets::so
|
||||
ChangeRealHost(GetIPString(), true);
|
||||
}
|
||||
|
||||
LocalUser::LocalUser(int myfd, const std::string& uid, Serializable::Data& data)
|
||||
: User(uid, ServerInstance->FakeClient->server, USERTYPE_LOCAL)
|
||||
, eh(this)
|
||||
, already_sent(0)
|
||||
{
|
||||
eh.SetFd(myfd);
|
||||
Deserialize(data);
|
||||
}
|
||||
|
||||
User::~User()
|
||||
{
|
||||
}
|
||||
@ -749,17 +758,16 @@ void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa)
|
||||
return;
|
||||
|
||||
ServerInstance->Users.RemoveCloneCounts(this);
|
||||
|
||||
User::SetClientIP(sa);
|
||||
|
||||
FOREACH_MOD(OnSetUserIP, (this));
|
||||
|
||||
ServerInstance->Users.AddClone(this);
|
||||
|
||||
// Recheck the connect class.
|
||||
this->MyClass = NULL;
|
||||
this->SetClass();
|
||||
this->CheckClass();
|
||||
|
||||
if (!quitting)
|
||||
FOREACH_MOD(OnSetUserIP, (this));
|
||||
}
|
||||
|
||||
void LocalUser::Write(const ClientProtocol::SerializedMessage& text)
|
||||
@ -1189,10 +1197,24 @@ const std::string& FakeUser::GetFullRealHost()
|
||||
}
|
||||
|
||||
ConnectClass::ConnectClass(ConfigTag* tag, char t, const std::string& mask)
|
||||
: config(tag), type(t), fakelag(true), name("unnamed"), registration_timeout(0), host(mask),
|
||||
pingtime(0), softsendqmax(0), hardsendqmax(0), recvqmax(0),
|
||||
penaltythreshold(0), commandrate(0), maxlocal(0), maxglobal(0), maxconnwarn(true), maxchans(20),
|
||||
limit(0), resolvehostnames(true)
|
||||
: config(tag)
|
||||
, type(t)
|
||||
, fakelag(true)
|
||||
, name("unnamed")
|
||||
, registration_timeout(0)
|
||||
, host(mask)
|
||||
, pingtime(0)
|
||||
, softsendqmax(0)
|
||||
, hardsendqmax(0)
|
||||
, recvqmax(0)
|
||||
, penaltythreshold(0)
|
||||
, commandrate(0)
|
||||
, maxlocal(0)
|
||||
, maxglobal(0)
|
||||
, maxconnwarn(true)
|
||||
, maxchans(20)
|
||||
, limit(0)
|
||||
, resolvehostnames(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user