summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2010-09-09 23:43:11 -0400
committerAdam <Adam@anope.org>2010-09-09 23:43:11 -0400
commit46813ccb8c6ab572b8a9ff0a39afb1d92dc4482b (patch)
tree562da502a102230ce207bbe921fdc978ee71e20c /src
parentfdd196e50b4616ac377bd0ee0ae5ce6c57b657ee (diff)
Added an asynchronous DNS system and m_dnsbl, which checks clients against DNS blacklists.
Rewrote internal handling of IPs, we now properly support users using IPv6. Fixed a few problems with the UnrealIRCd protocol module.
Diffstat (limited to 'src')
-rw-r--r--src/actions.cpp19
-rw-r--r--src/base64.cpp14
-rw-r--r--src/channels.cpp24
-rw-r--r--src/config.cpp32
-rw-r--r--src/dns.cpp550
-rw-r--r--src/init.cpp9
-rw-r--r--src/logger.cpp2
-rw-r--r--src/main.cpp5
-rw-r--r--src/misc.cpp63
-rw-r--r--src/operserv.cpp20
-rw-r--r--src/servers.cpp9
-rw-r--r--src/sockets.cpp288
-rw-r--r--src/users.cpp39
13 files changed, 791 insertions, 283 deletions
diff --git a/src/actions.cpp b/src/actions.cpp
index bdc5a041d..92ecca132 100644
--- a/src/actions.cpp
+++ b/src/actions.cpp
@@ -73,8 +73,7 @@ void kill_user(const Anope::string &source, const Anope::string &user, const Ano
*/
void common_unban(ChannelInfo *ci, const Anope::string &nick)
{
- Anope::string host;
- uint32 ip = 0;
+ //uint32 ip = 0;
User *u;
Entry *ban, *next;
@@ -87,27 +86,13 @@ void common_unban(ChannelInfo *ci, const Anope::string &nick)
if (!ci->c->bans || !ci->c->bans->count)
return;
- if (u->hostip.empty())
- {
- host = host_resolve(u->host);
- /* we store the just resolved hostname so we don't
- * need to do this again */
- if (!host.empty())
- u->hostip = host;
- }
- else
- host = u->hostip;
- /* Convert the host to an IP.. */
- if (!host.empty())
- ip = str_is_ip(host);
-
if (ircd->svsmode_unban)
ircdproto->SendBanDel(ci->c, nick);
else
for (ban = ci->c->bans->entries; ban; ban = next)
{
next = ban->next;
- if (entry_match(ban, u->nick, u->GetIdent(), u->host, ip) || entry_match(ban, u->nick, u->GetIdent(), u->GetDisplayedHost(), ip))
+ if (entry_match(ban, u->nick, u->GetIdent(), u->host, /*ip XXX */ 0) || entry_match(ban, u->nick, u->GetIdent(), u->GetDisplayedHost(), /*ip XXX */0))
ci->c->RemoveMode(NULL, CMODE_BAN, ban->mask);
}
}
diff --git a/src/base64.cpp b/src/base64.cpp
index 4f51eb5e8..cddfb273f 100644
--- a/src/base64.cpp
+++ b/src/base64.cpp
@@ -161,17 +161,3 @@ void b64_decode(const Anope::string &src, Anope::string &target)
target.erase(target.length() - 1);
}
-int decode_ip(const Anope::string &buf)
-{
- int len = buf.length();
- Anope::string targ;
-
- b64_decode(buf, targ);
- const struct in_addr ia = *reinterpret_cast<const struct in_addr *>(targ.c_str());
- if (len == 24) /* IPv6 */
- return 0;
- else if (len == 8) /* IPv4 */
- return ia.s_addr;
- else /* Error?? */
- return 0;
-}
diff --git a/src/channels.cpp b/src/channels.cpp
index 389577f71..882dc887a 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -1765,33 +1765,17 @@ Entry *elist_match_mask(EList *list, const Anope::string &mask, uint32 ip)
Entry *elist_match_user(EList *list, User *u)
{
Entry *res;
- Anope::string host;
- uint32 ip = 0;
+ //uint32 ip = 0;
if (!list || !list->entries || !u)
return NULL;
- if (u->hostip.empty())
- {
- host = host_resolve(u->host);
- /* we store the just resolved hostname so we don't
- * need to do this again */
- if (!host.empty())
- u->hostip = host;
- }
- else
- host = u->hostip;
-
- /* Convert the host to an IP.. */
- if (!host.empty())
- ip = str_is_ip(host);
-
/* Match what we ve got against the lists.. */
- res = elist_match(list, u->nick, u->GetIdent(), u->host, ip);
+ res = elist_match(list, u->nick, u->GetIdent(), u->host, /*ip XXX*/0);
if (!res)
- res = elist_match(list, u->nick, u->GetIdent(), u->GetDisplayedHost(), ip);
+ res = elist_match(list, u->nick, u->GetIdent(), u->GetDisplayedHost(), /*ip XXX*/0);
if (!res && !u->GetCloakedHost().empty() && !u->GetCloakedHost().equals_cs(u->GetDisplayedHost()))
- res = elist_match(list, u->nick, u->GetIdent(), u->GetCloakedHost(), ip);
+ res = elist_match(list, u->nick, u->GetIdent(), u->GetCloakedHost(), /*ip XXX*/ 0);
return res;
}
diff --git a/src/config.cpp b/src/config.cpp
index d43f97e6f..d8ac4f863 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -349,6 +349,36 @@ ServerConfig::ServerConfig() : errstr(""), config_data()
}
SetDefaultMLock(this);
+
+ if (IsFile(this->NameServer))
+ {
+ std::ifstream f(this->NameServer.c_str());
+ Anope::string server;
+ bool success = false;
+
+ while (f.is_open() && getline(f, server.str()))
+ {
+ if (server.find("nameserver ") == 0 && getline(f, server.str()))
+ {
+ if (server.substr(11).is_pos_number_only())
+ {
+ this->NameServer = server.substr(11);
+ Log(LOG_DEBUG) << "Nameserver set to " << this->NameServer;
+ success = true;
+ break;
+ }
+ }
+ }
+
+ if (f.is_open())
+ f.close();
+
+ if (!success)
+ {
+ Log() << "Unable to find nameserver, defaulting to 127.0.0.1";
+ this->NameServer = "127.0.0.1";
+ }
+ }
}
bool ServerConfig::CheckOnce(const Anope::string &tag)
@@ -1053,6 +1083,8 @@ void ServerConfig::Read()
{"mail", "restrict", "no", new ValueContainerBool(&this->RestrictMail), DT_BOOLEAN, NoValidation},
{"mail", "delay", "0", new ValueContainerTime(&this->MailDelay), DT_TIME, NoValidation},
{"mail", "dontquoteaddresses", "no", new ValueContainerBool(&this->DontQuoteAddresses), DT_BOOLEAN, NoValidation},
+ {"dns", "nameserver", "127.0.0.1", new ValueContainerString(&this->NameServer), DT_STRING, NoValidation},
+ {"dns", "timeout", "5", new ValueContainerTime(&this->DNSTimeout), DT_TIME, NoValidation},
{"chanserv", "nick", "ChanServ", new ValueContainerString(&this->s_ChanServ), DT_STRING | DT_NORELOAD, ValidateNotEmpty},
{"chanserv", "description", "Channel Registration Service", new ValueContainerString(&this->desc_ChanServ), DT_STRING | DT_NORELOAD, ValidateNotEmpty},
{"chanserv", "modules", "", new ValueContainerString(&ChanCoreModules), DT_STRING, NoValidation},
diff --git a/src/dns.cpp b/src/dns.cpp
new file mode 100644
index 000000000..51cd14938
--- /dev/null
+++ b/src/dns.cpp
@@ -0,0 +1,550 @@
+#include "services.h"
+
+DNSManager *DNSEngine;
+
+static inline unsigned short GetRandomID()
+{
+ return random();
+}
+
+DNSRequest::DNSRequest(const Anope::string &addr, QueryType qt, bool cache) : address(addr), QT(qt)
+{
+ if (!DNSEngine)
+ DNSEngine = new DNSManager();
+ if (DNSEngine->packets.size() == 65535)
+ throw SocketException("DNS queue full");
+
+ Log(LOG_DEBUG_2) << "Resolver: Processing request to lookup " << addr << ", of type " << qt;
+
+ if (cache && DNSEngine->CheckCache(this))
+ {
+ delete this;
+ return;
+ }
+
+ DNSPacket *p = new DNSPacket();
+
+ while (DNSEngine->requests.count((p->id = GetRandomID())));
+
+ DNSEngine->requests[p->id] = this;
+ DNSEngine->packets.push_back(p);
+
+ p->flags = DNS_QUERYFLAGS_RD;
+ if (!p->AddQuestion(addr, qt))
+ {
+ delete this;
+ return;
+ }
+
+ SocketEngine->MarkWritable(DNSEngine->sock);
+
+ this->timeout = new DNSRequestTimeout(this, Config->DNSTimeout);
+}
+
+DNSRequest::~DNSRequest()
+{
+ if (!this->timeout->done)
+ {
+ delete this->timeout;
+ }
+}
+
+void DNSRequest::OnError(DNSError error, const Anope::string &message)
+{
+}
+
+inline DNSPacket::DNSPacket()
+{
+ this->id = this->flags = this->qdcount = this->ancount = this->nscount = this->arcount = this->payload_count = 0;
+ memset(&this->payload, 0, sizeof(this->payload));
+}
+
+bool DNSPacket::AddQuestion(const Anope::string &name, const QueryType qt)
+{
+ unsigned char temp_buffer[512] = "";
+ unsigned short buffer_pos = 0;
+
+ Anope::string working_name = name;
+
+ switch (qt)
+ {
+ case DNS_QUERY_PTR:
+ {
+ if (working_name.find(':') != Anope::string::npos)
+ {
+ in6_addr ip;
+ if (!inet_pton(AF_INET6, working_name.c_str(), &ip))
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received an invalid IP for PTR lookup (" << working_name << "): " << strerror(errno);
+ return false;
+ }
+
+ static const char *const hex = "0123456789abcdef";
+ char reverse_ip[128];
+ unsigned reverse_ip_count = 0;
+ for (int i = 15; i >= 0; --i)
+ {
+ reverse_ip[reverse_ip_count++] = hex[ip.s6_addr[i] & 0xF];
+ reverse_ip[reverse_ip_count++] = '.';
+ reverse_ip[reverse_ip_count++] = hex[ip.s6_addr[i] >> 4];
+ reverse_ip[reverse_ip_count++] = '.';
+ }
+ reverse_ip[reverse_ip_count++] = 0;
+
+ working_name = reverse_ip;
+ working_name += "ip6.arpa";
+ Log(LOG_DEBUG_2) << "IP changed to in6.arpa format: " << working_name;
+ }
+ else
+ {
+ in_addr ip;
+ if (!inet_pton(AF_INET, working_name.c_str(), &ip))
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received an invalid IP for PTR lookup (" << working_name << "): " << strerror(errno);
+ return false;
+ }
+ unsigned long reverse_ip = ((ip.s_addr & 0xFF) << 24) | ((ip.s_addr & 0xFF00) << 8) | ((ip.s_addr & 0xFF0000) >> 8) | ((ip.s_addr & 0xFF000000) >> 24);
+ char ipbuf[INET_ADDRSTRLEN];
+ if (!inet_ntop(AF_INET, &reverse_ip, ipbuf, sizeof(ipbuf)))
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Reformatted IP " << working_name << " back into an invalid IP: " << strerror(errno);
+ return false;
+ }
+
+ working_name = ipbuf;
+ working_name += ".in-addr.arpa";
+ Log(LOG_DEBUG_2) << "IP changed to in-addr.arpa format: " << working_name;
+ }
+ }
+ case DNS_QUERY_CNAME:
+ case DNS_QUERY_A:
+ case DNS_QUERY_AAAA:
+ {
+ sepstream sep(working_name, '.');
+ Anope::string token;
+ while (sep.GetToken(token))
+ {
+ temp_buffer[buffer_pos++] = token.length();
+ memcpy(&temp_buffer[buffer_pos], token.c_str(), token.length());
+ buffer_pos += token.length();
+ }
+ break;
+ }
+ default:
+ Log(LOG_DEBUG_2) << "Resolver: Received an unknown query type format " << qt;
+ return false;
+ }
+
+ temp_buffer[buffer_pos++] = 0;
+
+ short i = htons(qt);
+ memcpy(&temp_buffer[buffer_pos], &i, 2);
+ buffer_pos += 2;
+
+ i = htons(1);
+ memcpy(&temp_buffer[buffer_pos], &i, 2);
+ buffer_pos += 2;
+
+ Log(LOG_DEBUG_3) << "Resolver: Packet payload to: " << temp_buffer;
+ Log(LOG_DEBUG_3) << "Resolver: Bytes used: " << buffer_pos << ", payload count " << this->payload_count;
+
+ if (buffer_pos > (sizeof(this->payload) - this->payload_count))
+ return false;
+
+ memmove(this->payload + this->payload_count, temp_buffer, buffer_pos);
+ this->payload_count += buffer_pos;
+
+ this->qdcount++;
+
+ return true;
+}
+
+inline void DNSPacket::FillPacket(const unsigned char *input, const size_t length)
+{
+ this->id = (input[0] << 8) | input[1];
+ this->flags = (input[2] << 8) | input[3];
+ this->qdcount = (input[4] << 8) | input[5];
+ this->ancount = (input[6] << 8) | input[7];
+ this->nscount = (input[8] << 8) | input[9];
+ this->arcount = (input[10] << 8) | input[11];
+ memcpy(this->payload, &input[12], length);
+ this->payload_count = length;
+}
+
+inline void DNSPacket::FillBuffer(unsigned char *buffer)
+{
+ buffer[0] = this->id >> 8;
+ buffer[1] = this->id & 0xFF;
+ buffer[2] = this->flags >> 8;
+ buffer[3] = this->flags & 0xFF;
+ buffer[4] = this->qdcount >> 8;
+ buffer[5] = this->qdcount & 0xFF;
+ buffer[6] = this->ancount >> 8;
+ buffer[7] = this->ancount & 0xFF;
+ buffer[8] = this->nscount >> 8;
+ buffer[9] = this->nscount & 0xFF;
+ buffer[10] = this->arcount >> 8;
+ buffer[11] = this->arcount & 0xFF;
+ memcpy(&buffer[12], this->payload, this->payload_count);
+}
+
+inline DNSRecord::DNSRecord()
+{
+ this->type = DNS_QUERY_NONE;
+ this->record_class = this->ttl = this->rdlength = 0;
+ this->created = time(NULL);
+}
+
+DNSSocket::DNSSocket(const Anope::string &nTargetHost, int nPort) : ClientSocket(nTargetHost, nPort, "", false, SOCK_DGRAM)
+{
+ this->server_addr.pton(AF_INET, TargetHost, Port);
+}
+
+DNSSocket::~DNSSocket()
+{
+ Log() << "Resolver: Lost connection to nameserver";
+ DNSEngine->sock = NULL;
+}
+
+int DNSSocket::SendTo(const unsigned char *buf, size_t len) const
+{
+ return sendto(this->GetSock(), buf, len, 0, &this->server_addr.sa, this->server_addr.size());
+}
+
+int DNSSocket::RecvFrom(char *buf, size_t len, sockaddrs &addrs) const
+{
+ socklen_t x = sizeof(addrs);
+ return recvfrom(this->GetSock(), buf, len, 0, &addrs.sa, &x);
+}
+
+bool DNSSocket::ProcessRead()
+{
+ Log(LOG_DEBUG_2) << "Resolver: Reading from UDP socket";
+
+ sockaddrs from_server;
+ unsigned char packet_buffer[524];
+ int length = this->RecvFrom(reinterpret_cast<char *>(&packet_buffer), sizeof(packet_buffer), from_server);
+
+ if (length < 0)
+ return false;
+
+ if (this->server_addr != from_server)
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received an answer from the wrong nameserver, Bad NAT or DNS forging attempt? '" << this->server_addr.addr() << "' != '" << from_server.addr() << "'";
+ return true;
+ }
+
+ if (length < 12)
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received a corrupted packet";
+ return true;
+ }
+
+ /* Remove header length */
+ length -= 12;
+
+ DNSPacket recv_packet;
+ recv_packet.FillPacket(packet_buffer, length);
+
+ std::map<short, DNSRequest *>::iterator it = DNSEngine->requests.find(recv_packet.id);
+ if (it == DNSEngine->requests.end())
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received an answer for something we didn't request";
+ return true;
+ }
+ DNSRequest *request = it->second;
+ DNSEngine->requests.erase(it);
+
+ if (!(recv_packet.flags & DNS_QUERYFLAGS_QR))
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received a non-answer";
+ request->OnError(DNS_ERROR_NOT_AN_ANSWER, "Received a non-answer");
+ }
+ else if (recv_packet.flags & DNS_QUERYFLAGS_OPCODE)
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received a nonstandard query";
+ request->OnError(DNS_ERROR_NONSTANDARD_QUERY, "Received a nonstandard query");
+ }
+ else if (recv_packet.flags & DNS_QUERYFLAGS_RCODE)
+ {
+ switch (recv_packet.flags & DNS_QUERYFLAGS_RCODE)
+ {
+ case 1:
+ Log(LOG_DEBUG_2) << "Resolver: Format error";
+ request->OnError(DNS_ERROR_FORMAT_ERROR, "Format error");
+ break;
+ case 2:
+ Log(LOG_DEBUG_2) << "Resolver: Server failure";
+ request->OnError(DNS_ERROR_SERVER_FAILURE, "Server failure");
+ break;
+ case 3:
+ Log(LOG_DEBUG_2) << "Resolver: Domain name not found";
+ request->OnError(DNS_ERROR_DOMAIN_NOT_FOUND, "Domain not found");
+ break;
+ case 4:
+ Log(LOG_DEBUG_2) << "Resolver: Not Implemented - The name server does not support the requested kind of query.";
+ request->OnError(DNS_ERROR_NOT_IMPLEMENTED, "Not Implemented - The name server does not support the requested kind of query.");
+ break;
+ case 5:
+ Log(LOG_DEBUG_2) << "Resolver: Server refused to perform the specificed operation";
+ request->OnError(DNS_ERROR_REFUSED, "Server refused to perform the specified operation");
+ break;
+ default:
+ Log(LOG_DEBUG_2) << "Resolver: Unknown error";
+ request->OnError(DNS_ERROR_UNKNOWN, "Unknown error");
+ }
+ }
+ else if (recv_packet.ancount < 1)
+ {
+ Log(LOG_DEBUG_2) << "Resolver: No resource records returned";
+ request->OnError(DNS_ERROR_NO_RECORDS, "No resource records returned");
+ }
+ else
+ {
+ unsigned packet_pos = 0;
+
+ /* Skip over the questions in this reponse */
+ for (unsigned qdcount = 0; qdcount < recv_packet.qdcount; ++qdcount)
+ {
+ for (unsigned offset = recv_packet.payload[packet_pos]; offset; packet_pos += offset + 1, offset = recv_packet.payload[packet_pos])
+ {
+ if (offset & 0xC0)
+ {
+ packet_pos += 2;
+ offset = 0;
+ }
+ }
+
+ packet_pos += 5;
+ }
+
+ for (unsigned ancount = 0; ancount < recv_packet.ancount; ++ancount)
+ {
+ Anope::string name;
+ unsigned packet_pos_ptr = packet_pos;
+ for (unsigned offset = recv_packet.payload[packet_pos_ptr]; offset; packet_pos_ptr += offset + 1, offset = recv_packet.payload[packet_pos_ptr])
+ {
+ if (offset & 0xC0)
+ {
+ offset = (offset & 0x3F) << 8 | recv_packet.payload[++packet_pos_ptr];
+ packet_pos_ptr = offset - 12;
+ offset = recv_packet.payload[packet_pos_ptr];
+ }
+ for (unsigned i = 1; i <= offset; ++i)
+ name += recv_packet.payload[packet_pos_ptr + i];
+ name += ".";
+ }
+ name.erase(name.begin() + name.length() - 1);
+
+ if (packet_pos_ptr < packet_pos)
+ packet_pos += 2;
+ else
+ packet_pos = packet_pos_ptr + 1;
+
+ DNSRecord *rr = new DNSRecord;
+ rr->name = name;
+
+ Log(LOG_DEBUG_2) << "Resolver: Received answer for " << name;
+
+ rr->type = static_cast<QueryType>(recv_packet.payload[packet_pos] << 8 | (recv_packet.payload[packet_pos + 1] & 0xFF));
+ packet_pos += 2;
+
+ rr->record_class = recv_packet.payload[packet_pos] << 8 | (recv_packet.payload[packet_pos + 1] & 0xFF);
+ packet_pos += 2;
+
+ rr->ttl = (recv_packet.payload[packet_pos] << 24) | (recv_packet.payload[packet_pos + 1] << 16) | (recv_packet.payload[packet_pos + 2] << 8) | recv_packet.payload[packet_pos + 3];
+ packet_pos += 4;
+
+ rr->rdlength = (recv_packet.payload[packet_pos] << 8 | recv_packet.payload[packet_pos + 1]);
+ packet_pos += 2;
+
+ switch (rr->type)
+ {
+ case DNS_QUERY_A:
+ {
+ unsigned long ip = (recv_packet.payload[packet_pos]) | (recv_packet.payload[packet_pos + 1]) << 8 | (recv_packet.payload[packet_pos + 2] << 16) | (recv_packet.payload[packet_pos + 3] << 24);
+ packet_pos += 4;
+
+ char ipbuf[INET_ADDRSTRLEN];
+ if (!inet_ntop(AF_INET, &ip, ipbuf, sizeof(ipbuf)))
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received an invalid IP for DNS_QUERY_A: " << strerror(errno);
+ request->OnError(DNS_ERROR_FORMAT_ERROR, "Received an invalid IP from the nameserver: " + stringify(strerror(errno)));
+ delete rr;
+ rr = NULL;
+ }
+ else
+ rr->result = ipbuf;
+ break;
+ }
+ case DNS_QUERY_AAAA:
+ {
+ unsigned char ip[16];
+ for (int i = 0; i < 16; ++i)
+ ip[i] = recv_packet.payload[packet_pos + i];
+ packet_pos += 16;
+
+ char ipbuf[INET6_ADDRSTRLEN];
+ if (!inet_ntop(AF_INET6, &ip, ipbuf, sizeof(ipbuf)))
+ {
+ Log(LOG_DEBUG_2) << "Resolver: Received an invalid IP for DNS_QUERY_A: " << strerror(errno);
+ request->OnError(DNS_ERROR_FORMAT_ERROR, "Received an invalid IP from the nameserver: " + stringify(strerror(errno)));
+ delete rr;
+ rr = NULL;
+ }
+ else
+ rr->result = ipbuf;
+ break;
+ }
+ case DNS_QUERY_CNAME:
+ case DNS_QUERY_PTR:
+ {
+ name.clear();
+ packet_pos_ptr = packet_pos;
+ for (unsigned offset = recv_packet.payload[packet_pos_ptr]; offset; packet_pos_ptr += offset + 1, offset = recv_packet.payload[packet_pos_ptr])
+ {
+ if (offset & 0xC0)
+ {
+ offset = (offset & 0x3F) << 8 | recv_packet.payload[++packet_pos_ptr];
+ packet_pos_ptr = offset - 12;
+ offset = recv_packet.payload[packet_pos_ptr];
+ }
+ for (unsigned i = 1; i <= offset; ++i)
+ name += recv_packet.payload[packet_pos_ptr + i];
+ name += ".";
+ }
+ name.erase(name.begin() + name.length() - 1);
+
+ if (packet_pos_ptr < packet_pos)
+ packet_pos += 2;
+ else
+ packet_pos = packet_pos_ptr + 1;
+
+ rr->result = name;
+ break;
+ }
+ default:
+ delete rr;
+ request->OnError(DNS_ERROR_INVALID_TYPE, "Invalid query type");
+ rr = NULL;
+ }
+
+ if (rr && request->QT != rr->type)
+ {
+ delete rr;
+ rr = NULL;
+ }
+
+ if (rr)
+ {
+ request->OnLookupComplete(rr);
+ DNSEngine->AddCache(rr);
+ }
+ }
+ }
+
+ delete request;
+ return true;
+}
+
+bool DNSSocket::ProcessWrite()
+{
+ Log(LOG_DEBUG_2) << "Resolver: Writing to UDP socket";
+
+ bool cont = true;
+ for (unsigned i = DNSEngine->packets.size(); i > 0; --i)
+ {
+ DNSPacket *r = DNSEngine->packets[i - 1];
+
+ unsigned char buffer[524];
+ r->FillBuffer(buffer);
+
+ cont = this->SendTo(buffer, r->payload_count + 12) >= 0;
+
+ if (!cont)
+ break;
+
+ delete r;
+ DNSEngine->packets.erase(DNSEngine->packets.begin() + i - 1);
+ }
+ SocketEngine->ClearWritable(this);
+ return cont;
+}
+
+DNSManager::DNSManager() : Timer(3600, time(NULL), true)
+{
+ this->sock = NULL;
+
+ try
+ {
+ this->sock = new DNSSocket(Config->NameServer, DNSManager::DNSPort);
+ }
+ catch (const SocketException &ex)
+ {
+ throw SocketException("Unable to connect to nameserver: " + ex.GetReason());
+ }
+}
+
+DNSManager::~DNSManager()
+{
+ delete this->sock;
+}
+
+void DNSManager::AddCache(DNSRecord *rr)
+{
+ this->cache.insert(std::make_pair(rr->name, rr));
+}
+
+bool DNSManager::CheckCache(DNSRequest *request)
+{
+ std::multimap<Anope::string, DNSRecord *>::iterator it = this->cache.find(request->address);
+ if (it != this->cache.end())
+ {
+ std::multimap<Anope::string, DNSRecord *>::iterator it_end = this->cache.upper_bound(request->address);
+
+ time_t now = time(NULL);
+ for (; it != it_end; ++it)
+ {
+ DNSRecord *rec = it->second;
+ if (rec->created + rec->ttl >= now)
+ {
+ request->OnLookupComplete(rec);
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void DNSManager::Tick(time_t now)
+{
+ for (std::multimap<Anope::string, DNSRecord *>::iterator it = this->cache.begin(), it_end = this->cache.end(); it != it_end; ++it)
+ {
+ DNSRecord *req = it->second;
+
+ if (req->created + req->ttl < now)
+ {
+ delete req;
+ this->cache.erase(it);
+ }
+ }
+}
+
+DNSRequestTimeout::DNSRequestTimeout(DNSRequest *r, time_t timeout) : Timer(timeout), request(r)
+{
+ this->done = false;
+}
+
+DNSRequestTimeout::~DNSRequestTimeout()
+{
+}
+
+void DNSRequestTimeout::Tick(time_t)
+{
+ this->done = true;
+ this->request->OnError(DNS_ERROR_TIMEOUT, "Request timed out");
+ delete this->request;
+}
+
diff --git a/src/init.cpp b/src/init.cpp
index aae8e9eb2..c91cc3b31 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -373,6 +373,15 @@ void Init(int ac, char **av)
if (ModuleManager::LoadModule(Config->SocketEngine, NULL))
throw FatalException("Unable to load socket engine " + Config->SocketEngine);
+ try
+ {
+ DNSEngine = new DNSManager();
+ }
+ catch (const SocketException &ex)
+ {
+ throw FatalException(ex.GetReason());
+ }
+
/* Add Core MSG handles */
moduleAddMsgs();
diff --git a/src/logger.cpp b/src/logger.cpp
index a5637d4d8..673f7f9cb 100644
--- a/src/logger.cpp
+++ b/src/logger.cpp
@@ -290,7 +290,7 @@ bool LogInfo::HasType(LogType type)
case LOG_RAWIO:
return this->RawIO;
case LOG_DEBUG:
- return this->Debug;
+ return debug ? true : this->Debug;
// LOG_DEBUG_[234]
default:
break;
diff --git a/src/main.cpp b/src/main.cpp
index 04baf1dd3..d325cdd06 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -243,10 +243,6 @@ static void services_shutdown()
void sighandler(int signum)
{
- /* We set the quit message to something default, just to be sure it is
- * always set when we need it. It seems some signals slip through to the
- * QUIT code without having a valid quitmsg. -GD
- */
if (quitmsg.empty())
quitmsg = Anope::string("Services terminating via signal ") + strsignal(signum) + " (" + stringify(signum) + ")";
bool fatal = false;
@@ -286,7 +282,6 @@ void sighandler(int signum)
expire_all();
save_databases();
- quitmsg = "shutting down on sigterm";
default:
fatal = true;
break;
diff --git a/src/misc.cpp b/src/misc.cpp
index 66beff127..05240b77e 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -815,32 +815,6 @@ int myNumToken(const Anope::string &str, char dilim)
/*************************************************************************/
-/**
- * Resolve a host to an IP
- * @param host to convert
- * @return ip address
- */
-Anope::string host_resolve(const Anope::string &host)
-{
- struct hostent *hentp = gethostbyname(host.c_str());
- Anope::string ipreturn;
-
- if (hentp)
- {
- uint32 ip;
- memcpy(&ip, hentp->h_addr, sizeof(hentp->h_length));
- struct in_addr addr;
- addr.s_addr = ip;
- char ipbuf[16];
- ntoa(addr, ipbuf, sizeof(ipbuf));
- ipreturn = ipbuf;
- Log(LOG_DEBUG) << "resolved " << host << " to " << ipbuf;
- }
- return ipreturn;
-}
-
-/*************************************************************************/
-
/** Build a string list from a source string
* @param src The source string
* @return a list of strings
@@ -1199,43 +1173,6 @@ bool str_is_pure_wildcard(const Anope::string &str)
/*************************************************************************/
/**
- * Check if the given string is an IP, and return the IP.
- * @param str String to check
- * @return The IP, if one found. 0 if none.
- */
-uint32 str_is_ip(const Anope::string &str)
-{
- int octets[4] = { -1, -1, -1, -1 };
- std::vector<Anope::string> octets_str = BuildStringVector(str, '.');
-
- if (octets_str.size() != 4)
- return false;
-
- for (unsigned i = 0; i < 4; ++i)
- {
- Anope::string octet = octets_str[i];
-
- if (!octet.is_number_only())
- return 0;
-
- octets[i] = convertTo<int>(octet);
- /* Bail out if the octet is invalid or wrongly terminated */
- if (octets[i] < 0 || octets[i] > 255)
- return 0;
- }
-
- /* Fill the IP - the dirty way */
- uint32 ip = octets[3];
- ip += octets[2] * 256;
- ip += octets[1] * 65536;
- ip += octets[0] * 16777216;
-
- return ip;
-}
-
-/*************************************************************************/
-
-/**
* Check if the given string is an IP or CIDR mask, and fill the given
* ip/cidr params if so.
* @param str String to check
diff --git a/src/operserv.cpp b/src/operserv.cpp
index bbc38eb1a..1a6f20eb5 100644
--- a/src/operserv.cpp
+++ b/src/operserv.cpp
@@ -239,7 +239,7 @@ std::pair<XLineManager *, XLine *> XLineManager::CheckAll(User *u)
if (x)
{
ret.first = xlm;
- ret.second = x;;
+ ret.second = x;
break;
}
}
@@ -425,7 +425,7 @@ XLine *XLineManager::Check(User *u)
if (!x->GetUser().empty() && !Anope::Match(u->GetIdent(), x->GetUser()))
continue;
- if (x->GetHost().empty() || (!u->hostip.empty() && Anope::Match(u->hostip, x->GetHost())) || Anope::Match(u->host, x->GetHost()) || (!u->chost.empty() && Anope::Match(u->chost, x->GetHost())) || (!u->vhost.empty() && Anope::Match(u->vhost, x->GetHost())))
+ if (x->GetHost().empty() || (u->ip() && Anope::Match(u->ip.addr(), x->GetHost())) || Anope::Match(u->host, x->GetHost()) || (!u->chost.empty() && Anope::Match(u->chost, x->GetHost())) || (!u->vhost.empty() && Anope::Match(u->vhost, x->GetHost())))
{
OnMatch(u, x);
return x;
@@ -486,14 +486,14 @@ XLine *SGLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_
notice_lang(bi->nick, u, OPER_AKILL_ALREADY_COVERED, mask.c_str(), canAdd.second->Mask.c_str());
}
- return canAdd.second;
+ return NULL;
}
Anope::string realreason = reason;
if (u && Config->AddAkiller)
realreason = "[" + u->nick + "]" + reason;
- XLine *x = new XLine(mask, u ? u->nick : "", expires, realreason);
+ XLine *x = new XLine(mask, u ? u->nick : OperServ->nick, expires, realreason);
EventReturn MOD_RESULT;
FOREACH_RESULT(I_OnAddAkill, OnAddAkill(u, x));
@@ -549,10 +549,10 @@ XLine *SNLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_
notice_lang(bi->nick, u, OPER_SNLINE_ALREADY_COVERED, mask.c_str(), canAdd.second->Mask.c_str());
}
- return canAdd.second;
+ return NULL;
}
- XLine *x = new XLine(mask, u ? u->nick : "", expires, reason);
+ XLine *x = new XLine(mask, u ? u->nick : OperServ->nick, expires, reason);
EventReturn MOD_RESULT;
FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SNLINE));
@@ -629,10 +629,10 @@ XLine *SQLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_
notice_lang(bi->nick, u, OPER_SQLINE_ALREADY_COVERED, mask.c_str(), canAdd.second->Mask.c_str());
}
- return canAdd.second;
+ return NULL;
}
- XLine *x = new XLine(mask, u ? u->nick : "", expires, reason);
+ XLine *x = new XLine(mask, u ? u->nick : OperServ->nick, expires, reason);
EventReturn MOD_RESULT;
FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SQLINE));
@@ -747,10 +747,10 @@ XLine *SZLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_
notice_lang(bi->nick, u, OPER_SZLINE_ALREADY_COVERED, mask.c_str(), canAdd.second->Mask.c_str());
}
- return canAdd.second;
+ return NULL;
}
- XLine *x = new XLine(mask, u ? u->nick : "", expires, reason);
+ XLine *x = new XLine(mask, u ? u->nick : OperServ->nick, expires, reason);
EventReturn MOD_RESULT;
FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SZLINE));
diff --git a/src/servers.cpp b/src/servers.cpp
index 4b843411c..a5721083f 100644
--- a/src/servers.cpp
+++ b/src/servers.cpp
@@ -236,18 +236,18 @@ void Server::Sync(bool SyncLinks)
this->Links[i]->Sync(true);
}
- if (this == Me->GetLinks().front())
+ if (this->GetUplink() && this->GetUplink() == Me)
{
FOREACH_MOD(I_OnPreUplinkSync, OnPreUplinkSync(this));
ircdproto->SendEOB();
- Me->UnsetFlag(SERVER_SYNCING);
+ Me->Sync(false);
}
Log(this, "sync") << "is done syncing";
FOREACH_MOD(I_OnServerSync, OnServerSync(this));
- if (this == Me->GetLinks().front())
+ if (this->GetUplink() && this->GetUplink() == Me)
{
FOREACH_MOD(I_OnUplinkSync, OnUplinkSync(this));
restore_unsynced_topics();
@@ -407,9 +407,6 @@ void CapabParse(int ac, const char **av)
if (Capab_Info[j].Token.equals_ci(av[i]))
{
Capab.SetFlag(Capab_Info[j].Flag);
-
- if (Capab_Info[j].Token.equals_ci("NICKIP") && !ircd->nickip)
- ircd->nickip = 1;
break;
}
}
diff --git a/src/sockets.cpp b/src/sockets.cpp
index 7dcdde678..f58aa2498 100644
--- a/src/sockets.cpp
+++ b/src/sockets.cpp
@@ -15,11 +15,147 @@ static void TrimBuf(std::string &buffer)
buffer.erase(buffer.length() - 1);
}
+/** Get the size of the sockaddr we represent
+ * @return The size
+ */
+size_t sockaddrs::size() const
+{
+ switch (sa.sa_family)
+ {
+ case AF_INET:
+ return sizeof(sa4);
+ case AF_INET6:
+ return sizeof(sa6);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/** Get the port represented by this addr
+ * @return The port, or -1 on fail
+ */
+int sockaddrs::port() const
+{
+ switch (sa.sa_family)
+ {
+ case AF_INET:
+ return ntohs(sa4.sin_port);
+ case AF_INET6:
+ return ntohs(sa6.sin6_port);
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+/** Get the address represented by this addr
+ * @return The address
+ */
+Anope::string sockaddrs::addr() const
+{
+ char address[INET6_ADDRSTRLEN + 1] = "";
+
+ switch (sa.sa_family)
+ {
+ case AF_INET:
+ if (!inet_ntop(AF_INET, &sa4.sin_addr, address, sizeof(address)))
+ throw SocketException(strerror(errno));
+ return address;
+ case AF_INET6:
+ if (!inet_ntop(AF_INET6, &sa6.sin6_addr, address, sizeof(address)))
+ throw SocketException(strerror(errno));
+ return address;
+ default:
+ break;
+ }
+
+ return address;
+}
+
+/** Construct the object, sets everything to 0
+ */
+sockaddrs::sockaddrs()
+{
+ memset(this, 0, sizeof(*this));
+}
+
+/** Check if this sockaddr has data in it
+ */
+bool sockaddrs::operator()() const
+{
+ return this->sa.sa_family != 0;
+}
+
+/** Compares with sockaddr with another. Compares address type, port, and address
+ * @return true if they are the same
+ */
+bool sockaddrs::operator==(const sockaddrs &other) const
+{
+ if (sa.sa_family != other.sa.sa_family)
+ return false;
+ switch (sa.sa_family)
+ {
+ case AF_INET:
+ return (sa4.sin_port == other.sa4.sin_port) && (sa4.sin_addr.s_addr == other.sa4.sin_addr.s_addr);
+ case AF_INET6:
+ return (sa6.sin6_port == other.sa6.sin6_port) && !memcmp(sa6.sin6_addr.s6_addr, other.sa6.sin6_addr.s6_addr, 16);
+ default:
+ return !memcmp(this, &other, sizeof(*this));
+ }
+
+ return false;
+}
+
+void sockaddrs::pton(int type, const Anope::string &address, int pport)
+{
+ switch (type)
+ {
+ case AF_INET:
+ if (inet_pton(type, address.c_str(), &sa4.sin_addr) < 1)
+ throw SocketException(Anope::string("Invalid host: ") + strerror(errno));
+ sa4.sin_family = type;
+ sa4.sin_port = htons(pport);
+ return;
+ case AF_INET6:
+ if (inet_pton(type, address.c_str(), &sa6.sin6_addr) < 1)
+ throw SocketException(Anope::string("Invalid host: ") + strerror(errno));
+ sa6.sin6_family = type;
+ sa6.sin6_port = htons(pport);
+ return;
+ default:
+ break;
+ }
+
+ throw CoreException("Invalid socket type");
+}
+
+void sockaddrs::ntop(int type, const void *src)
+{
+ switch (type)
+ {
+ case AF_INET:
+ sa4.sin_addr = *reinterpret_cast<const in_addr *>(src);
+ sa4.sin_family = type;
+ return;
+ case AF_INET6:
+ sa6.sin6_addr = *reinterpret_cast<const in6_addr *>(src);
+ sa6.sin6_family = type;
+ return;
+ default:
+ break;
+ }
+
+ throw CoreException("Invalid socket type");
+}
+
SocketEngineBase::SocketEngineBase()
{
#ifdef _WIN32
if (WSAStartup(MAKEWORD(2, 0), &wsa))
- Log() << "Failed to initialize WinSock library";
+ throw FatalException("Failed to initialize WinSock library");
#endif
}
@@ -40,13 +176,14 @@ Socket::Socket()
/** Constructor
* @param nsock The socket
* @param nIPv6 IPv6?
+ * @param type The socket type, defaults to SOCK_STREAM
*/
-Socket::Socket(int nsock, bool nIPv6)
+Socket::Socket(int nsock, bool nIPv6, int type)
{
Type = SOCKTYPE_CLIENT;
IPv6 = nIPv6;
if (nsock == 0)
- Sock = socket(IPv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
+ Sock = socket(IPv6 ? AF_INET6 : AF_INET, type, 0);
else
Sock = nsock;
SocketEngine->AddSocket(this);
@@ -56,7 +193,8 @@ Socket::Socket(int nsock, bool nIPv6)
*/
Socket::~Socket()
{
- SocketEngine->DelSocket(this);
+ if (SocketEngine)
+ SocketEngine->DelSocket(this);
CloseSocket(Sock);
}
@@ -183,7 +321,7 @@ bool Socket::ProcessRead()
return true;
}
-/** Called when there is something to be written to this socket
+/** Called when the socket is ready to be written to
* @return true on success, false to drop this socket
*/
bool Socket::ProcessWrite()
@@ -197,7 +335,7 @@ bool Socket::ProcessWrite()
return false;
}
WriteBuffer.clear();
- SocketEngine->ClearWriteable(this);
+ SocketEngine->ClearWritable(this);
return true;
}
@@ -243,7 +381,7 @@ void Socket::Write(const char *message, ...)
void Socket::Write(const Anope::string &message)
{
WriteBuffer.append(message.str() + "\r\n");
- SocketEngine->MarkWriteable(this);
+ SocketEngine->MarkWritable(this);
}
/** Constructor
@@ -251,103 +389,22 @@ void Socket::Write(const Anope::string &message)
* @param nu The user using this socket
* @param nsock The socket
* @param nIPv6 IPv6
+ * @param type The socket type, defaults to SOCK_STREAM
*/
-ClientSocket::ClientSocket(const Anope::string &nTargetHost, int nPort, const Anope::string &nBindHost, bool nIPv6) : Socket(0, nIPv6), TargetHost(nTargetHost), Port(nPort), BindHost(nBindHost)
+ClientSocket::ClientSocket(const Anope::string &nTargetHost, int nPort, const Anope::string &nBindHost, bool nIPv6, int type) : Socket(0, nIPv6, type), TargetHost(nTargetHost), Port(nPort), BindHost(nBindHost)
{
- addrinfo hints;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = 0;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_family = IPv6 ? AF_INET6 : AF_INET;
-
if (!BindHost.empty())
{
- addrinfo *bindar;
- sockaddr_in bindaddr;
- sockaddr_in6 bindaddr6;
-
- if (!getaddrinfo(BindHost.c_str(), NULL, &hints, &bindar))
- {
- if (IPv6)
- memcpy(&bindaddr6, bindar->ai_addr, bindar->ai_addrlen);
- else
- memcpy(&bindaddr, bindar->ai_addr, bindar->ai_addrlen);
-
- freeaddrinfo(bindar);
- }
- else
- {
- if (IPv6)
- {
- bindaddr6.sin6_family = AF_INET6;
-
- if (inet_pton(AF_INET6, BindHost.c_str(), &bindaddr6.sin6_addr) < 1)
- throw SocketException(Anope::string("Invalid bind host: ") + strerror(errno));
- }
- else
- {
- bindaddr.sin_family = AF_INET;
-
- if (inet_pton(AF_INET, BindHost.c_str(), &bindaddr.sin_addr) < 1)
- throw SocketException(Anope::string("Invalid bind host: ") + strerror(errno));
- }
- }
-
- if (IPv6)
- {
- if (bind(Sock, reinterpret_cast<sockaddr *>(&bindaddr6), sizeof(bindaddr6)) == -1)
- throw SocketException(Anope::string("Unable to bind to address: ") + strerror(errno));
- }
- else
- {
- if (bind(Sock, reinterpret_cast<sockaddr *>(&bindaddr), sizeof(bindaddr)) == -1)
- throw SocketException(Anope::string("Unable to bind to address: ") + strerror(errno));
- }
- }
-
- addrinfo *conar;
- sockaddr_in6 addr6;
- sockaddr_in addr;
-
- if (!getaddrinfo(TargetHost.c_str(), NULL, &hints, &conar))
- {
- if (IPv6)
- memcpy(&addr6, conar->ai_addr, conar->ai_addrlen);
- else
- memcpy(&addr, conar->ai_addr, conar->ai_addrlen);
-
- freeaddrinfo(conar);
- }
- else
- {
- if (IPv6)
- {
- if (inet_pton(AF_INET6, TargetHost.c_str(), &addr6.sin6_addr) < 1)
- throw SocketException(Anope::string("Invalid server host: ") + strerror(errno));
- }
- else
- {
- if (inet_pton(AF_INET, TargetHost.c_str(), &addr.sin_addr) < 1)
- throw SocketException(Anope::string("Invalid server host: ") + strerror(errno));
- }
- }
-
- if (IPv6)
- {
- addr6.sin6_family = AF_INET6;
- addr6.sin6_port = htons(nPort);
-
- if (connect(Sock, reinterpret_cast<sockaddr *>(&addr6), sizeof(addr6)) == -1)
- throw SocketException(Anope::string("Error connecting to server: ") + strerror(errno));
+ sockaddrs bindaddr;
+ bindaddr.pton(IPv6 ? AF_INET6 : AF_INET, BindHost, 0);
+ if (bind(Sock, &bindaddr.sa, bindaddr.size()) == -1)
+ throw SocketException(Anope::string("Unable to bind to address: ") + strerror(errno));
}
- else
- {
- addr.sin_family = AF_INET;
- addr.sin_port = htons(nPort);
- if (connect(Sock, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) == -1)
- throw SocketException(Anope::string("Error connecting to server: ") + strerror(errno));
- }
+ sockaddrs conaddr;
+ conaddr.pton(IPv6 ? AF_INET6 : AF_INET, TargetHost, Port);
+ if (connect(Sock, &conaddr.sa, conaddr.size()) == -1)
+ throw SocketException(Anope::string("Error connecting to server: ") + strerror(errno));
this->SetNonBlocking();
}
@@ -377,36 +434,11 @@ ListenSocket::ListenSocket(const Anope::string &bindip, int port) : Socket(0, (b
BindIP = bindip;
Port = port;
- sockaddr_in sock_addr;
- sockaddr_in6 sock_addr6;
-
- if (IPv6)
- {
- sock_addr6.sin6_family = AF_INET6;
- sock_addr6.sin6_port = htons(port);
-
- if (inet_pton(AF_INET6, bindip.c_str(), &sock_addr6.sin6_addr) < 1)
- throw SocketException(Anope::string("Invalid bind host: ") + strerror(errno));
- }
- else
- {
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_port = htons(port);
-
- if (inet_pton(AF_INET, bindip.c_str(), &sock_addr.sin_addr) < 1)
- throw SocketException(Anope::string("Invalid bind host: ") + strerror(errno));
- }
+ sockaddrs sockaddr;
+ sockaddr.pton(IPv6 ? AF_INET6 : AF_INET, BindIP, Port);
- if (IPv6)
- {
- if (bind(Sock, reinterpret_cast<sockaddr *>(&sock_addr6), sizeof(sock_addr6)) == -1)
- throw SocketException(Anope::string("Unable to bind to address: ") + strerror(errno));
- }
- else
- {
- if (bind(Sock, reinterpret_cast<sockaddr *>(&sock_addr), sizeof(sock_addr)) == -1)
- throw SocketException(Anope::string("Unable to bind to address: ") + strerror(errno));
- }
+ if (bind(Sock, &sockaddr.sa, sockaddr.size()) == -1)
+ throw SocketException(Anope::string("Unable to bind to address: ") + strerror(errno));
if (listen(Sock, 5) == -1)
throw SocketException(Anope::string("Unable to listen: ") + strerror(errno));
@@ -426,7 +458,7 @@ bool ListenSocket::ProcessRead()
{
int newsock = accept(Sock, NULL, NULL);
-#ifndef _WIN32
+#ifndef INVALID_SOCKET
# define INVALID_SOCKET 0
#endif
diff --git a/src/users.cpp b/src/users.cpp
index c9c5ce20e..36b32071b 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -186,7 +186,7 @@ User::~User()
{
Log(LOG_DEBUG_2) << "User::~User() called";
- Log(this, "disconnect") << " (" << this->realname << ") " << "disconnected from the network (" << this->server->GetName() << ")";
+ Log(this, "disconnect") << "(" << this->realname << ") " << "disconnected from the network (" << this->server->GetName() << ")";
this->Logout();
@@ -642,16 +642,13 @@ User *finduser(const Anope::string &nick)
/* Handle a server NICK command. */
-User *do_nick(const Anope::string &source, const Anope::string &nick, const Anope::string &username, const Anope::string &host, const Anope::string &server, const Anope::string &realname, time_t ts, uint32 ip, const Anope::string &vhost, const Anope::string &uid)
+User *do_nick(const Anope::string &source, const Anope::string &nick, const Anope::string &username, const Anope::string &host, const Anope::string &server, const Anope::string &realname, time_t ts, const Anope::string &ip, const Anope::string &vhost, const Anope::string &uid)
{
User *user = NULL;
Anope::string vhost2 = vhost;
if (source.empty())
{
- char ipbuf[16];
- struct in_addr addr;
-
if (ircd->nickvhost && !vhost2.empty() && vhost2.equals_cs("*"))
{
vhost2.clear();
@@ -660,12 +657,6 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop
/* This is a new user; create a User structure for it. */
Log(LOG_DEBUG) << "new user: " << nick;
- if (ircd->nickip)
- {
- addr.s_addr = htonl(ip);
- ntoa(addr, ipbuf, sizeof(ipbuf));
- }
-
Server *serv = Server::Find(server);
/* Allocate User structure and fill it in. */
@@ -677,14 +668,24 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop
if (!vhost2.empty())
user->SetCloakedHost(vhost2);
user->SetVIdent(username);
- /* We now store the user's ip in the user_ struct,
- * because we will use it in serveral places -- DrStein */
- if (ircd->nickip)
- user->hostip = ipbuf;
- else
- user->hostip = "";
- Log(user, "connect") << (ircd->nickvhost && !vhost2.empty() ? Anope::string("(") + vhost2 + ")" : "") << ") (" << user->realname << ") " << (ircd->nickip ? Anope::string("[") + ipbuf + "] " : "") << "connected to the network (" << serv->GetName() << ")";
+ if (!ip.empty())
+ {
+ try
+ {
+ if (ip.find(':') != Anope::string::npos)
+ user->ip.pton(AF_INET6, ip);
+ else
+ user->ip.pton(AF_INET, ip);
+ }
+ catch (const SocketException &ex)
+ {
+ Log() << "Received an invalid IP for user " << user->nick << " (" << ip << ")";
+ Log() << ex.GetReason();
+ }
+ }
+
+ Log(user, "connect") << (ircd->nickvhost && !vhost2.empty() ? Anope::string("(") + vhost2 + ")" : "") << ") (" << user->realname << ") " << (user->ip() ? Anope::string("[") + user->ip.addr() + "] " : "") << "connected to the network (" << serv->GetName() << ")";
EventReturn MOD_RESULT;
FOREACH_RESULT(I_OnPreUserConnect, OnPreUserConnect(user));
@@ -692,7 +693,7 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop
return finduser(nick);
if (Config->LimitSessions && !serv->IsULined())
- add_session(nick, host, ipbuf);
+ add_session(nick, host, user->ip() ? user->ip.addr() : "");
XLineManager::CheckAll(user);