]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree.cpp
Made SANICK not collide the user (theres no need to in the new 1.1 now we have return...
[user/henk/code/inspircd.git] / src / modules / m_spanningtree.cpp
index 39564477204022e5c159c974c15ecd5c547170d2..c52a167871515a76a59a778706a08de89469c322 100644 (file)
@@ -33,6 +33,12 @@ using namespace std;
 
 #define nspace __gnu_cxx
 
+
+/** If you make a change which breaks the protocol, increment this.
+ * If you  completely change the protocol, completely change the number.
+ */
+const long ProtocolVersion = 1100;
+
 /*
  * The server list in InspIRCd is maintained as two structures
  * which hold the data in different ways. Most of the time, we
@@ -588,7 +594,7 @@ class cmd_rconnect : public command_t
                syntax = "<remote-server-mask> <servermask>";
        }
 
-       void Handle (const char** parameters, int pcnt, userrec *user)
+       CmdResult Handle (const char** parameters, int pcnt, userrec *user)
        {
                user->WriteServ("NOTICE %s :*** RCONNECT: Sending remote connect to \002%s\002 to connect server \002%s\002.",user->nick,parameters[0],parameters[1]);
                /* Is this aimed at our server? */
@@ -599,7 +605,11 @@ class cmd_rconnect : public command_t
                        const char* para[1];
                        para[0] = parameters[1];
                        Creator->OnPreCommand("CONNECT", para, 1, user, true);
+
+                       return CMD_SUCCESS;
                }
+
+               return CMD_FAILURE;
        }
 };
  
@@ -852,7 +862,7 @@ class TreeSocket : public InspSocket
 #ifdef SUPPORT_IP6LINKS
                ip6support = 1;
 #endif
-               this->WriteLine("CAPAB CAPABILITIES :NICKMAX="+ConvToStr(NICKMAX)+" HALFOP="+ConvToStr(this->Instance->Config->AllowHalfop)+" CHANMAX="+ConvToStr(CHANMAX)+" MAXMODES="+ConvToStr(MAXMODES)+" IDENTMAX="+ConvToStr(IDENTMAX)+" MAXQUIT="+ConvToStr(MAXQUIT)+" MAXTOPIC="+ConvToStr(MAXTOPIC)+" MAXKICK="+ConvToStr(MAXKICK)+" MAXGECOS="+ConvToStr(MAXGECOS)+" MAXAWAY="+ConvToStr(MAXAWAY)+" IP6NATIVE="+ConvToStr(ip6)+" IP6SUPPORT="+ConvToStr(ip6support));
+               this->WriteLine("CAPAB CAPABILITIES :NICKMAX="+ConvToStr(NICKMAX)+" HALFOP="+ConvToStr(this->Instance->Config->AllowHalfop)+" CHANMAX="+ConvToStr(CHANMAX)+" MAXMODES="+ConvToStr(MAXMODES)+" IDENTMAX="+ConvToStr(IDENTMAX)+" MAXQUIT="+ConvToStr(MAXQUIT)+" MAXTOPIC="+ConvToStr(MAXTOPIC)+" MAXKICK="+ConvToStr(MAXKICK)+" MAXGECOS="+ConvToStr(MAXGECOS)+" MAXAWAY="+ConvToStr(MAXAWAY)+" IP6NATIVE="+ConvToStr(ip6)+" IP6SUPPORT="+ConvToStr(ip6support)+" PROTOCOL="+ConvToStr(ProtocolVersion));
 
                this->WriteLine("CAPAB END");
        }
@@ -938,6 +948,18 @@ class TreeSocket : public InspSocket
                        if (((this->CapKeys.find("NICKMAX") == this->CapKeys.end()) || ((this->CapKeys.find("NICKMAX") != this->CapKeys.end()) && (this->CapKeys.find("NICKMAX")->second != ConvToStr(NICKMAX)))))
                                reason = "Maximum nickname lengths differ or remote nickname length not specified";
 
+                       if (((this->CapKeys.find("PROTOCOL") == this->CapKeys.end()) || ((this->CapKeys.find("PROTOCOL") != this->CapKeys.end()) && (this->CapKeys.find("PROTOCOL")->second != ConvToStr(ProtocolVersion)))))
+                       {
+                               if (this->CapKeys.find("PROTOCOL") != this->CapKeys.end())
+                               {
+                                       reason = "Mismatched protocol versions "+this->CapKeys.find("PROTOCOL")->second+" and "+ConvToStr(ProtocolVersion);
+                               }
+                               else
+                               {
+                                       reason = "Protocol version not specified";
+                               }
+                       }
+
                        if (((this->CapKeys.find("HALFOP") == this->CapKeys.end()) && (Instance->Config->AllowHalfop)) || ((this->CapKeys.find("HALFOP") != this->CapKeys.end()) && (this->CapKeys.find("HALFOP")->second != ConvToStr(Instance->Config->AllowHalfop))))
                                reason = "We don't both have halfop support enabled/disabled identically";
 
@@ -1618,11 +1640,8 @@ class TreeSocket : public InspSocket
                                }
                                else
                                {
-                                       for (unsigned int f = 2; f < modectr; f++)
-                                               free(mode_users[f]);
-
-                                       this->WriteLine("ERROR :Invalid user '"+std::string(usr)+"' in FJOIN to '"+channel+"'");
-                                       return false;
+                                       ServerInstance->Log(SPARSE,"Warning! Invalid user %s in FJOIN to channel %s IGNORED", who->nick, channel.c_str());
+                                       continue;
                                }
                        }
                }
@@ -1664,26 +1683,6 @@ class TreeSocket : public InspSocket
                return true;
        }
 
-       bool SyncChannelTS(std::string source, std::deque<std::string> &params)
-       {
-               if (params.size() >= 2)
-               {
-                       chanrec* c = this->Instance->FindChan(params[0]);
-                       if (c)
-                       {
-                               time_t theirTS = atoi(params[1].c_str());
-                               time_t ourTS = c->age;
-                               if (ourTS >= theirTS)
-                               {
-                                       ServerInstance->Log(DEBUG,"Updating timestamp for %s, our timestamp was %lu and theirs is %lu",c->name,ourTS,theirTS);
-                                       c->age = theirTS;
-                               }
-                       }
-               }
-               DoOneToAllButSender(this->Instance->Config->ServerName,"SYNCTS",params,source);
-               return true;
-       }
-
        /* NICK command */
        bool IntroduceClient(std::string source, std::deque<std::string> &params)
        {
@@ -3186,10 +3185,17 @@ class TreeSocket : public InspSocket
                                                {
                                                        strparams[q] = params[q].c_str();
                                                }
-                                               if (!this->Instance->CallCommandHandler(command.c_str(), strparams, params.size(), who))
+                                               switch (this->Instance->CallCommandHandler(command.c_str(), strparams, params.size(), who))
                                                {
-                                                       this->WriteLine("ERROR :Unrecognised command '"+std::string(command.c_str())+"' -- possibly loaded mismatched modules");
-                                                       return false;
+                                                       case CMD_INVALID:
+                                                               this->WriteLine("ERROR :Unrecognised command '"+std::string(command.c_str())+"' -- possibly loaded mismatched modules");
+                                                               return false;
+                                                       break;
+                                                       case CMD_FAILURE:
+                                                               return true;
+                                                       break;
+                                                       default:
+                                                       break;
                                                }
                                        }
                                        else
@@ -3250,7 +3256,7 @@ class TreeSocket : public InspSocket
                {
                        Squit(s,"Remote host closed the connection");
                }
-               this->Instance->WriteOpers("Server '\2%s\2' closed the connection.",quitserver.c_str());
+               this->Instance->SNO->WriteToSnoMask('l',"Connection to '\2%s\2' failed.",quitserver.c_str());
        }
 
        virtual int OnIncomingConnection(int newsock, char* ip)
@@ -3270,7 +3276,7 @@ class TreeSocket : public InspSocket
 
                        if (!found)
                        {
-                               this->Instance->WriteOpers("Server connection from %s denied (no link blocks with that IP address)", ip);
+                               this->Instance->SNO->WriteToSnoMask('l',"Server connection from %s denied (no link blocks with that IP address)", ip);
                                close(newsock);
                                return false;
                        }
@@ -4084,6 +4090,11 @@ class ModuleSpanningTree : public Module
        {
                if (x->FailOver.length())
                {
+                       if (x->FailOver == x->Name)
+                       {
+                               ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Some muppet configured the failover for server \002%s\002 to point at itself. Not following it!", x->Name.c_str());
+                               return;
+                       }
                        Link* TryThisOne = this->FindLink(x->FailOver.c_str());
                        if (TryThisOne)
                        {
@@ -4118,6 +4129,18 @@ class ModuleSpanningTree : public Module
                                ServerInstance->Log(DEBUG,"Auto-Connecting %s",x->Name.c_str());
                                x->NextConnectTime = curtime + x->AutoConnect;
                                TreeServer* CheckDupe = FindServer(x->Name.c_str());
+                               if (x->FailOver.length())
+                               {
+                                       TreeServer* CheckFailOver = FindServer(x->FailOver.c_str());
+                                       if (CheckFailOver)
+                                       {
+                                               /* The failover for this server is currently a member of the network.
+                                                * The failover probably succeeded, where the main link did not.
+                                                * Don't try the main link until the failover is gone again.
+                                                */
+                                               continue;
+                                       }
+                               }
                                if (!CheckDupe)
                                {
                                        // an autoconnected server is not connected. Check if its time to connect it
@@ -4263,7 +4286,13 @@ class ModuleSpanningTree : public Module
                        this->HandleVersion(parameters,pcnt,user);
                        return 1;
                }
-               else if (ServerInstance->IsValidModuleCommand(command, pcnt, user))
+
+               return 0;
+       }
+
+       virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result)
+       {
+               if ((result == CMD_SUCCESS) && (ServerInstance->IsValidModuleCommand(command, pcnt, user)))
                {
                        // this bit of code cleverly routes all module commands
                        // to all remote severs *automatically* so that modules
@@ -4286,7 +4315,6 @@ class ModuleSpanningTree : public Module
                        ServerInstance->Log(DEBUG,"Globally route '%s'",command.c_str());
                        DoOneToMany(user->nick,command,params);
                }
-               return 0;
        }
 
        virtual void OnGetServerDescription(const std::string &servername,std::string &description)
@@ -4438,10 +4466,19 @@ class ModuleSpanningTree : public Module
                // Only do this for local users
                if (IS_LOCAL(user))
                {
+                       char ts[24];
+                       snprintf(ts,24,"%lu",(unsigned long)channel->age);
+
                        std::deque<std::string> params;
                        params.clear();
                        params.push_back(channel->name);
 
+                       /** XXX: The client protocol will IGNORE this parameter.
+                        * We could make use of it if we wanted to keep the TS
+                        * in step if somehow we lose it.
+                        */
+                       params.push_back(ts);
+
                        if (channel->GetUserCounter() > 1)
                        {
                                // not the first in the channel
@@ -4451,8 +4488,6 @@ class ModuleSpanningTree : public Module
                        {
                                // first in the channel, set up their permissions
                                // and the channel TS with FJOIN.
-                               char ts[24];
-                               snprintf(ts,24,"%lu",(unsigned long)channel->age);
                                params.clear();
                                params.push_back(channel->name);
                                params.push_back(ts);
@@ -4807,7 +4842,7 @@ class ModuleSpanningTree : public Module
                List[I_OnUserQuit] = List[I_OnUserPostNick] = List[I_OnUserKick] = List[I_OnRemoteKill] = List[I_OnRehash] = 1;
                List[I_OnOper] = List[I_OnAddGLine] = List[I_OnAddZLine] = List[I_OnAddQLine] = List[I_OnAddELine] = 1;
                List[I_OnDelGLine] = List[I_OnDelZLine] = List[I_OnDelQLine] = List[I_OnDelELine] = List[I_ProtoSendMode] = List[I_OnMode] = 1;
-               List[I_OnStats] = List[I_ProtoSendMetaData] = List[I_OnEvent] = List[I_OnSetAway] = List[I_OnCancelAway] = 1;
+               List[I_OnStats] = List[I_ProtoSendMetaData] = List[I_OnEvent] = List[I_OnSetAway] = List[I_OnCancelAway] = List[I_OnPostCommand] = 1;
        }
 
        /* It is IMPORTANT that m_spanningtree is the last module in the chain