class ModuleSpanningTree;
static ModuleSpanningTree* TreeProtocolModule;
+extern ServerConfig* Config;
+
extern std::vector<Module*> modules;
extern std::vector<ircd_module*> factory;
extern int MODCOUNT;
return UserCount;
}
+ void AddUserCount()
+ {
+ UserCount++;
+ }
+
+ void DelUserCount()
+ {
+ UserCount--;
+ }
+
int GetOperCount()
{
return OperCount;
time_t NextPing;
bool LastPingWasGood;
bool bursting;
- AES* ctx;
+ AES* ctx_in;
+ AES* ctx_out;
unsigned int keylength;
public:
{
myhost = host;
this->LinkState = LISTENER;
+ this->ctx_in = NULL;
+ this->ctx_out = NULL;
}
TreeSocket(std::string host, int port, bool listening, unsigned long maxtime, std::string ServerName)
{
myhost = ServerName;
this->LinkState = CONNECTING;
+ this->ctx_in = NULL;
+ this->ctx_out = NULL;
}
/* When a listening socket gives us a new file descriptor,
: InspSocket(newfd, ip)
{
this->LinkState = WAIT_AUTH_1;
+ this->ctx_in = NULL;
+ this->ctx_out = NULL;
this->SendCapabilities();
}
+ ~TreeSocket()
+ {
+ if (ctx_in)
+ delete ctx_in;
+ if (ctx_out)
+ delete ctx_out;
+ }
+
void InitAES(std::string key,std::string SName)
{
if (key == "")
return;
- ctx = new AES();
+ ctx_in = new AES();
+ ctx_out = new AES();
log(DEBUG,"Initialized AES key %s",key.c_str());
// key must be 16, 24, 32 etc bytes (multiple of 8)
keylength = key.length();
else
{
WriteOpers("*** \2AES\2: Initialized %d bit encryption to server %s",keylength*8,SName.c_str());
- ctx->MakeKey(key.c_str(), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+ ctx_in->MakeKey(key.c_str(), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", keylength, keylength);
+ ctx_out->MakeKey(key.c_str(), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", keylength, keylength);
}
}
}
params[7] = ":" + params[7];
DoOneToAllButSender(source,"NICK",params,source);
+
+ // Increment the Source Servers User Count..
+ TreeServer* SourceServer = FindServer(source);
+ if (SourceServer) {
+ SourceServer->AddUserCount();
+ }
+
return true;
}
snprintf(data,MAXBUF,":%s FMODE %s +b %s",Srv->GetServerName().c_str(),c->second->name,b->data);
this->WriteLine(data);
}
- FOREACH_MOD OnSyncChannel(c->second,(Module*)TreeProtocolModule,(void*)this);
+ FOREACH_MOD(I_OnSyncChannel,OnSyncChannel(c->second,(Module*)TreeProtocolModule,(void*)this));
list.clear();
c->second->GetExtList(list);
for (unsigned int j = 0; j < list.size(); j++)
{
- FOREACH_MOD OnSyncChannelMetaData(c->second,(Module*)TreeProtocolModule,(void*)this,list[j]);
+ FOREACH_MOD(I_OnSyncChannelMetaData,OnSyncChannelMetaData(c->second,(Module*)TreeProtocolModule,(void*)this,list[j]));
}
}
}
{
this->WriteLine(":"+std::string(u->second->nick)+" OPERTYPE "+std::string(u->second->oper));
}
- FOREACH_MOD OnSyncUser(u->second,(Module*)TreeProtocolModule,(void*)this);
+ FOREACH_MOD(I_OnSyncUser,OnSyncUser(u->second,(Module*)TreeProtocolModule,(void*)this));
list.clear();
u->second->GetExtList(list);
for (unsigned int j = 0; j < list.size(); j++)
{
- FOREACH_MOD OnSyncUserMetaData(u->second,(Module*)TreeProtocolModule,(void*)this,list[j]);
+ FOREACH_MOD(I_OnSyncUserMetaData,OnSyncUserMetaData(u->second,(Module*)TreeProtocolModule,(void*)this,list[j]));
}
}
}
std::string ret = "";
while ((*line != '\n') && (strlen(line)))
{
- ret = ret + *line;
+ if ((*line != '\r') && (*line != '\n'))
+ ret = ret + *line;
line++;
}
if ((*line == '\n') || (*line == '\r'))
/* Process this one, abort if it
* didnt return true.
*/
- if (this->ctx)
+ if (this->ctx_in)
{
char out[1024];
char result[1024];
+ memset(result,0,1024);
+ memset(out,0,1024);
log(DEBUG,"Original string '%s'",ret.c_str());
- /* ERROR is still allowed unencryped */
- if (ret.substr(0,7) != "ERROR :")
+ /* ERROR + CAPAB is still allowed unencryped */
+ if ((ret.substr(0,7) != "ERROR :") && (ret.substr(0,6) != "CAPAB "))
{
int nbytes = from64tobits(out, ret.c_str(), 1024);
- log(DEBUG,"m_spanningtree: decrypt %d bytes",nbytes);
- ctx->Decrypt(out, result, nbytes, 0);
- for (int t = 0; t < nbytes; t++)
- if (result[t] == '\7') result[t] = 0;
- ret = result;
+ if ((nbytes > 0) && (nbytes < 1024))
+ {
+ log(DEBUG,"m_spanningtree: decrypt %d bytes",nbytes);
+ ctx_in->Decrypt(out, result, nbytes, 1);
+ for (int t = 0; t < nbytes; t++)
+ if (result[t] == '\7') result[t] = 0;
+ ret = result;
+ }
}
}
if (!this->ProcessLine(ret))
int WriteLine(std::string line)
{
log(DEBUG,"OUT: %s",line.c_str());
- if (this->ctx)
+ if (this->ctx_out)
{
log(DEBUG,"AES context");
- char result[1024];
- char result64[1024];
+ char result[10240];
+ char result64[10240];
if (this->keylength)
{
while (line.length() % this->keylength != 0)
line = line + "\7";
}
}
- ctx->Encrypt(line.c_str(), result, line.length(),0);
- to64frombits((unsigned char*)result64,
- (unsigned char*)result,
- line.length());
+ unsigned int ll = line.length();
+ log(DEBUG,"Plaintext line with padding = %d chars",ll);
+ ctx_out->Encrypt(line.c_str(), result, ll, 1);
+ log(DEBUG,"Encrypted.");
+ to64frombits((unsigned char*)result64,(unsigned char*)result,ll);
line = result64;
log(DEBUG,"Encrypted: %s",line.c_str());
//int from64tobits(char *out, const char *in, int maxlen);
chanrec* c = Srv->FindChannel(params[0]);
if (c)
{
- FOREACH_MOD OnDecodeMetaData(TYPE_CHANNEL,c,params[1],params[2]);
+ FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(TYPE_CHANNEL,c,params[1],params[2]));
}
}
else
userrec* u = Srv->FindNick(params[0]);
if (u)
{
- FOREACH_MOD OnDecodeMetaData(TYPE_USER,u,params[1],params[2]);
+ FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(TYPE_USER,u,params[1],params[2]));
}
}
}
* hasnt bothered to send the AES command before SERVER, then we
* boot them off as we MUST have this connection encrypted.
*/
- if ((x->EncryptionKey != "") && (!this->ctx))
+ if ((x->EncryptionKey != "") && (!this->ctx_in))
{
this->WriteLine("ERROR :This link requires AES encryption to be enabled. Plaintext connection refused.");
Srv->SendOpers("*** Server connection from \2"+servername+"\2 denied, remote server did not enable AES.");
params.pop_front();
}
- if ((!this->ctx) && (command == "AES"))
+ if ((!this->ctx_in) && (command == "AES"))
{
std::string sserv = params[0];
for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++)
}
return true;
}
- else if ((this->ctx) && (command == "AES"))
+ else if ((this->ctx_in) && (command == "AES"))
{
WriteOpers("*** \2AES\2: Encryption already enabled on this connection yet %s is trying to enable it twice!",params[0].c_str());
}
if ((!route_back_again) || (route_back_again->GetSocket() != this))
{
if (route_back_again)
- {
- WriteOpers("*** Protocol violation: Fake direction in command '%s' from connection '%s'",line.c_str(),this->GetName().c_str());
- }
- else
- {
- WriteOpers("*** Protocol violation: Invalid source '%s' in command '%s' from connection '%s'",direction.c_str(),line.c_str(),this->GetName().c_str());
- }
-
+ log(DEBUG,"Protocol violation: Fake direction in command '%s' from connection '%s'",line.c_str(),this->GetName().c_str());
return true;
}
}
}
else
{
- log(DEFAULT,"m_spanningtree: Invalid configuration for server '%s', ignored!",L.Name.c_str());
+ if (L.RecvPass == "")
+ {
+ log(DEFAULT,"Invalid configuration for server '%s', recvpass not defined!",L.Name.c_str());
+ }
+ else if (L.SendPass == "")
+ {
+ log(DEFAULT,"Invalid configuration for server '%s', sendpass not defined!",L.Name.c_str());
+ }
+ else if (L.Name == "")
+ {
+ log(DEFAULT,"Invalid configuration, link tag without a name!");
+ }
+ else if (!L.Port)
+ {
+ log(DEFAULT,"Invalid configuration for server '%s', no port specified!",L.Name.c_str());
+ }
}
}
delete Conf;
{
matrix[line][t] = ' ';
}
- strlcpy(&matrix[line][depth],Current->GetName().c_str(),80);
+
+ // For Aligning, we need to work out exactly how deep this thing is, and produce
+ // a 'Spacer' String to compensate.
+ char spacer[40];
+
+ memset(spacer,' ',40);
+ if ((40 - Current->GetName().length() - depth) > 1) {
+ spacer[40 - Current->GetName().length() - depth] = '\0';
+ } else {
+ spacer[5] = '\0';
+ }
+
+ float percent;
+ char text[80];
+ if (clientlist.size() == 0) {
+ // If there are no users, WHO THE HELL DID THE /MAP?!?!?!
+ percent = 0;
+ } else {
+ percent = ((float)Current->GetUserCount() / (float)clientlist.size()) * 100;
+ }
+ snprintf(text, 80, "%s %s%d [%.2f%%]", Current->GetName().c_str(), spacer, Current->GetUserCount(), percent);
+ strlcpy(&matrix[line][depth],text,80);
line++;
for (unsigned int q = 0; q < Current->ChildCount(); q++)
{
params.push_back(user->ip);
params.push_back(":"+std::string(user->fullname));
DoOneToMany(Srv->GetServerName(),"NICK",params);
+
+ // User is Local, change needs to be reflected!
+ TreeServer* SourceServer = FindServer(user->server);
+ if (SourceServer) {
+ SourceServer->AddUserCount();
+ }
+
}
}
params.push_back(":"+reason);
DoOneToMany(user->nick,"QUIT",params);
}
+ // Regardless, We need to modify the user Counts..
+ TreeServer* SourceServer = FindServer(user->server);
+ if (SourceServer) {
+ SourceServer->DelUserCount();
+ }
+
}
virtual void OnUserPostNick(userrec* user, std::string oldnick)
{
return Version(1,0,0,0,VF_STATIC|VF_VENDOR);
}
+
+ void Implements(char* List)
+ {
+ List[I_OnPreCommand] = List[I_OnGetServerDescription] = List[I_OnUserInvite] = List[I_OnPostLocalTopicChange] = 1;
+ List[I_OnWallops] = List[I_OnUserNotice] = List[I_OnUserMessage] = List[I_OnBackgroundTimer] = 1;
+ List[I_OnUserJoin] = List[I_OnChangeHost] = List[I_OnChangeName] = List[I_OnUserPart] = List[I_OnUserConnect] = 1;
+ 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_ProtoSendMetaData] = 1;
+ }
};