summaryrefslogtreecommitdiff
path: root/src/modules/m_spanningtree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/m_spanningtree.cpp')
-rw-r--r--src/modules/m_spanningtree.cpp58
1 files changed, 46 insertions, 12 deletions
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp
index 55b1ebf92..cd64ed7c5 100644
--- a/src/modules/m_spanningtree.cpp
+++ b/src/modules/m_spanningtree.cpp
@@ -882,8 +882,25 @@ class TreeSocket : public InspSocket
this->WriteLine("ERROR :Version 1.0 FMODE sent to version 1.1 server");
return false;
}
- userrec* who = new userrec(); /* Create dummy userrec */
- who->fd = FD_MAGIC_NUMBER;
+
+ bool smode = false;
+ std::string sourceserv;
+
+ /* Are we dealing with an FMODE from a user, or from a server? */
+ userrec* who = Srv->FindNick(source);
+ if (who)
+ {
+ /* FMODE from a user, set sourceserv to the users server name */
+ sourceserv = who->server;
+ }
+ else
+ {
+ /* FMODE from a server, create a fake user to receive mode feedback */
+ who = new userrec();
+ who->fd = FD_MAGIC_NUMBER;
+ smode = true; /* Setting this flag tells us we should free the userrec later */
+ sourceserv = source; /* Set sourceserv to the actual source string */
+ }
const char* modelist[64];
time_t TS = 0;
int n = 0;
@@ -899,8 +916,12 @@ class TreeSocket : public InspSocket
TS = atoi(params[q].c_str());
}
else
+ {
/* Everything else is fine to append to the modelist */
modelist[n++] = params[q].c_str();
+ log(DEBUG,"Add param: %s",params[q].c_str());
+ }
+
}
/* Extract the TS value of the object, either userrec or chanrec */
userrec* dst = Srv->FindNick(params[0]);
@@ -983,7 +1004,7 @@ class TreeSocket : public InspSocket
/* Call the ModeSet method to determine if its set with the
* given parameter here or not.
*/
- ret = mh->ModeSet(NULL, dst, chan, p);
+ ret = mh->ModeSet(smode ? NULL : who, dst, chan, p);
/* XXX: Really. Dont ask.
* Determine from if its set combined with what the current
@@ -1023,24 +1044,32 @@ class TreeSocket : public InspSocket
/* Update the parameters for FMODE with the new 'bounced' string */
newparams[2] = modebounce;
/* Only send it back the way it came, no need to send it anywhere else */
- DoOneToOne(Srv->GetServerName(),"FMODE",newparams,source);
+ DoOneToOne(Srv->GetServerName(),"FMODE",newparams,sourceserv);
log(DEBUG,"FMODE bounced intelligently, our TS less than theirs and the other server is NOT a uline.");
}
else
{
+ log(DEBUG,"Allow modes, TS lower for sender");
/* The server was ulined, but something iffy is up with the TS.
* Sound the alarm bells!
*/
- if ((Srv->IsUlined(source)) && (TS > ourTS))
+ if ((Srv->IsUlined(sourceserv)) && (TS > ourTS))
{
- WriteOpers("\2WARNING!\2 U-Lined server '%s' has bad TS for '%s' (accepted change): \2SYNC YOUR CLOCKS\2 to avoid this notice",source.c_str(),params[0].c_str());
+ WriteOpers("\2WARNING!\2 U-Lined server '%s' has bad TS for '%s' (accepted change): \2SYNC YOUR CLOCKS\2 to avoid this notice",sourceserv.c_str(),params[0].c_str());
}
- /* Allow the mode */
- Srv->SendMode(modelist,n,who);
+ /* Allow the mode, route it to either server or user command handling */
+ if (smode)
+ Srv->SendMode(modelist,n,who);
+ else
+ Srv->CallCommandHandler("MODE", modelist, n, who);
+
/* HOT POTATO! PASS IT ON! */
- DoOneToAllButSender(source,"FMODE",params,source);
+ DoOneToAllButSender(source,"FMODE",params,sourceserv);
}
- DELETE(who);
+ /* Are we supposed to free the userrec? */
+ if (smode)
+ DELETE(who);
+
return true;
}
@@ -3909,6 +3938,9 @@ class ModuleSpanningTree : public Module
virtual void OnMode(userrec* user, void* dest, int target_type, const std::string &text)
{
+ /* 1.1 Series InspIRCd Spanning Tree now uses FMODE for all user modes,
+ * with a timestamp to prevent certain types of modehack
+ */
if ((user->fd > -1) && (user->registered == 7))
{
if (target_type == TYPE_USER)
@@ -3916,16 +3948,18 @@ class ModuleSpanningTree : public Module
userrec* u = (userrec*)dest;
std::deque<std::string> params;
params.push_back(u->nick);
+ params.push_back(ConvToStr(u->age));
params.push_back(text);
- DoOneToMany(user->nick,"MODE",params);
+ DoOneToMany(user->nick,"FMODE",params);
}
else
{
chanrec* c = (chanrec*)dest;
std::deque<std::string> params;
params.push_back(c->name);
+ params.push_back(ConvToStr(c->age));
params.push_back(text);
- DoOneToMany(user->nick,"MODE",params);
+ DoOneToMany(user->nick,"FMODE",params);
}
}
}