Example #1
0
bool TreeSocket::CheckDuplicate(const std::string& sname, const std::string& sid)
{
	/* Check for fully initialized instances of the server by name */
	TreeServer* CheckDupe = Utils->FindServer(sname);
	if (CheckDupe)
	{
		std::string pname = CheckDupe->GetParent() ? CheckDupe->GetParent()->GetName() : "<ourself>";
		SendError("Server "+sname+" already exists on server "+pname+"!");
		ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+pname);
		return false;
	}

	/* Check for fully initialized instances of the server by id */
	ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Looking for dupe SID %s", sid.c_str());
	CheckDupe = Utils->FindServerID(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 \2"+sname+"\2 denied, server ID '"+CheckDupe->GetID()+
				"' already exists on server "+CheckDupe->GetName());
		return false;
	}

	return true;
}
Example #2
0
bool TreeSocket::CheckDuplicate(const std::string& sname, const std::string& sid)
{
	// Check if the server name is not in use by a server that's already fully connected
	TreeServer* CheckDupe = Utils->FindServer(sname);
	if (CheckDupe)
	{
		std::string pname = CheckDupe->GetParent() ? CheckDupe->GetParent()->GetName() : "<ourself>";
		SendError("Server "+sname+" already exists on server "+pname+"!");
		ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+pname);
		return false;
	}

	// Check if the id is not in use by a server that's already fully connected
	ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Looking for dupe SID %s", sid.c_str());
	CheckDupe = Utils->FindServerID(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 \2"+sname+"\2 denied, server ID '"+CheckDupe->GetID()+
				"' already exists on server "+CheckDupe->GetName());
		return false;
	}

	return true;
}
Example #3
0
int ModuleSpanningTree::HandleStats(const char** parameters, int pcnt, userrec* user)
{
	if (pcnt > 1)
	{
		if (match(ServerInstance->Config->ServerName, parameters[1]))
			return 0;

		/* Remote STATS, the server is within the 2nd parameter */
		std::deque<std::string> params;
		params.push_back(parameters[0]);
		params.push_back(parameters[1]);
		/* Send it out remotely, generate no reply yet */

		TreeServer* s = Utils->FindServerMask(parameters[1]);
		if (s)
		{
			params[1] = s->GetName();
			Utils->DoOneToOne(user->nick, "STATS", params, s->GetName());
		}
		else
		{
			user->WriteServ( "402 %s %s :No such server", user->nick, parameters[1]);
		}
		return 1;
	}
	return 0;
}
Example #4
0
/*
 * Some server somewhere in the network introducing another server.
 *	-- w
 */
bool TreeSocket::RemoteServer(const std::string &prefix, parameterlist &params)
{
	if (params.size() < 5)
	{
		SendError("Protocol error - Not enough parameters for SERVER command");
		return false;
	}

	std::string servername = params[0];
	// password is not used for a remote server
	// hopcount is not used (ever)
	std::string sid = params[3];
	std::string description = params[4];
	TreeServer* ParentOfThis = Utils->FindServer(prefix);

	if (!ParentOfThis)
	{
		this->SendError("Protocol error - Introduced remote server from unknown server "+prefix);
		return false;
	}
	if (!ServerInstance->IsSID(sid))
	{
		this->SendError("Invalid format server ID: "+sid+"!");
		return false;
	}
	TreeServer* CheckDupe = Utils->FindServer(servername);
	if (CheckDupe)
	{
		this->SendError("Server "+servername+" already exists!");
		ServerInstance->SNO->WriteToSnoMask('L', "Server \2"+CheckDupe->GetName()+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, already exists. Closing link with " + ParentOfThis->GetName());
		return false;
	}
	CheckDupe = Utils->FindServer(sid);
	if (CheckDupe)
	{
		this->SendError("Server ID "+sid+" already exists! 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 \2"+servername+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, server ID already exists on the network. Closing link with " + ParentOfThis->GetName());
		return false;
	}


	Link* lnk = Utils->FindLink(servername);

	TreeServer *Node = new TreeServer(Utils, servername, description, sid, ParentOfThis,NULL, lnk ? lnk->Hidden : false);

	ParentOfThis->AddChild(Node);
	params[4] = ":" + params[4];
	Utils->DoOneToAllButSender(prefix,"SERVER",params,prefix);
	ServerInstance->SNO->WriteToSnoMask('L', "Server \002"+ParentOfThis->GetName()+"\002 introduced server \002"+servername+"\002 ("+description+")");
	return true;
}
Example #5
0
bool TreeSocket::DelLine(const std::string &prefix, parameterlist &params)
{
	if (params.size() < 2)
		return true;

	std::string setter = "<unknown>";

	User* user = ServerInstance->FindNick(prefix);
	if (user)
		setter = user->nick;
	else
	{
		TreeServer* t = Utils->FindServer(prefix);
		if (t)
			setter = t->GetName();
	}


	/* NOTE: No check needed on 'user', this function safely handles NULL */
	if (ServerInstance->XLines->DelLine(params[1].c_str(), params[0], user))
	{
		ServerInstance->SNO->WriteToSnoMask('X',"%s removed %s%s on %s", setter.c_str(),
				params[0].c_str(), params[0].length() == 1 ? "-line" : "", params[1].c_str());
		Utils->DoOneToAllButSender(prefix,"DELLINE", params, prefix);
	}
	return true;
}
Example #6
0
int ModuleSpanningTree::HandleModules(const std::vector<std::string>& parameters, User* user)
{
	if (parameters.size() > 0)
	{
		if (InspIRCd::Match(ServerInstance->Config->ServerName, parameters[0]))
			return 0;

		std::deque<std::string> params;
		params.push_back(parameters[0]);
		TreeServer* s = Utils->FindServerMask(parameters[0].c_str());
		if (s)
		{
			params[0] = s->GetName();
			Utils->DoOneToOne(user->uuid, "MODULES", params, s->GetName());
		}
		else
			user->WriteNumeric(ERR_NOSUCHSERVER, "%s %s :No such server", user->nick.c_str(), parameters[0].c_str());
		return 1;
	}
	return 0;
}
Example #7
0
void CommandMap::ShowMap(TreeServer* Current, User* user, int depth, int &line, char* names, int &maxnamew, char* stats)
{
	ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "ShowMap depth %d on line %d", depth, line);
	float percent;

	if (ServerInstance->Users->clientlist->size() == 0)
	{
		// If there are no users, WHO THE HELL DID THE /MAP?!?!?!
		percent = 0;
	}
	else
	{
		percent = Current->UserCount * 100.0 / ServerInstance->Users->clientlist->size();
	}

	const std::string operdata = user->IsOper() ? MapOperInfo(Current) : "";

	char* myname = names + 100 * line;
	char* mystat = stats + 50 * line;
	memset(myname, ' ', depth);
	int w = depth;

	if (user->IsOper())
	{
		w += snprintf(myname + depth, 99 - depth, "%s (%s)", Current->GetName().c_str(), Current->GetID().c_str());
	}
	else
	{
		w += snprintf(myname + depth, 99 - depth, "%s", Current->GetName().c_str());
	}
	memset(myname + w, ' ', 100 - w);
	if (w > maxnamew)
		maxnamew = w;
	snprintf(mystat, 49, "%5d [%5.2f%%]%s", Current->UserCount, percent, operdata.c_str());

	line++;

	if (user->IsOper() || !Utils->FlatLinks)
		depth = depth + 2;

	const TreeServer::ChildServers& servers = Current->GetChildren();
	for (TreeServer::ChildServers::const_iterator i = servers.begin(); i != servers.end(); ++i)
	{
		TreeServer* child = *i;
		if (!user->IsOper()) {
			if (child->Hidden)
				continue;
			if ((Utils->HideULines) && (ServerInstance->ULine(child->GetName())))
				continue;
		}
		ShowMap(child, user, depth, line, names, maxnamew, stats);
	}
}
Example #8
0
int ModuleSpanningTree::HandleModules(const char** parameters, int pcnt, userrec* user)
{
	if (pcnt > 0)
	{
		if (match(ServerInstance->Config->ServerName, parameters[0]))
			return 0;

		std::deque<std::string> params;
		params.push_back(parameters[0]);
		TreeServer* s = Utils->FindServerMask(parameters[0]);
		if (s)
		{
			params[0] = s->GetName();
			Utils->DoOneToOne(user->nick, "MODULES", params, s->GetName());
		}
		else
			user->WriteServ( "402 %s %s :No such server", user->nick, parameters[0]);
		return 1;
	}
	return 0;
}
Example #9
0
void ModuleSpanningTree::ShowMap(TreeServer* Current, User* user, int depth, int &line, char* names, int &maxnamew, char* stats)
{
	ServerInstance->Logs->Log("map",LOG_DEBUG,"ShowMap depth %d on line %d", depth, line);
	float percent;

	if (ServerInstance->Users->clientlist->size() == 0)
	{
		// If there are no users, WHO THE HELL DID THE /MAP?!?!?!
		percent = 0;
	}
	else
	{
		percent = Current->UserCount * 100.0 / ServerInstance->Users->clientlist->size();
	}

	const std::string operdata = user->IsOper() ? MapOperInfo(Current) : "";

	char* myname = names + 100 * line;
	char* mystat = stats + 50 * line;
	memset(myname, ' ', depth);
	int w = depth;

	std::string servername = Current->GetName();
	if (user->IsOper())
	{
		w += snprintf(myname + depth, 99 - depth, "%s (%s)", servername.c_str(), Current->GetID().c_str());
	}
	else
	{
		w += snprintf(myname + depth, 99 - depth, "%s", servername.c_str());
	}
	memset(myname + w, ' ', 100 - w);
	if (w > maxnamew)
		maxnamew = w;
	snprintf(mystat, 49, "%5d [%5.2f%%]%s", Current->UserCount, percent, operdata.c_str());

	line++;

	if (user->IsOper() || !Utils->FlatLinks)
		depth = depth + 2;
	for (unsigned int q = 0; q < Current->ChildCount(); q++)
	{
		TreeServer* child = Current->GetChild(q);
		if (!user->IsOper()) {
			if (child->Hidden)
				continue;
			if ((Utils->HideULines) && (ServerInstance->ULine(child->GetName())))
				continue;
		}
		ShowMap(child, user, depth, line, names, maxnamew, stats);
	}
}
Example #10
0
int ModuleSpanningTree::HandleMotd(const std::vector<std::string>& parameters, User* user)
{
	if (parameters.size() > 0)
	{
		if (InspIRCd::Match(ServerInstance->Config->ServerName, parameters[0]))
			return 0;

		/* Remote MOTD, the server is within the 1st parameter */
		std::deque<std::string> params;
		params.push_back(parameters[0]);
		/* Send it out remotely, generate no reply yet */
		TreeServer* s = Utils->FindServerMask(parameters[0]);
		if (s)
		{
			params[0] = s->GetName();
			Utils->DoOneToOne(user->uuid, "MOTD", params, s->GetName());
		}
		else
			user->WriteNumeric(ERR_NOSUCHSERVER, "%s %s :No such server", user->nick.c_str(), parameters[0].c_str());
		return 1;
	}
	return 0;
}
Example #11
0
int ModuleSpanningTree::HandleTime(const char** parameters, int pcnt, userrec* user)
{
	if ((IS_LOCAL(user)) && (pcnt))
	{
		TreeServer* found = Utils->FindServerMask(parameters[0]);
		if (found)
		{
			// we dont' override for local server
			if (found == Utils->TreeRoot)
				return 0;
			
			std::deque<std::string> params;
			params.push_back(found->GetName());
			params.push_back(user->nick);
			Utils->DoOneToOne(ServerInstance->Config->ServerName,"TIME",params,found->GetName());
		}
		else
		{
			user->WriteServ("402 %s %s :No such server",user->nick,parameters[0]);
		}
	}
	return 1;
}
Example #12
0
void SpanningTreeProtocolInterface::GetServerList(ServerList& sl)
{
	for (server_hash::iterator i = Utils->serverlist.begin(); i != Utils->serverlist.end(); i++)
	{
		ServerInfo ps;
		ps.servername = i->second->GetName();
		TreeServer* s = i->second->GetParent();
		ps.parentname = s ? s->GetName() : "";
		ps.usercount = i->second->UserCount;
		ps.opercount = i->second->OperCount;
		ps.gecos = i->second->GetDesc();
		ps.latencyms = i->second->rtt;
		sl.push_back(ps);
	}
}
Example #13
0
void ModuleSpanningTree::DoPingChecks(time_t curtime)
{
	for (unsigned int j = 0; j < Utils->TreeRoot->ChildCount(); j++)
	{
		TreeServer* serv = Utils->TreeRoot->GetChild(j);
		TreeSocket* sock = serv->GetSocket();
		if (sock)
		{
			if (curtime >= serv->NextPingTime())
			{
				if (serv->AnsweredLastPing())
				{
					sock->WriteLine(std::string(":")+ServerInstance->Config->ServerName+" PING "+serv->GetName());
					serv->SetNextPingTime(curtime + 60);
					serv->LastPing = curtime;
					serv->Warned = false;
				}
				else
				{
					/* they didnt answer, boot them */
					sock->SendError("Ping timeout");
					sock->Squit(serv,"Ping timeout");
					ServerInstance->SE->DelFd(sock);
					sock->Close();
					return;
				}
			}
			else if ((Utils->PingWarnTime) && (!serv->Warned) && (curtime >= serv->NextPingTime() - (60 - Utils->PingWarnTime)) && (!serv->AnsweredLastPing()))
			{
				/* The server hasnt responded, send a warning to opers */
				ServerInstance->SNO->WriteToSnoMask('l',"Server \002%s\002 has not responded to PING for %d seconds, high latency.", serv->GetName().c_str(), Utils->PingWarnTime);
				serv->Warned = true;
			}
		}
	}

	/* Cancel remote burst mode on any servers which still have it enabled due to latency/lack of data.
	 * This prevents lost REMOTECONNECT notices
	 */
	for (server_hash::iterator i = Utils->serverlist.begin(); i != Utils->serverlist.end(); i++)
		Utils->SetRemoteBursting(i->second, false);
}
Example #14
0
bool SpanningTreeUtilities::DoOneToAllButSender(const std::string& prefix, const std::string& command, const parameterlist& params, const std::string& omit)
{
	TreeServer* omitroute = this->BestRouteTo(omit);
	std::string FullLine = ConstructLine(prefix, command, params);

	unsigned int items = this->TreeRoot->ChildCount();
	for (unsigned int x = 0; x < items; x++)
	{
		TreeServer* Route = this->TreeRoot->GetChild(x);
		// Send the line IF:
		// The route has a socket (its a direct connection)
		// The route isnt the one to be omitted
		// The route isnt the path to the one to be omitted
		if ((Route) && (Route->GetSocket()) && (Route->GetName() != omit) && (omitroute != Route))
		{
			TreeSocket* Sock = Route->GetSocket();
			if (Sock)
				Sock->WriteLine(FullLine);
		}
	}
	return true;
}
Example #15
0
/*
 * Some server somewhere in the network introducing another server.
 *	-- w
 */
CmdResult CommandServer::HandleServer(TreeServer* ParentOfThis, std::vector<std::string>& params)
{
	std::string servername = params[0];
	// password is not used for a remote server
	// hopcount is not used (ever)
	std::string sid = params[3];
	std::string description = params[4];
	TreeSocket* socket = ParentOfThis->GetSocket();

	if (!InspIRCd::IsSID(sid))
	{
		socket->SendError("Invalid format server ID: "+sid+"!");
		return CMD_FAILURE;
	}
	TreeServer* CheckDupe = Utils->FindServer(servername);
	if (CheckDupe)
	{
		socket->SendError("Server "+servername+" already exists!");
		ServerInstance->SNO->WriteToSnoMask('L', "Server \2"+CheckDupe->GetName()+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, already exists. Closing link with " + ParentOfThis->GetName());
		return CMD_FAILURE;
	}
	CheckDupe = Utils->FindServer(sid);
	if (CheckDupe)
	{
		socket->SendError("Server ID "+sid+" already exists! 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 \2"+servername+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, server ID already exists on the network. Closing link with " + ParentOfThis->GetName());
		return CMD_FAILURE;
	}


	Link* lnk = Utils->FindLink(servername);

	TreeServer* Node = new TreeServer(servername, description, sid, ParentOfThis, ParentOfThis->GetSocket(), lnk ? lnk->Hidden : false);

	ParentOfThis->AddChild(Node);
	ServerInstance->SNO->WriteToSnoMask('L', "Server \002"+ParentOfThis->GetName()+"\002 introduced server \002"+servername+"\002 ("+description+")");
	return CMD_SUCCESS;
}
Example #16
0
void ModuleSpanningTree::ShowLinks(TreeServer* Current, User* user, int hops)
{
	std::string Parent = Utils->TreeRoot->GetName();
	if (Current->GetParent())
	{
		Parent = Current->GetParent()->GetName();
	}

	const TreeServer::ChildServers& children = Current->GetChildren();
	for (TreeServer::ChildServers::const_iterator i = children.begin(); i != children.end(); ++i)
	{
		TreeServer* server = *i;
		if ((server->Hidden) || ((Utils->HideULines) && (ServerInstance->ULine(server->GetName()))))
		{
			if (user->IsOper())
			{
				 ShowLinks(server, user, hops+1);
			}
		}
		else
		{
			ShowLinks(server, user, hops+1);
		}
	}
	/* Don't display the line if its a uline, hide ulines is on, and the user isnt an oper */
	if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetName())) && (!user->IsOper()))
		return;
	/* Or if the server is hidden and they're not an oper */
	else if ((Current->Hidden) && (!user->IsOper()))
		return;

	user->WriteNumeric(364, "%s %s %s :%d %s",	user->nick.c_str(), Current->GetName().c_str(),
			(Utils->FlatLinks && (!user->IsOper())) ? ServerInstance->Config->ServerName.c_str() : Parent.c_str(),
			(Utils->FlatLinks && (!user->IsOper())) ? 0 : hops,
			Current->GetDesc().c_str());
}
Example #17
0
void ModuleSpanningTree::DoPingChecks(time_t curtime)
{
	/*
	 * Cancel remote burst mode on any servers which still have it enabled due to latency/lack of data.
	 * This prevents lost REMOTECONNECT notices
	 */
	long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);

restart:
	for (server_hash::iterator i = Utils->serverlist.begin(); i != Utils->serverlist.end(); i++)
	{
		TreeServer *s = i->second;

		// Skip myself
		if (s->IsRoot())
			continue;

		if (s->GetSocket()->GetLinkState() == DYING)
		{
			s->GetSocket()->Close();
			goto restart;
		}

		// Do not ping servers that are not fully connected yet!
		// Servers which are connected to us have IsLocal() == true and if they're fully connected
		// then Socket->LinkState == CONNECTED. Servers that are linked to another server are always fully connected.
		if (s->IsLocal() && s->GetSocket()->GetLinkState() != CONNECTED)
			continue;

		// Now do PING checks on all servers
		// Only ping if this server needs one
		if (curtime >= s->NextPingTime())
		{
			// And if they answered the last
			if (s->AnsweredLastPing())
			{
				// They did, send a ping to them
				s->SetNextPingTime(curtime + Utils->PingFreq);
				s->GetSocket()->WriteLine(":" + ServerInstance->Config->GetSID() + " PING " + s->GetID());
				s->LastPingMsec = ts;
			}
			else
			{
				// They didn't answer the last ping, if they are locally connected, get rid of them.
				if (s->IsLocal())
				{
					TreeSocket* sock = s->GetSocket();
					sock->SendError("Ping timeout");
					sock->Close();
					goto restart;
				}
			}
		}

		// If warn on ping enabled and not warned and the difference is sufficient and they didn't answer the last ping...
		if ((Utils->PingWarnTime) && (!s->Warned) && (curtime >= s->NextPingTime() - (Utils->PingFreq - Utils->PingWarnTime)) && (!s->AnsweredLastPing()))
		{
			/* The server hasnt responded, send a warning to opers */
			ServerInstance->SNO->WriteToSnoMask('l',"Server \002%s\002 has not responded to PING for %d seconds, high latency.", s->GetName().c_str(), Utils->PingWarnTime);
			s->Warned = true;
		}
	}
}
Example #18
0
// Ok, prepare to be confused.
// After much mulling over how to approach this, it struck me that
// the 'usual' way of doing a /MAP isnt the best way. Instead of
// keeping track of a ton of ascii characters, and line by line
// under recursion working out where to place them using multiplications
// and divisons, we instead render the map onto a backplane of characters
// (a character matrix), then draw the branches as a series of "L" shapes
// from the nodes. This is not only friendlier on CPU it uses less stack.
bool ModuleSpanningTree::HandleMap(const std::vector<std::string>& parameters, User* user)
{
	if (parameters.size() > 0)
	{
		/* Remote MAP, the server is within the 1st parameter */
		TreeServer* s = Utils->FindServerMask(parameters[0]);
		bool ret = false;
		if (!s)
		{
			user->WriteNumeric(ERR_NOSUCHSERVER, "%s %s :No such server", user->nick.c_str(), parameters[0].c_str());
			ret = true;
		}
		else if (s && s != Utils->TreeRoot)
		{
			parameterlist params;
			params.push_back(parameters[0]);

			params[0] = s->GetName();
			Utils->DoOneToOne(user->uuid, "MAP", params, s->GetName());
			ret = true;
		}

		// Don't return if s == Utils->TreeRoot (us)
		if (ret)
			return true;
	}

	// These arrays represent a virtual screen which we will
	// "scratch" draw to, as the console device of an irc
	// client does not provide for a proper terminal.
	int totusers = ServerInstance->Users->clientlist->size();
	int totservers = this->CountServs();
	int maxnamew = 0;
	int line = 0;
	char* names = new char[totservers * 100];
	char* stats = new char[totservers * 50];

	// The only recursive bit is called here.
	ShowMap(Utils->TreeRoot,user,0,line,names,maxnamew,stats);

	// Process each line one by one.
	for (int l = 1; l < line; l++)
	{
		char* myname = names + 100 * l;
		// scan across the line looking for the start of the
		// servername (the recursive part of the algorithm has placed
		// the servers at indented positions depending on what they
		// are related to)
		int first_nonspace = 0;

		while (myname[first_nonspace] == ' ')
		{
			first_nonspace++;
		}

		first_nonspace--;

		// Draw the `- (corner) section: this may be overwritten by
		// another L shape passing along the same vertical pane, becoming
		// a |- (branch) section instead.

		myname[first_nonspace] = '-';
		myname[first_nonspace-1] = '`';
		int l2 = l - 1;

		// Draw upwards until we hit the parent server, causing possibly
		// other corners (`-) to become branches (|-)
		while ((names[l2 * 100 + first_nonspace-1] == ' ') || (names[l2 * 100 + first_nonspace-1] == '`'))
		{
			names[l2 * 100 + first_nonspace-1] = '|';
			l2--;
		}
	}

	float avg_users = totusers * 1.0 / line;

	ServerInstance->Logs->Log("map",LOG_DEBUG,"local");
	for (int t = 0; t < line; t++)
	{
		// terminate the string at maxnamew characters
		names[100 * t + maxnamew] = '\0';
		user->SendText(":%s %03d %s :%s %s", ServerInstance->Config->ServerName.c_str(),
			RPL_MAP, user->nick.c_str(), names + 100 * t, stats + 50 * t);
	}
	user->SendText(":%s %03d %s :%d server%s and %d user%s, average %.2f users per server",
		ServerInstance->Config->ServerName.c_str(), RPL_MAPUSERS, user->nick.c_str(),
		line, (line > 1 ? "s" : ""), totusers, (totusers > 1 ? "s" : ""), avg_users);
	user->SendText(":%s %03d %s :End of /MAP", ServerInstance->Config->ServerName.c_str(),
		RPL_ENDMAP, user->nick.c_str());

	delete[] names;
	delete[] stats;

	return true;
}
Example #19
0
void ModuleSpanningTree::DoPingChecks(time_t curtime)
{
	/*
	 * Cancel remote burst mode on any servers which still have it enabled due to latency/lack of data.
	 * This prevents lost REMOTECONNECT notices
	 */
	timeval t;
	gettimeofday(&t, NULL);
	long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000);

	for (server_hash::iterator i = Utils->serverlist.begin(); i != Utils->serverlist.end(); i++)
	{
		TreeServer *s = i->second;

		// Fix for bug #792, do not ping servers that are not connected yet!
		// Remote servers have Socket == NULL and local connected servers have
		// Socket->LinkState == CONNECTED
		if (s->GetSocket() && s->GetSocket()->GetLinkState() != CONNECTED)
			continue;

		// Now do PING checks on all servers
		TreeServer *mts = Utils->BestRouteTo(s->GetID());

		if (mts)
		{
			// Only ping if this server needs one
			if (curtime >= s->NextPingTime())
			{
				// And if they answered the last
				if (s->AnsweredLastPing())
				{
					// They did, send a ping to them
					s->SetNextPingTime(curtime + Utils->PingFreq);
					TreeSocket *tsock = mts->GetSocket();

					// ... if we can find a proper route to them
					if (tsock)
					{
						tsock->WriteLine(std::string(":") + ServerInstance->Config->GetSID() + " PING " +
								ServerInstance->Config->GetSID() + " " + s->GetID());
						s->LastPingMsec = ts;
					}
				}
				else
				{
					// They didn't answer the last ping, if they are locally connected, get rid of them.
					TreeSocket *sock = s->GetSocket();
					if (sock)
					{
						sock->SendError("Ping timeout");
						sock->Squit(s,"Ping timeout");
						ServerInstance->SE->DelFd(sock);
						sock->Close();
						return;
					}
				}
			}

			// If warn on ping enabled and not warned and the difference is sufficient and they didn't answer the last ping...
			if ((Utils->PingWarnTime) && (!s->Warned) && (curtime >= s->NextPingTime() - (Utils->PingFreq - Utils->PingWarnTime)) && (!s->AnsweredLastPing()))
			{
				/* The server hasnt responded, send a warning to opers */
				ServerInstance->SNO->WriteToSnoMask('l',"Server \002%s\002 has not responded to PING for %d seconds, high latency.", s->GetName().c_str(), Utils->PingWarnTime);
				s->Warned = true;
			}
		}
	}
}
Example #20
0
CmdResult CommandUID::Handle(User* serversrc, std::vector<std::string>& params)
{
	/** Do we have enough parameters:
	 *      0    1    2    3    4    5        6        7     8        9       (n-1)
	 * UID uuid age nick host dhost ident ip.string signon +modes (modepara) :gecos
	 */
	time_t age_t = ConvToInt(params[1]);
	time_t signon = ConvToInt(params[7]);
	std::string empty;
	const std::string& modestr = params[8];

	TreeServer* remoteserver = Utils->FindServer(serversrc->server);

	if (!remoteserver)
		return CMD_INVALID;
	/* Is this a valid UID, and not misrouted? */
	if (params[0].length() != 9 || params[0].substr(0,3) != serversrc->uuid)
		return CMD_INVALID;
	/* Check parameters for validity before introducing the client, discovered by dmb */
	if (!age_t)
		return CMD_INVALID;
	if (!signon)
		return CMD_INVALID;
	if (modestr[0] != '+')
		return CMD_INVALID;

	/* check for collision */
	user_hash::iterator iter = ServerInstance->Users->clientlist->find(params[2]);

	if (iter != ServerInstance->Users->clientlist->end())
	{
		/*
		 * Nick collision.
		 */
		int collide = Utils->DoCollision(iter->second, remoteserver, age_t, params[5], params[6], params[0]);
		ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "*** Collision on %s, collide=%d", params[2].c_str(), collide);

		if (collide != 1)
		{
			// Remote client lost, make sure we change their nick for the hash too
			params[2] = params[0];
		}
	}

	/* IMPORTANT NOTE: For remote users, we pass the UUID in the constructor. This automatically
	 * sets it up in the UUID hash for us.
	 */
	User* _new = NULL;
	try
	{
		_new = new RemoteUser(params[0], remoteserver->GetName());
	}
	catch (...)
	{
		ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Duplicate UUID %s in client introduction", params[0].c_str());
		return CMD_INVALID;
	}
	(*(ServerInstance->Users->clientlist))[params[2]] = _new;
	_new->nick = params[2];
	_new->host = params[3];
	_new->dhost = params[4];
	_new->ident = params[5];
	_new->fullname = params[params.size() - 1];
	_new->registered = REG_ALL;
	_new->signon = signon;
	_new->age = age_t;

	unsigned int paramptr = 9;

	for (std::string::const_iterator v = modestr.begin(); v != modestr.end(); ++v)
	{
		// Accept more '+' chars, for now
		if (*v == '+')
			continue;

		/* For each mode thats set, find the mode handler and set it on the new user */
		ModeHandler* mh = ServerInstance->Modes->FindMode(*v, MODETYPE_USER);
		if (!mh)
		{
			ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Unrecognised mode '%c' for a user in UID, dropping link", *v);
			return CMD_INVALID;
		}

		if (mh->GetNumParams(true))
		{
			if (paramptr >= params.size() - 1)
				return CMD_INVALID;
			std::string mp = params[paramptr++];
			/* IMPORTANT NOTE:
			 * All modes are assumed to succeed here as they are being set by a remote server.
			 * Modes CANNOT FAIL here. If they DO fail, then the failure is ignored. This is important
			 * to note as all but one modules currently cannot ever fail in this situation, except for
			 * m_servprotect which specifically works this way to prevent the mode being set ANYWHERE
			 * but here, at client introduction. You may safely assume this behaviour is standard and
			 * will not change in future versions if you want to make use of this protective behaviour
			 * yourself.
			 */
			mh->OnModeChange(_new, _new, NULL, mp, true);
		}
		else
			mh->OnModeChange(_new, _new, NULL, empty, true);
		_new->SetMode(mh, true);
	}

	_new->SetClientIP(params[6].c_str());

	ServerInstance->Users->AddGlobalClone(_new);
	remoteserver->UserCount++;

	bool dosend = true;

	if ((Utils->quiet_bursts && remoteserver->bursting) || ServerInstance->SilentULine(_new->server))
		dosend = false;

	if (dosend)
		ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s (%s) [%s]", _new->server.c_str(), _new->GetFullRealHost().c_str(), _new->GetIPString().c_str(), _new->fullname.c_str());

	FOREACH_MOD(OnPostConnect, (_new));

	return CMD_SUCCESS;
}