Exemplo n.º 1
0
int InspIRCd::BindPorts(FailedPortList& failed_ports)
{
	int bound = 0;
	std::vector<ListenSocket*> old_ports(ports.begin(), ports.end());

	ConfigTagList tags = ServerInstance->Config->ConfTags("bind");
	for (ConfigIter i = tags.first; i != tags.second; ++i)
	{
		ConfigTag* tag = i->second;

		// Are we creating a TCP/IP listener?
		const std::string address = tag->getString("address");
		const std::string portlist = tag->getString("port");
		if (!address.empty() || !portlist.empty())
		{
			// InspIRCd supports IPv4 and IPv6 natively; no 4in6 required.
			if (strncasecmp(address.c_str(), "::ffff:", 7) == 0)
				this->Logs.Log("SOCKET", LOG_DEFAULT, "Using 4in6 (::ffff:) isn't recommended. You should bind IPv4 addresses directly instead.");

			// A TCP listener with no ports is not very useful.
			if (portlist.empty())
				this->Logs.Log("SOCKET", LOG_DEFAULT, "TCP listener on %s at %s has no ports specified!",
					address.empty() ? "*" : address.c_str(), tag->getTagLocation().c_str());

			irc::portparser portrange(portlist, false);
			for (int port; (port = portrange.GetToken()); )
			{
				irc::sockets::sockaddrs bindspec;
				if (!irc::sockets::aptosa(address, port, bindspec))
					continue;

				if (!BindPort(tag, bindspec, old_ports))
					failed_ports.push_back(std::make_pair(bindspec, errno));
				else
					bound++;
			}
			continue;
		}

#ifndef _WIN32
		// Are we creating a UNIX listener?
		const std::string path = tag->getString("path");
		if (!path.empty())
		{
			// UNIX socket paths are length limited to less than PATH_MAX.
			irc::sockets::sockaddrs bindspec;
			if (path.length() > std::min(ServerInstance->Config->Limits.MaxHost, sizeof(bindspec.un.sun_path)))
			{
				this->Logs.Log("SOCKET", LOG_DEFAULT, "UNIX listener on %s at %s specified a path that is too long!",
					path.c_str(), tag->getTagLocation().c_str());
				continue;
			}

			// Create the bindspec manually (aptosa doesn't work with AF_UNIX yet).
			memset(&bindspec, 0, sizeof(bindspec));
			bindspec.un.sun_family = AF_UNIX;
			memcpy(&bindspec.un.sun_path, path.c_str(), sizeof(bindspec.un.sun_path));

			if (!BindPort(tag, bindspec, old_ports))
				failed_ports.push_back(std::make_pair(bindspec, errno));
			else
				bound++;
		}
#endif
	}

	std::vector<ListenSocket*>::iterator n = ports.begin();
	for (std::vector<ListenSocket*>::iterator o = old_ports.begin(); o != old_ports.end(); ++o)
	{
		while (n != ports.end() && *n != *o)
			n++;
		if (n == ports.end())
		{
			this->Logs.Log("SOCKET", LOG_DEFAULT, "Port bindings slipped out of vector, aborting close!");
			break;
		}

		this->Logs.Log("SOCKET", LOG_DEFAULT, "Port binding %s was removed from the config file, closing.",
			(**n).bind_sa.str().c_str());
		delete *n;

		// this keeps the iterator valid, pointing to the next element
		n = ports.erase(n);
	}

	return bound;
}
Exemplo n.º 2
0
int InspIRCd::BindPorts(FailedPortList &failed_ports)
{
	int bound = 0;
	std::vector<ListenSocket*> old_ports(ports.begin(), ports.end());

	ConfigTagList tags = ServerInstance->Config->ConfTags("bind");
	for(ConfigIter i = tags.first; i != tags.second; ++i)
	{
		ConfigTag* tag = i->second;
		std::string porttag = tag->getString("port");
		std::string Addr = tag->getString("address");

		if (strncasecmp(Addr.c_str(), "::ffff:", 7) == 0)
			this->Logs->Log("SOCKET", LOG_DEFAULT, "Using 4in6 (::ffff:) isn't recommended. You should bind IPv4 addresses directly instead.");

		irc::portparser portrange(porttag, false);
		int portno = -1;
		while (0 != (portno = portrange.GetToken()))
		{
			irc::sockets::sockaddrs bindspec;
			if (!irc::sockets::aptosa(Addr, portno, bindspec))
				continue;
			std::string bind_readable = bindspec.str();

			bool skip = false;
			for (std::vector<ListenSocket*>::iterator n = old_ports.begin(); n != old_ports.end(); ++n)
			{
				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
					(*n)->ResetIOHookProvider();

					skip = true;
					old_ports.erase(n);
					break;
				}
			}
			if (!skip)
			{
				ListenSocket* ll = new ListenSocket(tag, bindspec);

				if (ll->GetFd() > -1)
				{
					bound++;
					ports.push_back(ll);
				}
				else
				{
					failed_ports.push_back(std::make_pair(bind_readable, strerror(errno)));
					delete ll;
				}
			}
		}
	}

	std::vector<ListenSocket*>::iterator n = ports.begin();
	for (std::vector<ListenSocket*>::iterator o = old_ports.begin(); o != old_ports.end(); ++o)
	{
		while (n != ports.end() && *n != *o)
			n++;
		if (n == ports.end())
		{
			this->Logs->Log("SOCKET", LOG_DEFAULT, "Port bindings slipped out of vector, aborting close!");
			break;
		}

		this->Logs->Log("SOCKET", LOG_DEFAULT, "Port binding %s was removed from the config file, closing.",
			(**n).bind_desc.c_str());
		delete *n;

		// this keeps the iterator valid, pointing to the next element
		n = ports.erase(n);
	}

	return bound;
}