コード例 #1
0
ファイル: socket.cpp プロジェクト: aszrul/inspircd
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;
}
コード例 #2
0
ファイル: socket.cpp プロジェクト: Canternet/inspircd
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;
}
コード例 #3
0
ファイル: m_dnsbl.cpp プロジェクト: novas0x2a/inspircd
	/** Fill our conf vector with data
	 */
	void ReadConf()
	{
		DNSBLConfEntries.clear();

		ConfigTagList dnsbls = ServerInstance->Config->ConfTags("dnsbl");
		for(ConfigIter i = dnsbls.first; i != dnsbls.second; ++i)
		{
			ConfigTag* tag = i->second;
			reference<DNSBLConfEntry> e = new DNSBLConfEntry();

			e->name = tag->getString("name");
			e->ident = tag->getString("ident");
			e->host = tag->getString("host");
			e->reason = tag->getString("reason");
			e->domain = tag->getString("domain");

			if (tag->getString("type") == "bitmask")
			{
				e->type = DNSBLConfEntry::A_BITMASK;
				e->bitmask = tag->getInt("bitmask");
			}
			else
			{
				memset(e->records, 0, sizeof(e->records));
				e->type = DNSBLConfEntry::A_RECORD;
				irc::portparser portrange(tag->getString("records"), false);
				long item = -1;
				while ((item = portrange.GetToken()))
					e->records[item] = 1;
			}

			e->banaction = str2banaction(tag->getString("action"));
			e->duration = tag->getDuration("duration", 60, 1);

			/* Use portparser for record replies */

			/* yeah, logic here is a little messy */
			if ((e->bitmask <= 0) && (DNSBLConfEntry::A_BITMASK == e->type))
			{
				std::string location = tag->getTagLocation();
				ServerInstance->SNO->WriteGlobalSno('a', "DNSBL(%s): invalid bitmask", location.c_str());
			}
			else if (e->name.empty())
			{
				std::string location = tag->getTagLocation();
				ServerInstance->SNO->WriteGlobalSno('a', "DNSBL(%s): Invalid name", location.c_str());
			}
			else if (e->domain.empty())
			{
				std::string location = tag->getTagLocation();
				ServerInstance->SNO->WriteGlobalSno('a', "DNSBL(%s): Invalid domain", location.c_str());
			}
			else if (e->banaction == DNSBLConfEntry::I_UNKNOWN)
			{
				std::string location = tag->getTagLocation();
				ServerInstance->SNO->WriteGlobalSno('a', "DNSBL(%s): Invalid banaction", location.c_str());
			}
			else
			{
				if (e->reason.empty())
				{
					std::string location = tag->getTagLocation();
					ServerInstance->SNO->WriteGlobalSno('a', "DNSBL(%s): empty reason, using defaults", location.c_str());
					e->reason = "Your IP has been blacklisted.";
				}

				/* add it, all is ok */
				DNSBLConfEntries.push_back(e);
			}
		}
	}
コード例 #4
0
ファイル: configreader.cpp プロジェクト: aszrul/inspircd
void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
{
	typedef std::map<std::string, ConnectClass*> ClassMap;
	ClassMap oldBlocksByMask;
	if (current)
	{
		for(ClassVector::iterator i = current->Classes.begin(); i != current->Classes.end(); ++i)
		{
			ConnectClass* c = *i;
			if (c->name.compare(0, 8, "unnamed-", 8))
			{
				oldBlocksByMask["n" + c->name] = c;
			}
			else if (c->type == CC_ALLOW || c->type == CC_DENY)
			{
				std::string typeMask = (c->type == CC_ALLOW) ? "a" : "d";
				typeMask += c->host;
				oldBlocksByMask[typeMask] = c;
			}
		}
	}

	size_t blk_count = config_data.count("connect");
	if (blk_count == 0)
	{
		// No connect blocks found; make a trivial default block
		ConfigItems* items;
		ConfigTag* tag = ConfigTag::create("connect", "<auto>", 0, items);
		(*items)["allow"] = "*";
		config_data.insert(std::make_pair("connect", tag));
		blk_count = 1;
	}

	Classes.resize(blk_count);
	std::map<std::string, size_t> names;

	bool try_again = true;
	for(size_t tries = 0; try_again; tries++)
	{
		try_again = false;
		ConfigTagList tags = ConfTags("connect");
		size_t i = 0;
		for(ConfigIter it = tags.first; it != tags.second; ++it, ++i)
		{
			ConfigTag* tag = it->second;
			if (Classes[i])
				continue;

			ConnectClass* parent = NULL;
			std::string parentName = tag->getString("parent");
			if (!parentName.empty())
			{
				std::map<std::string, size_t>::const_iterator parentIter = names.find(parentName);
				if (parentIter == names.end())
				{
					try_again = true;
					// couldn't find parent this time. If it's the last time, we'll never find it.
					if (tries >= blk_count)
						throw CoreException("Could not find parent connect class \"" + parentName + "\" for connect block at " + tag->getTagLocation());
					continue;
				}
				parent = Classes[parentIter->second];
			}

			std::string name = tag->getString("name");
			std::string mask, typeMask;
			char type;

			if (tag->readString("allow", mask, false))
			{
				type = CC_ALLOW;
				typeMask = 'a' + mask;
			}
			else if (tag->readString("deny", mask, false))
			{
				type = CC_DENY;
				typeMask = 'd' + mask;
			}
			else if (!name.empty())
			{
				type = CC_NAMED;
				mask = name;
				typeMask = 'n' + mask;
			}
			else
			{
				throw CoreException("Connect class must have allow, deny, or name specified at " + tag->getTagLocation());
			}

			if (name.empty())
			{
				name = "unnamed-" + ConvToStr(i);
			}
			else
			{
				typeMask = 'n' + name;
			}

			if (names.find(name) != names.end())
				throw CoreException("Two connect classes with name \"" + name + "\" defined!");
			names[name] = i;

			ConnectClass* me = parent ?
				new ConnectClass(tag, type, mask, *parent) :
				new ConnectClass(tag, type, mask);

			me->name = name;

			me->registration_timeout = tag->getDuration("timeout", me->registration_timeout);
			me->pingtime = tag->getDuration("pingfreq", me->pingtime);
			std::string sendq;
			if (tag->readString("sendq", sendq))
			{
				// attempt to guess a good hard/soft sendq from a single value
				unsigned long value = strtoul(sendq.c_str(), NULL, 10);
				if (value > 16384)
					me->softsendqmax = value / 16;
				else
					me->softsendqmax = value;
				me->hardsendqmax = value * 8;
			}
			me->softsendqmax = tag->getUInt("softsendq", me->softsendqmax);
			me->hardsendqmax = tag->getUInt("hardsendq", me->hardsendqmax);
			me->recvqmax = tag->getUInt("recvq", me->recvqmax);
			me->penaltythreshold = tag->getUInt("threshold", me->penaltythreshold);
			me->commandrate = tag->getUInt("commandrate", me->commandrate);
			me->fakelag = tag->getBool("fakelag", me->fakelag);
			me->maxlocal = tag->getUInt("localmax", me->maxlocal);
			me->maxglobal = tag->getUInt("globalmax", me->maxglobal);
			me->maxchans = tag->getUInt("maxchans", me->maxchans);
			me->maxconnwarn = tag->getBool("maxconnwarn", me->maxconnwarn);
			me->limit = tag->getUInt("limit", me->limit);
			me->resolvehostnames = tag->getBool("resolvehostnames", me->resolvehostnames);

			std::string ports = tag->getString("port");
			if (!ports.empty())
			{
				irc::portparser portrange(ports, false);
				while (int port = portrange.GetToken())
					me->ports.insert(port);
			}

			ClassMap::iterator oldMask = oldBlocksByMask.find(typeMask);
			if (oldMask != oldBlocksByMask.end())
			{
				ConnectClass* old = oldMask->second;
				oldBlocksByMask.erase(oldMask);
				old->Update(me);
				delete me;
				me = old;
			}
			Classes[i] = me;
		}
	}
}
コード例 #5
0
ファイル: cmd_who.cpp プロジェクト: Cronus89/inspircd
bool CommandWho::whomatch(User* cuser, User* user, const char* matchtext)
{
	bool match = false;
	bool positive = false;

	if (user->registered != REG_ALL)
		return false;

	if (opt_local && !IS_LOCAL(user))
		return false;
	else if (opt_far && IS_LOCAL(user))
		return false;

	if (opt_mode)
	{
		for (const char* n = matchtext; *n; n++)
		{
			if (*n == '+')
			{
				positive = true;
				continue;
			}
			else if (*n == '-')
			{
				positive = false;
				continue;
			}
			if (user->IsModeSet(*n) != positive)
				return false;
		}
		return true;
	}
	else
	{
		/*
		 * This was previously one awesome pile of ugly nested if, when really, it didn't need
		 * to be, since only one condition was ever checked, a chained if works just fine.
		 * -- w00t
		 */
		if (opt_metadata)
		{
			match = false;
			const Extensible::ExtensibleStore& list = user->GetExtList();
			for(Extensible::ExtensibleStore::const_iterator i = list.begin(); i != list.end(); ++i)
				if (InspIRCd::Match(i->first->name, matchtext))
					match = true;
		}
		else if (opt_realname)
			match = InspIRCd::Match(user->fullname, matchtext);
		else if (opt_showrealhost)
			match = InspIRCd::Match(user->host, matchtext, ascii_case_insensitive_map);
		else if (opt_ident)
			match = InspIRCd::Match(user->ident, matchtext, ascii_case_insensitive_map);
		else if (opt_port)
		{
			irc::portparser portrange(matchtext, false);
			long portno = -1;
			while ((portno = portrange.GetToken()))
				if (IS_LOCAL(user) && portno == IS_LOCAL(user)->GetServerPort())
				{
					match = true;
					break;
				}
		}
		else if (opt_away)
			match = InspIRCd::Match(user->awaymsg, matchtext);
		else if (opt_time)
		{
			long seconds = InspIRCd::Duration(matchtext);

			// Okay, so time matching, we want all users connected `seconds' ago
			if (user->age >= ServerInstance->Time() - seconds)
				match = true;
		}

		/*
		 * Once the conditionals have been checked, only check dhost/nick/server
		 * if they didn't match this user -- and only match if we don't find a match.
		 *
		 * This should make things minutely faster, and again, less ugly.
		 * -- w00t
		 */
		if (!match)
			match = InspIRCd::Match(user->dhost, matchtext, ascii_case_insensitive_map);

		if (!match)
			match = InspIRCd::Match(user->nick, matchtext);

		/* Don't allow server name matches if HideWhoisServer is enabled, unless the command user has the priv */
		if (!match && (ServerInstance->Config->HideWhoisServer.empty() || cuser->HasPrivPermission("users/auspex")))
			match = InspIRCd::Match(user->server, matchtext);

		return match;
	}
}