-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2012 William Pitcock <nenolod@dereferenced.org>
+ * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+ * Copyright (C) 2006, 2009 Robin Burchell <robin+git@viroteck.net>
+ * Copyright (C) 2007, 2009 Dennis Friis <peavey@inspircd.org>
+ * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
+ * Copyright (C) 2005-2007 Craig Edwards <craigedwards@brainbox.cc>
*
- * InspIRCd: (C) 2002-2010 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
*
- * This program is free but copyrighted software; see
- * the file COPYING for details.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
*
- * ---------------------------------------------------
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
/* $Core */
/*
looks like this, walks like this or tastes like this.
*/
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
DNSRequest(DNS* dns, int id, const std::string &original);
~DNSRequest();
- DNSInfo ResultIsReady(DNSHeader &h, int length);
+ DNSInfo ResultIsReady(DNSHeader &h, unsigned length);
int SendRequests(const DNSHeader *header, const int length, QueryType qt);
};
return NULL;
/* Create an id */
+ unsigned int tries = 0;
do {
id = ServerInstance->GenRandomInt(DNS::MAX_REQUEST_ID);
+ if (++tries == DNS::MAX_REQUEST_ID*5)
+ {
+ // If we couldn't find an empty slot this many times, do a sequential scan as a last
+ // resort. If an empty slot is found that way, go on, otherwise throw an exception
+ id = -1;
+ for (int i = 0; i < DNS::MAX_REQUEST_ID; i++)
+ {
+ if (!requests[i])
+ {
+ id = i;
+ break;
+ }
+ }
+
+ if (id == -1)
+ throw ModuleException("DNS: All ids are in use");
+
+ break;
+ }
} while (requests[id]);
DNSRequest* req = new DNSRequest(this, id, original);
/* Clear the requests class table */
memset(requests,0,sizeof(requests));
- /* Set the id of the next request to 0
- */
- currid = 0;
-
/* DNS::Rehash() sets this to a valid ptr
*/
this->cache = NULL;
*/
if (from != myserver)
{
+ std::string server1 = from.str();
+ std::string server2 = myserver.str();
ServerInstance->Logs->Log("RESOLVER",DEBUG,"Got a result from the wrong server! Bad NAT or DNS forging attempt? '%s' != '%s'",
- from.str().c_str(), myserver.str().c_str());
+ server1.c_str(), server2.c_str());
return DNSResult(-1,"",0,"");
}
}
/** A result is ready, process it */
-DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)
+DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length)
{
unsigned i = 0, o;
int q = 0;
/* Subtract the length of the header from the length of the packet */
length -= 12;
- while ((unsigned int)q < header.qdcount && i < (unsigned) length)
+ while ((unsigned int)q < header.qdcount && i < length)
{
if (header.payload[i] > 63)
{
while ((unsigned)curanswer < header.ancount)
{
q = 0;
- while (q == 0 && i < (unsigned) length)
+ while (q == 0 && i < length)
{
if (header.payload[i] > 63)
{
else i += header.payload[i] + 1; /* skip length and label */
}
}
- if ((unsigned) length - i < 10)
+ if (static_cast<int>(length - i) < 10)
return std::make_pair((unsigned char*)NULL,"Incorrectly sized DNS reply");
/* XXX: We actually initialise 'rr' here including its ttl field */
*/
case DNS_QUERY_CNAME:
case DNS_QUERY_PTR:
+ {
+ unsigned short lowest_pos = length;
o = 0;
q = 0;
- while (q == 0 && i < (unsigned) length && o + 256 < 1023)
+ while (q == 0 && i < length && o + 256 < 1023)
{
/* DN label found (byte over 63) */
if (header.payload[i] > 63)
i = ntohs(ptr);
/* check that highest two bits are set. if not, we've been had */
- if (!(i & DN_COMP_BITMASK))
+ if ((i & DN_COMP_BITMASK) != DN_COMP_BITMASK)
return std::make_pair((unsigned char *) NULL, "DN label decompression header is bogus");
/* mask away the two highest bits. */
i &= ~DN_COMP_BITMASK;
/* and decrease length by 12 bytes. */
- i =- 12;
+ i -= 12;
+
+ if (i >= lowest_pos)
+ return std::make_pair((unsigned char *) NULL, "Invalid decompression pointer");
+ lowest_pos = i;
}
else
{
}
}
res[o] = 0;
+ }
break;
case DNS_QUERY_AAAA:
+ if (rr.rdlength != sizeof(struct in6_addr))
+ return std::make_pair((unsigned char *) NULL, "rr.rdlength is larger than 16 bytes for an ipv6 entry -- malformed/hostile packet?");
+
memcpy(res,&header.payload[i],rr.rdlength);
res[rr.rdlength] = 0;
break;
case DNS_QUERY_A:
+ if (rr.rdlength != sizeof(struct in_addr))
+ return std::make_pair((unsigned char *) NULL, "rr.rdlength is larger than 4 bytes for an ipv4 entry -- malformed/hostile packet?");
+
memcpy(res,&header.payload[i],rr.rdlength);
res[rr.rdlength] = 0;
break;
default:
- memcpy(res,&header.payload[i],rr.rdlength);
- res[rr.rdlength] = 0;
+ return std::make_pair((unsigned char *) NULL, "don't know how to handle undefined type (" + ConvToStr(rr.type) + ") -- rejecting");
break;
}
return std::make_pair(res,"No error");
Classes[r->GetId()] = r;
return true;
}
- else
- /* Duplicate id */
- return false;
}
- else
- {
- /* Pointer or id not valid.
- * Free the item and return
- */
- if (r)
- delete r;
- return false;
- }
+ /* Pointer or id not valid, or duplicate id.
+ * Free the item and return
+ */
+ delete r;
+ return false;
}
void DNS::CleanResolvers(Module* module)