summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/conf/modules.conf.example22
-rw-r--r--include/base.h15
-rw-r--r--include/modules.h10
-rw-r--r--include/socket.h2
-rw-r--r--include/users.h6
-rw-r--r--src/commands/cmd_notice.cpp9
-rw-r--r--src/configreader.cpp12
-rw-r--r--src/modules.cpp1
-rw-r--r--src/modules/extra/m_mysql.cpp2
-rw-r--r--src/modules/extra/m_regex_stdlib.cpp112
-rw-r--r--src/modules/m_blockamsg.cpp6
-rw-r--r--src/modules/m_cgiirc.cpp61
-rw-r--r--src/modules/m_dnsbl.cpp6
-rw-r--r--src/modules/m_knock.cpp32
-rw-r--r--src/modules/m_shun.cpp1
-rw-r--r--src/modules/m_sslinfo.cpp4
-rw-r--r--src/socket.cpp1
-rw-r--r--src/socketengine.cpp7
-rw-r--r--src/usermanager.cpp6
-rw-r--r--src/users.cpp42
20 files changed, 294 insertions, 63 deletions
diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example
index 76563fbeb..ea0431499 100644
--- a/docs/conf/modules.conf.example
+++ b/docs/conf/modules.conf.example
@@ -943,6 +943,14 @@
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Knock module: adds the /KNOCK command and +K channel mode
#<module name="m_knock.so">
+# This setting specifes what to do when someone successfully /KNOCKs.
+# If set to "notice", then a NOTICE will be sent to the channel.
+# This is the default and the compatible setting, as it requires no
+# special support from the clients.
+# If set to "numeric" then a 710 numeric will be sent to the channel.
+# This allows easier scripting but not all clients support it.
+# If set to "both" then (surprise!) both will be sent.
+#<knock notify="notice">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# LDAP authentication module: Adds the ability to authenticate users #
@@ -1381,6 +1389,20 @@
#<module name="m_regex_posix.so">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
+# Regular Expression Provider for C++11 std::regex Regular Expressions.
+# This module works on any fully compliant implementation of the C++11
+# std::regex container. Examples for such are Visual C++ 2010 and newer
+# but not libstdc++ (which GCC uses)
+# You should verify that std::regex is supported by your setup before
+# using this module, as it may compile normally but won't do anything
+# on some implementations.
+#<module name="m_regex_stdlib.so">
+
+# Specify the Regular Expression engine to use here. Valid settings are
+# bre, ere, awk, grep, egrep, ecmascript (default if not specified)
+#<stdregex type="ecmascript">
+
+#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Regular Expression Provider for TRE Regular Expressions.
# This is the same regular expression engine used by UnrealIRCd, so
# if you are most familiar with the syntax of /spamfilter from there,
diff --git a/include/base.h b/include/base.h
index 45c60802c..230ed1db4 100644
--- a/include/base.h
+++ b/include/base.h
@@ -142,6 +142,21 @@ class CoreExport reference
if (value && value->refcount_dec())
delete value;
}
+
+ inline reference<T>& operator=(T* other)
+ {
+ if (value != other)
+ {
+ if (value && value->refcount_dec())
+ delete value;
+ value = other;
+ if (value)
+ value->refcount_inc();
+ }
+
+ return *this;
+ }
+
inline operator bool() const { return value; }
inline operator T*() const { return value; }
inline T* operator->() const { return value; }
diff --git a/include/modules.h b/include/modules.h
index 49c16ae61..281da2705 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -116,7 +116,7 @@ struct ModResult {
* and numerical comparisons in preprocessor macros if they wish to support
* multiple versions of InspIRCd in one file.
*/
-#define INSPIRCD_VERSION_API 1
+#define INSPIRCD_VERSION_API 2
/**
* This #define allows us to call a method in all
@@ -338,7 +338,7 @@ enum Implementation
I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnPostCommand, I_OnPostJoin,
I_OnWhoisLine, I_OnBuildNeighborList, I_OnGarbageCollect, I_OnSetConnectClass,
I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO,
- I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent,
+ I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_OnSetUserIP,
I_END
};
@@ -1288,6 +1288,12 @@ class CoreExport Module : public classbase, public usecountbase
* @param line The raw line to send; modifiable, if empty no line will be returned.
*/
virtual void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line);
+
+ /** Called whenever a local user's IP is set for the first time, or when a local user's IP changes due to
+ * a module like m_cgiirc changing it.
+ * @param user The user whose IP is being set
+ */
+ virtual void OnSetUserIP(LocalUser* user);
};
diff --git a/include/socket.h b/include/socket.h
index 16809c3f8..e868af93e 100644
--- a/include/socket.h
+++ b/include/socket.h
@@ -146,7 +146,7 @@ namespace irc
class CoreExport ListenSocket : public EventHandler
{
public:
- const reference<ConfigTag> bind_tag;
+ reference<ConfigTag> bind_tag;
std::string bind_addr;
int bind_port;
/** Human-readable bind description */
diff --git a/include/users.h b/include/users.h
index 57dea3fa5..5a8864cdd 100644
--- a/include/users.h
+++ b/include/users.h
@@ -395,6 +395,8 @@ class CoreExport User : public Extensible
*/
bool SetClientIP(const char* sip);
+ void SetClientIP(const irc::sockets::sockaddrs& sa);
+
/** Constructor
* @throw CoreException if the UID allocated to the user already exists
*/
@@ -819,6 +821,10 @@ class CoreExport LocalUser : public User, public InviteBase
*/
void SetClass(const std::string &explicit_name = "");
+ bool SetClientIP(const char* sip);
+
+ void SetClientIP(const irc::sockets::sockaddrs& sa);
+
void SendText(const std::string& line);
void Write(const std::string& text);
void Write(const char*, ...) CUSTOM_PRINTF(2, 3);
diff --git a/src/commands/cmd_notice.cpp b/src/commands/cmd_notice.cpp
index e10d6286d..b060a534f 100644
--- a/src/commands/cmd_notice.cpp
+++ b/src/commands/cmd_notice.cpp
@@ -110,6 +110,15 @@ CmdResult CommandNotice::Handle (const std::vector<std::string>& parameters, Use
user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
return CMD_FAILURE;
}
+
+ if (ServerInstance->Config->RestrictBannedUsers)
+ {
+ if (chan->IsBanned(user))
+ {
+ user->WriteNumeric(404, "%s %s :Cannot send to channel (you're banned)", user->nick.c_str(), chan->name.c_str());
+ return CMD_FAILURE;
+ }
+ }
}
ModResult MOD_RESULT;
diff --git a/src/configreader.cpp b/src/configreader.cpp
index b8796430b..37742cc9f 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -657,10 +657,14 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
for (int Index = 0; Index * sizeof(Deprecated) < sizeof(ChangedConfig); Index++)
{
std::string dummy;
- if (ConfValue(ChangedConfig[Index].tag)->readString(ChangedConfig[Index].value, dummy, true))
- errstr << "Your configuration contains a deprecated value: <"
- << ChangedConfig[Index].tag << ":" << ChangedConfig[Index].value << "> - " << ChangedConfig[Index].reason
- << " (at " << ConfValue(ChangedConfig[Index].tag)->getTagLocation() << ")\n";
+ ConfigTagList tags = ConfTags(ChangedConfig[Index].tag);
+ for(ConfigIter i = tags.first; i != tags.second; ++i)
+ {
+ if (i->second->readString(ChangedConfig[Index].value, dummy, true))
+ errstr << "Your configuration contains a deprecated value: <"
+ << ChangedConfig[Index].tag << ":" << ChangedConfig[Index].value << "> - " << ChangedConfig[Index].reason
+ << " (at " << i->second->getTagLocation() << ")\n";
+ }
}
Fill();
diff --git a/src/modules.cpp b/src/modules.cpp
index ccd78a8f0..075bbf85b 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -176,6 +176,7 @@ ModResult Module::OnNumeric(User*, unsigned int, const std::string&) { return MO
void Module::OnHookIO(StreamSocket*, ListenSocket*) { }
ModResult Module::OnAcceptConnection(int, ListenSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { return MOD_RES_PASSTHRU; }
void Module::OnSendWhoLine(User*, const std::vector<std::string>&, User*, std::string&) { }
+void Module::OnSetUserIP(LocalUser*) { }
ModuleManager::ModuleManager() : ModCount(0)
{
diff --git a/src/modules/extra/m_mysql.cpp b/src/modules/extra/m_mysql.cpp
index 86d9273c3..570e7d9ec 100644
--- a/src/modules/extra/m_mysql.cpp
+++ b/src/modules/extra/m_mysql.cpp
@@ -503,7 +503,7 @@ void DispatcherThread::Run()
*/
this->LockQueue();
- if (Parent->qq.front().q == i.q)
+ if (!Parent->qq.empty() && Parent->qq.front().q == i.q)
{
Parent->qq.pop_front();
Parent->rq.push_back(RQueueItem(i.q, res));
diff --git a/src/modules/extra/m_regex_stdlib.cpp b/src/modules/extra/m_regex_stdlib.cpp
new file mode 100644
index 000000000..4942e9739
--- /dev/null
+++ b/src/modules/extra/m_regex_stdlib.cpp
@@ -0,0 +1,112 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2012 ChrisTX <chris@rev-crew.info>
+ *
+ * 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"
+#include "m_regex.h"
+#include <regex>
+
+/* $ModDesc: Regex Provider Module for std::regex Regular Expressions */
+/* $ModConfig: <stdregex type="ecmascript">
+ * Specify the Regular Expression engine to use here. Valid settings are
+ * bre, ere, awk, grep, egrep, ecmascript (default if not specified)*/
+/* $CompileFlags: -std=c++11 */
+/* $ModDep: m_regex.h */
+
+class StdRegexException : public ModuleException
+{
+public:
+ StdRegexException(const std::string& rx, const std::string& error)
+ : ModuleException(std::string("Error in regex ") + rx + ": " + error)
+ {
+ }
+};
+
+class StdRegex : public Regex
+{
+private:
+ std::regex regexcl;
+public:
+ StdRegex(const std::string& rx, std::regex::flag_type fltype) : Regex(rx)
+ {
+ try{
+ regexcl.assign(rx, fltype | std::regex::optimize);
+ }
+ catch(std::regex_error rxerr)
+ {
+ throw StdRegexException(rx, rxerr.what());
+ }
+ }
+
+ virtual bool Matches(const std::string& text)
+ {
+ return std::regex_search(text, regexcl);
+ }
+};
+
+class StdRegexFactory : public RegexFactory
+{
+ public:
+ std::regex::flag_type regextype;
+ StdRegexFactory(Module* m) : RegexFactory(m, "regex/stdregex") {}
+ Regex* Create(const std::string& expr)
+ {
+ return new StdRegex(expr, regextype);
+ }
+};
+
+class ModuleRegexStd : public Module
+{
+public:
+ StdRegexFactory ref;
+ ModuleRegexStd() : ref(this) {
+ ServerInstance->Modules->AddService(ref);
+ Implementation eventlist[] = { I_OnRehash };
+ ServerInstance->Modules->Attach(eventlist, this, 1);
+ OnRehash(NULL);
+ }
+
+ Version GetVersion()
+ {
+ return Version("Regex Provider Module for std::regex", VF_VENDOR);
+ }
+
+ void OnRehash(User* u)
+ {
+ ConfigTag* Conf = ServerInstance->Config->ConfValue("stdregex");
+ std::string regextype = Conf->getString("type", "ecmascript");
+
+ if(regextype == "bre")
+ ref.regextype = std::regex::basic;
+ else if(regextype == "ere")
+ ref.regextype = std::regex::extended;
+ else if(regextype == "awk")
+ ref.regextype = std::regex::awk;
+ else if(regextype == "grep")
+ ref.regextype = std::regex::grep;
+ else if(regextype == "egrep")
+ ref.regextype = std::regex::egrep;
+ else
+ {
+ if(regextype != "ecmascript")
+ ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Non-existent regex engine '%s' specified. Falling back to ECMAScript.", regextype.c_str());
+ ref.regextype = std::regex::ECMAScript;
+ }
+ }
+};
+
+MODULE_INIT(ModuleRegexStd)
diff --git a/src/modules/m_blockamsg.cpp b/src/modules/m_blockamsg.cpp
index 8160fcf54..c570e0a71 100644
--- a/src/modules/m_blockamsg.cpp
+++ b/src/modules/m_blockamsg.cpp
@@ -102,11 +102,7 @@ class ModuleBlockAmsg : public Module
if (user->registered != REG_ALL)
return MOD_RES_PASSTHRU;
- // We want case insensitive command comparison.
- // Add std::string contructor for irc::string :x
- irc::string cmd = command.c_str();
-
- if(validated && (cmd == "PRIVMSG" || cmd == "NOTICE") && (parameters.size() >= 2))
+ if ((validated) && (parameters.size() >= 2) && ((command == "PRIVMSG") || (command == "NOTICE")))
{
// parameters[0] should have the target(s) in it.
// I think it will be faster to first check if there are any commas, and if there are then try and parse it out.
diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp
index 330c1b6c4..f47dc4b53 100644
--- a/src/modules/m_cgiirc.cpp
+++ b/src/modules/m_cgiirc.cpp
@@ -181,16 +181,10 @@ public:
ServerInstance->Extensions.Register(&cmd.realip);
ServerInstance->Extensions.Register(&cmd.webirc_hostname);
ServerInstance->Extensions.Register(&cmd.webirc_ip);
+ ServerInstance->Extensions.Register(&waiting);
- Implementation eventlist[] = { I_OnRehash, I_OnUserRegister, I_OnCheckReady, I_OnUserConnect };
- ServerInstance->Modules->Attach(eventlist, this, 4);
- }
-
- void Prioritize()
- {
- ServerInstance->Modules->SetPriority(this, I_OnUserConnect, PRIORITY_FIRST);
- Module* umodes = ServerInstance->Modules->Find("m_conn_umodes.so");
- ServerInstance->Modules->SetPriority(this, I_OnUserConnect, PRIORITY_BEFORE, &umodes);
+ Implementation eventlist[] = { I_OnRehash, I_OnUserRegister, I_OnCheckReady };
+ ServerInstance->Modules->Attach(eventlist, this, 3);
}
void OnRehash(User* user)
@@ -245,6 +239,32 @@ public:
{
if (waiting.get(user))
return MOD_RES_DENY;
+
+ std::string *webirc_ip = cmd.webirc_ip.get(user);
+ if (!webirc_ip)
+ return MOD_RES_PASSTHRU;
+
+ ServerInstance->Users->RemoveCloneCounts(user);
+ user->SetClientIP(webirc_ip->c_str());
+ cmd.webirc_ip.unset(user);
+
+ std::string* webirc_hostname = cmd.webirc_hostname.get(user);
+ if (webirc_hostname && webirc_hostname->length() < 64)
+ user->host = user->dhost = *webirc_hostname;
+ else
+ user->host = user->dhost = user->GetIPString();
+
+ user->InvalidateCache();
+ cmd.webirc_hostname.unset(user);
+
+ ServerInstance->Users->AddLocalClone(user);
+ ServerInstance->Users->AddGlobalClone(user);
+ user->SetClass();
+ user->CheckClass();
+ user->CheckLines(true);
+ if (user->quitting)
+ return MOD_RES_DENY;
+
return MOD_RES_PASSTHRU;
}
@@ -287,29 +307,6 @@ public:
return MOD_RES_PASSTHRU;
}
- virtual void OnUserConnect(LocalUser* user)
- {
- std::string *webirc_hostname = cmd.webirc_hostname.get(user);
- std::string *webirc_ip = cmd.webirc_ip.get(user);
- if (!webirc_ip)
- return;
- ServerInstance->Users->RemoveCloneCounts(user);
- user->SetClientIP(webirc_ip->c_str());
- user->InvalidateCache();
- if (webirc_hostname && webirc_hostname->length() < 64)
- user->host = user->dhost = *webirc_hostname;
- else
- user->host = user->dhost = user->GetIPString();
- user->InvalidateCache();
- ServerInstance->Users->AddLocalClone(user);
- ServerInstance->Users->AddGlobalClone(user);
- user->SetClass();
- user->CheckClass();
- user->CheckLines(true);
- cmd.webirc_ip.unset(user);
- cmd.webirc_hostname.unset(user);
- }
-
bool CheckPass(LocalUser* user)
{
if(IsValidHost(user->password))
diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp
index 2160b02dc..645949006 100644
--- a/src/modules/m_dnsbl.cpp
+++ b/src/modules/m_dnsbl.cpp
@@ -185,7 +185,7 @@ class DNSBLResolver : public Resolver
break;
}
- ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as being on a DNS blacklist (%s) with result %d", them->GetFullRealHost().c_str(), ConfEntry->domain.c_str(), (ConfEntry->type==DNSBLConfEntry::A_BITMASK) ? bitmask : record);
+ ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s%s detected as being on a DNS blacklist (%s) with result %d", them->nick.empty() ? "<unknown>" : "", them->GetFullRealHost().c_str(), ConfEntry->domain.c_str(), (ConfEntry->type==DNSBLConfEntry::A_BITMASK) ? bitmask : record);
}
else
ConfEntry->stats_misses++;
@@ -243,7 +243,7 @@ class ModuleDNSBL : public Module
ReadConf();
ServerInstance->Modules->AddService(nameExt);
ServerInstance->Modules->AddService(countExt);
- Implementation eventlist[] = { I_OnRehash, I_OnUserInit, I_OnStats, I_OnSetConnectClass, I_OnCheckReady };
+ Implementation eventlist[] = { I_OnRehash, I_OnSetUserIP, I_OnStats, I_OnSetConnectClass, I_OnCheckReady };
ServerInstance->Modules->Attach(eventlist, this, 5);
}
@@ -348,7 +348,7 @@ class ModuleDNSBL : public Module
ReadConf();
}
- void OnUserInit(LocalUser* user)
+ void OnSetUserIP(LocalUser* user)
{
if (user->exempt)
return;
diff --git a/src/modules/m_knock.cpp b/src/modules/m_knock.cpp
index 8cd5088bc..97eb0e005 100644
--- a/src/modules/m_knock.cpp
+++ b/src/modules/m_knock.cpp
@@ -28,6 +28,8 @@
class CommandKnock : public Command
{
public:
+ bool sendnotice;
+ bool sendnumeric;
CommandKnock(Module* Creator) : Command(Creator,"KNOCK", 2, 2)
{
syntax = "<channel> <reason>";
@@ -62,7 +64,12 @@ class CommandKnock : public Command
return CMD_FAILURE;
}
- c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :User %s is KNOCKing on %s (%s)", c->name.c_str(), user->nick.c_str(), c->name.c_str(), parameters[1].c_str());
+ if (sendnotice)
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :User %s is KNOCKing on %s (%s)", c->name.c_str(), user->nick.c_str(), c->name.c_str(), parameters[1].c_str());
+
+ if (sendnumeric)
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "710 %s %s %s :is KNOCKing: %s", c->name.c_str(), c->name.c_str(), user->GetFullHost().c_str(), parameters[1].c_str());
+
user->WriteServ("NOTICE %s :KNOCKing on %s", user->nick.c_str(), c->name.c_str());
return CMD_SUCCESS;
}
@@ -92,11 +99,30 @@ class ModuleKnock : public Module
throw ModuleException("Could not add new modes!");
ServerInstance->AddCommand(&cmd);
+ ServerInstance->Modules->Attach(I_OnRehash, this);
+ OnRehash(NULL);
}
-
- virtual ~ModuleKnock()
+ void OnRehash(User* user)
{
+ std::string knocknotify = ServerInstance->Config->ConfValue("knock")->getString("notify");
+ irc::string notify(knocknotify.c_str());
+
+ if (notify == "numeric")
+ {
+ cmd.sendnotice = false;
+ cmd.sendnumeric = true;
+ }
+ else if (notify == "both")
+ {
+ cmd.sendnotice = true;
+ cmd.sendnumeric = true;
+ }
+ else
+ {
+ cmd.sendnotice = true;
+ cmd.sendnumeric = false;
+ }
}
virtual Version GetVersion()
diff --git a/src/modules/m_shun.cpp b/src/modules/m_shun.cpp
index 197bbc1bf..78046954c 100644
--- a/src/modules/m_shun.cpp
+++ b/src/modules/m_shun.cpp
@@ -215,6 +215,7 @@ class ModuleShun : public Module
{
ConfigReader MyConf;
std::string cmds = MyConf.ReadValue("shun", "enabledcommands", 0);
+ std::transform(cmds.begin(), cmds.end(), cmds.begin(), ::toupper);
if (cmds.empty())
cmds = "PING PONG QUIT";
diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp
index 22be27383..33a36d3b4 100644
--- a/src/modules/m_sslinfo.cpp
+++ b/src/modules/m_sslinfo.cpp
@@ -174,9 +174,7 @@ class ModuleSSLInfo : public Module
ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line)
{
- irc::string pcmd = command.c_str();
-
- if ((pcmd == "OPER") && (validated))
+ if ((command == "OPER") && (validated))
{
OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]);
if (i != ServerInstance->Config->oper_blocks.end())
diff --git a/src/socket.cpp b/src/socket.cpp
index 98ff3e00c..8c7ec97d8 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -105,6 +105,7 @@ int InspIRCd::BindPorts(FailedPortList &failed_ports)
{
if ((**n).bind_desc == bind_readable)
{
+ (*n)->bind_tag = tag; // Replace tag, we know addr and port match, but other info (type, ssl) may not
skip = true;
old_ports.erase(n);
break;
diff --git a/src/socketengine.cpp b/src/socketengine.cpp
index 72075dd49..ccaa71aed 100644
--- a/src/socketengine.cpp
+++ b/src/socketengine.cpp
@@ -208,7 +208,12 @@ int SocketEngine::SendTo(EventHandler* fd, const void *buf, size_t len, int flag
int SocketEngine::Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen)
{
- return connect(fd->GetFd(), serv_addr, addrlen);
+ int ret = connect(fd->GetFd(), serv_addr, addrlen);
+#ifdef WINDOWS
+ if ((ret == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
+ errno = EINPROGRESS;
+#endif
+ return ret;
}
int SocketEngine::Shutdown(EventHandler* fd, int how)
diff --git a/src/usermanager.cpp b/src/usermanager.cpp
index 785d23625..d65f47128 100644
--- a/src/usermanager.cpp
+++ b/src/usermanager.cpp
@@ -66,16 +66,10 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
New->nick.assign(New->uuid, 0, ServerInstance->Config->Limits.NickMax);
(*(this->clientlist))[New->nick] = New;
- New->ident.assign("unknown");
-
New->registered = REG_NONE;
New->signon = ServerInstance->Time() + ServerInstance->Config->dns_timeout;
New->lastping = 1;
- /* Smarter than your average bear^H^H^H^Hset of strlcpys. */
- New->dhost.assign(New->GetIPString(), 0, 64);
- New->host.assign(New->GetIPString(), 0, 64);
-
ServerInstance->Users->AddLocalClone(New);
ServerInstance->Users->AddGlobalClone(New);
diff --git a/src/users.cpp b/src/users.cpp
index 6e282f7c0..f211f6b49 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -222,10 +222,22 @@ LocalUser::LocalUser(int myfd, irc::sockets::sockaddrs* client, irc::sockets::so
bytes_in(0), bytes_out(0), cmds_in(0), cmds_out(0), nping(0), CommandFloodPenalty(0),
already_sent(0)
{
+ ident = "unknown";
lastping = 0;
eh.SetFd(myfd);
- memcpy(&client_sa, client, sizeof(irc::sockets::sockaddrs));
memcpy(&server_sa, servaddr, sizeof(irc::sockets::sockaddrs));
+
+ /*
+ * Initialize host and dhost here to the user's IP.
+ * It is important to do this before calling SetClientIP()
+ * as that can pass execution to modules that expect these
+ * fields to be valid.
+ */
+
+ int port;
+ irc::sockets::satoap(*client, host, port);
+ dhost = host;
+ SetClientIP(*client);
}
User::~User()
@@ -980,10 +992,36 @@ irc::sockets::cidr_mask User::GetCIDRMask()
bool User::SetClientIP(const char* sip)
{
- this->cachedip = "";
+ cachedip.clear();
return irc::sockets::aptosa(sip, 0, client_sa);
}
+void User::SetClientIP(const irc::sockets::sockaddrs& sa)
+{
+ cachedip.clear();
+ memcpy(&client_sa, &sa, sizeof(irc::sockets::sockaddrs));
+}
+
+bool LocalUser::SetClientIP(const char* sip)
+{
+ irc::sockets::sockaddrs sa;
+ if (!irc::sockets::aptosa(sip, 0, sa))
+ // Invalid
+ return false;
+
+ LocalUser::SetClientIP(sa);
+ return true;
+}
+
+void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa)
+{
+ if (sa != client_sa)
+ {
+ User::SetClientIP(sa);
+ FOREACH_MOD(I_OnSetUserIP,OnSetUserIP(this));
+ }
+}
+
static std::string wide_newline("\r\n");
void User::Write(const std::string& text)