summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-10-22 00:54:30 -0400
committerAdam <Adam@anope.org>2012-10-22 00:54:30 -0400
commit0b9db15efc322336ddb08671ce68a3d45fb22520 (patch)
tree2e8149f370c63f08f2f197eaa92b1b36e857b0e9 /src
parentd5b2f9cfa78ed176ffe1d9f2923799fdd37217a5 (diff)
Add os_dns, a way to control your DNS zone via services
Diffstat (limited to 'src')
-rw-r--r--src/config.cpp39
-rw-r--r--src/dns.cpp94
-rw-r--r--src/init.cpp18
-rw-r--r--src/main.cpp11
-rw-r--r--src/users.cpp5
5 files changed, 110 insertions, 57 deletions
diff --git a/src/config.cpp b/src/config.cpp
index b90c8598a..6347754fb 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -17,6 +17,14 @@
#include "opertype.h"
#include "channels.h"
#include "hashcomp.h"
+#include "dns.h"
+
+#ifndef _WIN32
+#include <errno.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#endif
/*************************************************************************/
@@ -200,6 +208,9 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C
this->NameServer = "127.0.0.1";
}
}
+ if (DNSEngine)
+ DNSEngine->SetFlag(SF_DEAD);
+ DNSEngine = new DNSManager(this->NameServer, this->DNSPort);
if (this->CaseMap == "ascii")
Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>());
@@ -219,6 +230,31 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C
if (this->SessionIPv4CIDR > 32 || this->SessionIPv6CIDR > 128)
throw ConfigException("Session CIDR value out of range");
+
+#ifndef _WIN32
+ if (!this->User.empty())
+ {
+ errno = 0;
+ struct passwd *u = getpwnam(this->User.c_str());
+ if (u == NULL)
+ Log() << "Unable to setuid to " << this->User << ": " << Anope::LastError();
+ else if (setuid(u->pw_uid) == -1)
+ Log() << "Unable to setuid to " << this->User << ": " << Anope::LastError();
+ else
+ Log() << "Successfully set user to " << this->User;
+ }
+ if (!this->Group.empty())
+ {
+ errno = 0;
+ struct group *g = getgrnam(this->Group.c_str());
+ if (g == NULL)
+ Log() << "Unable to setgid to " << this->Group << ": " << Anope::LastError();
+ else if (setuid(g->gr_gid) == -1)
+ Log() << "Unable to setgid to " << this->Group << ": " << Anope::LastError();
+ else
+ Log() << "Successfully set group to " << this->Group;
+ }
+#endif
}
bool ServerConfig::CheckOnce(const Anope::string &tag)
@@ -1191,6 +1227,8 @@ ConfigItems::ConfigItems(ServerConfig *conf)
{"networkinfo", "userlen", "10", new ValueContainerUInt(&conf->UserLen), DT_UINTEGER | DT_NORELOAD, NoValidation},
{"networkinfo", "hostlen", "64", new ValueContainerUInt(&conf->HostLen), DT_UINTEGER | DT_NORELOAD, NoValidation},
{"networkinfo", "chanlen", "32", new ValueContainerUInt(&conf->ChanLen), DT_UINTEGER | DT_NORELOAD, NoValidation},
+ {"options", "user", "", new ValueContainerString(&conf->User), DT_STRING, NoValidation},
+ {"options", "group", "", new ValueContainerString(&conf->Group), DT_STRING, NoValidation},
{"options", "casemap", "ascii", new ValueContainerString(&conf->CaseMap), DT_STRING, NoValidation},
{"options", "passlen", "32", new ValueContainerUInt(&conf->PassLen), DT_UINTEGER | DT_NORELOAD, NoValidation},
{"options", "seed", "0", new ValueContainerLUInt(&conf->Seed), DT_LUINTEGER, NoValidation},
@@ -1264,6 +1302,7 @@ ConfigItems::ConfigItems(ServerConfig *conf)
{"mail", "memo_message", "", new ValueContainerString(&conf->MailMemoMessage), DT_STRING | DT_ALLOW_NEWLINE, ValidateMail},
{"dns", "nameserver", "127.0.0.1", new ValueContainerString(&conf->NameServer), DT_STRING, NoValidation},
{"dns", "timeout", "5", new ValueContainerTime(&conf->DNSTimeout), DT_TIME, NoValidation},
+ {"dns", "port", "53", new ValueContainerInt(&conf->DNSPort), DT_INTEGER, NoValidation},
{"chanserv", "name", "", new ValueContainerString(&conf->ChanServ), DT_STRING, NoValidation},
{"chanserv", "defaults", "keeptopic secure securefounder signkick", new ValueContainerString(&CSDefaults), DT_STRING, ValidateChanServ},
{"chanserv", "maxregistered", "0", new ValueContainerUInt(&conf->CSMaxReg), DT_UINTEGER, ValidateChanServ},
diff --git a/src/dns.cpp b/src/dns.cpp
index f21453ddd..519e02b8f 100644
--- a/src/dns.cpp
+++ b/src/dns.cpp
@@ -56,20 +56,11 @@ DNSQuery::DNSQuery(const Question &q)
this->error = DNS_ERROR_NONE;
}
-DNSQuery::DNSQuery(const DNSPacket &p)
-{
- this->questions = p.questions;
- this->answers = p.answers;
- this->authorities = p.authorities;
- this->additional = p.additional;
- this->error = DNS_ERROR_NONE;
-}
-
DNSRequest::DNSRequest(const Anope::string &addr, QueryType qt, bool cache, Module *c) : Timer(Config->DNSTimeout), Question(addr, qt), use_cache(cache), id(0), creator(c)
{
if (!DNSEngine)
- DNSEngine = new DNSManager(Config->NameServer, DNSManager::DNSPort);
- if (DNSEngine->packets.size() == 65535)
+ throw SocketException("No DNSEngine");
+ if (DNSEngine->GetPackets().size() == 65535)
throw SocketException("DNS queue full");
do
@@ -101,14 +92,12 @@ void DNSRequest::Process()
return;
}
- DNSPacket *p = new DNSPacket();
+ DNSPacket *p = new DNSPacket(DNSEngine->addrs);
p->flags = DNS_QUERYFLAGS_RD;
p->id = this->id;
p->questions.push_back(*this);
- DNSEngine->packets.push_back(p);
-
- SocketEngine::MarkWritable(DNSEngine);
+ DNSEngine->SendPacket(p);
}
void DNSRequest::OnError(const DNSQuery *r)
@@ -239,12 +228,12 @@ ResourceRecord DNSPacket::UnpackResourceRecord(const unsigned char *input, unsig
if (pos + 4 > input_size)
throw SocketException("Unable to unpack resource record");
- in_addr addr;
- addr.s_addr = input[pos] | (input[pos + 1] << 8) | (input[pos + 2] << 16) | (input[pos + 3] << 24);
+ in_addr a;
+ a.s_addr = input[pos] | (input[pos + 1] << 8) | (input[pos + 2] << 16) | (input[pos + 3] << 24);
pos += 4;
sockaddrs addrs;
- addrs.ntop(AF_INET, &addr);
+ addrs.ntop(AF_INET, &a);
record.rdata = addrs.addr();
break;
@@ -254,13 +243,13 @@ ResourceRecord DNSPacket::UnpackResourceRecord(const unsigned char *input, unsig
if (pos + 16 > input_size)
throw SocketException("Unable to unpack resource record");
- in6_addr addr;
+ in6_addr a;
for (int j = 0; j < 16; ++j)
- addr.s6_addr[j] = input[pos + j];
+ a.s6_addr[j] = input[pos + j];
pos += 16;
sockaddrs addrs;
- addrs.ntop(AF_INET6, &addr);
+ addrs.ntop(AF_INET6, &a);
record.rdata = addrs.addr();
break;
@@ -280,9 +269,8 @@ ResourceRecord DNSPacket::UnpackResourceRecord(const unsigned char *input, unsig
return record;
}
-DNSPacket::DNSPacket() : DNSQuery()
+DNSPacket::DNSPacket(const sockaddrs &a) : DNSQuery(), addr(a), id(0), flags(0)
{
- this->id = this->flags = 0;
}
void DNSPacket::Fill(const unsigned char *input, const unsigned short len)
@@ -426,13 +414,13 @@ unsigned short DNSPacket::Pack(unsigned char *output, unsigned short output_size
if (pos + 6 > output_size)
throw SocketException("Unable to pack packet");
- sockaddrs addr(rr.rdata);
+ sockaddrs a(rr.rdata);
s = htons(4);
memcpy(&output[pos], &s, 2);
pos += 2;
- memcpy(&output[pos], &addr.sa4.sin_addr, 4);
+ memcpy(&output[pos], &a.sa4.sin_addr, 4);
pos += 4;
break;
}
@@ -441,13 +429,13 @@ unsigned short DNSPacket::Pack(unsigned char *output, unsigned short output_size
if (pos + 18 > output_size)
throw SocketException("Unable to pack packet");
- sockaddrs addr(rr.rdata);
+ sockaddrs a(rr.rdata);
s = htons(16);
memcpy(&output[pos], &s, 2);
pos += 2;
- memcpy(&output[pos], &addr.sa6.sin6_addr, 16);
+ memcpy(&output[pos], &a.sa6.sin6_addr, 16);
pos += 16;
break;
}
@@ -477,6 +465,15 @@ unsigned short DNSPacket::Pack(unsigned char *output, unsigned short output_size
DNSManager::DNSManager(const Anope::string &nameserver, int port) : Timer(300, Anope::CurTime, true), Socket(-1, nameserver.find(':') != Anope::string::npos, SOCK_DGRAM)
{
this->addrs.pton(this->IPv6 ? AF_INET6 : AF_INET, nameserver, port);
+ try
+ {
+ this->Bind("0.0.0.0", port);
+ }
+ catch (const SocketException &ex)
+ {
+ /* This error can be from normal operation as most people don't use services to handle DNS queries, so put it in debug log */
+ Log(LOG_DEBUG) << "Unable to bind DNSManager to port " << port << ": " << ex.GetReason();
+ }
}
DNSManager::~DNSManager()
@@ -514,13 +511,7 @@ bool DNSManager::ProcessRead()
if (length < DNSPacket::HEADER_LENGTH)
return true;
- if (this->addrs != from_server)
- {
- Log(LOG_DEBUG_2) << "Resolver: Received an answer from the wrong nameserver, Bad NAT or DNS forging attempt? '" << this->addrs.addr() << "' != '" << from_server.addr() << "'";
- return true;
- }
-
- DNSPacket recv_packet;
+ DNSPacket recv_packet(from_server);
try
{
@@ -532,6 +523,18 @@ bool DNSManager::ProcessRead()
return true;
}
+ if (!(recv_packet.flags & DNS_QUERYFLAGS_QR))
+ {
+ FOREACH_MOD(I_OnDnsRequest, OnDnsRequest(recv_packet));
+ return true;
+ }
+
+ if (this->addrs != from_server)
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received an answer from the wrong nameserver, Bad NAT or DNS forging attempt? '" << this->addrs.addr() << "' != '" << from_server.addr() << "'";
+ return true;
+ }
+
std::map<unsigned short, DNSRequest *>::iterator it = DNSEngine->requests.find(recv_packet.id);
if (it == DNSEngine->requests.end())
{
@@ -540,13 +543,7 @@ bool DNSManager::ProcessRead()
}
DNSRequest *request = it->second;
- if (!(recv_packet.flags & DNS_QUERYFLAGS_QR))
- {
- Log(LOG_DEBUG_2) << "Resolver: Received a non-answer";
- recv_packet.error = DNS_ERROR_NOT_AN_ANSWER;
- request->OnError(&recv_packet);
- }
- else if (recv_packet.flags & DNS_QUERYFLAGS_OPCODE)
+ if (recv_packet.flags & DNS_QUERYFLAGS_OPCODE)
{
Log(LOG_DEBUG_2) << "Resolver: Received a nonstandard query";
recv_packet.error = DNS_ERROR_NONSTANDARD_QUERY;
@@ -614,7 +611,7 @@ bool DNSManager::ProcessWrite()
unsigned char buffer[524];
unsigned short len = r->Pack(buffer, sizeof(buffer));
- sendto(this->GetFD(), reinterpret_cast<char *>(buffer), len, 0, &this->addrs.sa, this->addrs.size());
+ sendto(this->GetFD(), reinterpret_cast<char *>(buffer), len, 0, &r->addr.sa, r->addr.size());
}
catch (const SocketException &) { }
@@ -698,6 +695,19 @@ void DNSManager::Cleanup(Module *mod)
}
}
+std::deque<DNSPacket *>& DNSManager::GetPackets()
+{
+ return this->packets;
+}
+
+void DNSManager::SendPacket(DNSPacket *p)
+{
+ Log(LOG_DEBUG_2) << "Resolver: Queueing packet " << p->id;
+ this->packets.push_back(p);
+
+ SocketEngine::MarkWritable(this);
+}
+
DNSQuery DNSManager::BlockingQuery(const Anope::string &mask, QueryType qt)
{
Question question(mask, qt);
diff --git a/src/init.cpp b/src/init.cpp
index 4f0f8bac3..c2c44ec16 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -422,6 +422,9 @@ void Init(int ac, char **av)
Log(LOG_TERMINAL) << "Using configuration file " << conf_dir << "/" << services_conf.GetName();
#endif
+ /* Initialize the socket engine */
+ SocketEngine::Init();
+
/* Read configuration file; exit if there are problems. */
try
{
@@ -441,6 +444,15 @@ void Init(int ac, char **av)
if (!SupportedWindowsVersion())
throw FatalException(GetWindowsVersion() + " is not a supported version of Windows");
#else
+ /* If we're root, issue a warning now */
+ if (!getuid() && !getgid())
+ {
+ std::cerr << "WARNING: You are currently running Anope as the root superuser. Anope does not" << std::endl;
+ std::cerr << " require root privileges to run, and it is discouraged that you run Anope" << std::endl;
+ std::cerr << " as the root superuser." << std::endl;
+ sleep(3);
+ }
+
if (!nofork && AtTerm())
{
/* Install these before fork() - it is possible for the child to
@@ -478,16 +490,16 @@ void Init(int ac, char **av)
}
#endif
- /* Initialize the socket engine */
- SocketEngine::Init();
-
/* Write our PID to the PID file. */
write_pidfile();
/* Create me */
Me = new Server(NULL, Config->ServerName, 0, Config->ServerDesc, Config->Numeric);
for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ {
it->second->server = Me;
+ ++Me->Users;
+ }
/* Announce ourselves to the logfile. */
Log() << "Anope " << Anope::Version() << " starting up" << (debug || readonly ? " (options:" : "") << (debug ? " debug" : "") << (readonly ? " readonly" : "") << (debug || readonly ? ")" : "");
diff --git a/src/main.cpp b/src/main.cpp
index d43bda2bc..26e7e67ff 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -362,17 +362,6 @@ Anope::string GetFullProgDir(const Anope::string &argv0)
int main(int ac, char **av, char **envp)
{
-#ifndef _WIN32
- /* If we're root, issue a warning now */
- if (!getuid() && !getgid())
- {
- std::cerr << "WARNING: You are currently running Anope as the root superuser. Anope does not" << std::endl;
- std::cerr << " require root privileges to run, and it is discouraged that you run Anope" << std::endl;
- std::cerr << " as the root superuser." << std::endl;
- sleep(3);
- }
-#endif
-
binary_dir = GetFullProgDir(av[0]);
if (binary_dir[binary_dir.length() - 1] == '.')
binary_dir = binary_dir.substr(0, binary_dir.length() - 2);
diff --git a/src/users.cpp b/src/users.cpp
index fac00d723..187e55808 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -66,7 +66,10 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
this->nc = NULL;
if (sserver) // Our bots are introduced on startup with no server
+ {
+ ++sserver->Users;
Log(this, "connect") << (!svhost.empty() ? Anope::string("(") + svhost + ") " : "") << "(" << srealname << ") " << sip << " connected to the network (" << sserver->GetName() << ")";
+ }
++usercnt;
if (usercnt > maxusercnt)
@@ -241,7 +244,7 @@ User::~User()
Log(LOG_DEBUG_2) << "User::~User() called";
Log(this, "disconnect") << "(" << this->realname << ") " << "disconnected from the network (" << this->server->GetName() << ")";
-
+ --this->server->Users;
FOREACH_MOD(I_OnUserLogoff, OnUserLogoff(this));