X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fdns.cpp;h=33dba1abb72a2e14f3838379bde0185a034e4690;hb=aec772bdc98bdcfe35c2fc8e74942403c9efcc4d;hp=3f8cde523825d9894d9c6cebc77ee926ffaa343d;hpb=61578deea0767122684d050c55740205fed904fa;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/dns.cpp b/src/dns.cpp index 3f8cde523..33dba1abb 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -32,10 +32,10 @@ looks like this, walks like this or tastes like this. #include "configreader.h" #include "socket.h" -using irc::sockets::insp_sockaddr; using irc::sockets::insp_inaddr; using irc::sockets::insp_ntoa; using irc::sockets::insp_aton; +using irc::sockets::OpenTCPSocket; /** Masks to mask off the responses we get from the DNSRequest methods */ @@ -91,12 +91,11 @@ class DNSRequest unsigned char* res; /* Result processing buffer */ unsigned int rr_class; /* Request class */ QueryType type; /* Request type */ - insp_inaddr myserver; /* DNS server address*/ DNS* dnsobj; /* DNS caller (where we get our FD from) */ unsigned long ttl; /* Time to live */ std::string orig; /* Original requested name/ip */ - DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id, const std::string &original); + DNSRequest(InspIRCd* Instance, DNS* dns, int id, const std::string &original); ~DNSRequest(); DNSInfo ResultIsReady(DNSHeader &h, int length); int SendRequests(const DNSHeader *header, const int length, QueryType qt); @@ -146,11 +145,10 @@ class RequestTimeout : public InspTimer }; /* Allocate the processing buffer */ -DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id, const std::string &original) : dnsobj(dns) +DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, int id, const std::string &original) : dnsobj(dns) { res = new unsigned char[512]; *res = 0; - memcpy(&myserver, &server, sizeof(insp_inaddr)); orig = original; RequestTimeout* RT = new RequestTimeout(Instance->Config->dns_timeout ? Instance->Config->dns_timeout : 5, Instance, this, id); Instance->Timers->AddTimer(RT); /* The timer manager frees this */ @@ -206,7 +204,6 @@ inline void DNS::EmptyHeader(unsigned char *output, const DNSHeader *header, con /** Send requests we have previously built down the UDP socket */ int DNSRequest::SendRequests(const DNSHeader *header, const int length, QueryType qt) { - insp_sockaddr addr; unsigned char payload[sizeof(DNSHeader)]; this->rr_class = 1; @@ -214,18 +211,36 @@ int DNSRequest::SendRequests(const DNSHeader *header, const int length, QueryTyp DNS::EmptyHeader(payload,header,length); - memset(&addr,0,sizeof(addr)); #ifdef IPV6 - memcpy(&addr.sin6_addr,&myserver,sizeof(addr.sin6_addr)); - addr.sin6_family = AF_FAMILY; - addr.sin6_port = htons(DNS::QUERY_PORT); + if (this->dnsobj->socketfamily == AF_INET6) + { + sockaddr_in6 addr; + memset(&addr,0,sizeof(addr)); + memcpy(&addr.sin6_addr,&dnsobj->myserver6,sizeof(addr.sin6_addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(DNS::QUERY_PORT); + if (sendto(dnsobj->GetFd(), payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) != length+12) + return -1; + } + else + { + sockaddr_in addr; + memset(&addr,0,sizeof(addr)); + memcpy(&addr.sin_addr.s_addr,&dnsobj->myserver4,sizeof(addr.sin_addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(DNS::QUERY_PORT); + if (sendto(dnsobj->GetFd(), payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) != length+12) + return -1; + } #else - memcpy(&addr.sin_addr.s_addr,&myserver,sizeof(addr.sin_addr)); - addr.sin_family = AF_FAMILY; + sockaddr_in addr; + memset(&addr,0,sizeof(addr)); + memcpy(&addr.sin_addr.s_addr, &dnsobj->myserver4, sizeof(addr.sin_addr)); + addr.sin_family = AF_INET; addr.sin_port = htons(DNS::QUERY_PORT); -#endif - if (sendto(dnsobj->GetFd(), payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) == -1) + if (sendto(dnsobj->GetFd(), payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) != length+12) return -1; +#endif return 0; } @@ -244,7 +259,7 @@ DNSRequest* DNS::AddQuery(DNSHeader *header, int &id, const char* original) while (requests[id]) id = this->PRNG() & DNS::MAX_REQUEST_ID; - DNSRequest* req = new DNSRequest(ServerInstance, this, this->myserver, id, original); + DNSRequest* req = new DNSRequest(ServerInstance, this, id, original); header->id[0] = req->id[0] = id >> 8; header->id[1] = req->id[1] = id & 0xFF; @@ -291,8 +306,8 @@ int DNS::PruneCache() void DNS::Rehash() { - insp_inaddr addr; ip6munge = false; + int portpass = 0; if (this->GetFd() > -1) { @@ -311,50 +326,39 @@ void DNS::Rehash() this->cache = new dnscache(); } - if (insp_aton(ServerInstance->Config->DNSServer,&addr) > 0) + if ((strstr(ServerInstance->Config->DNSServer,"::ffff:") == (char*)&ServerInstance->Config->DNSServer) || (strstr(ServerInstance->Config->DNSServer,"::FFFF:") == (char*)&ServerInstance->Config->DNSServer)) { - memcpy(&myserver,&addr,sizeof(insp_inaddr)); - if ((strstr(ServerInstance->Config->DNSServer,"::ffff:") == (char*)&ServerInstance->Config->DNSServer) || (strstr(ServerInstance->Config->DNSServer,"::FFFF:") == (char*)&ServerInstance->Config->DNSServer)) - { - ServerInstance->Log(DEFAULT,"WARNING: Using IPv4 addresses over IPv6 forces some DNS checks to be disabled."); - ServerInstance->Log(DEFAULT," This should not cause a problem, however it is recommended you migrate"); - ServerInstance->Log(DEFAULT," to a true IPv6 environment."); - this->ip6munge = true; - } + ServerInstance->Log(DEFAULT,"WARNING: Using IPv4 addresses over IPv6 forces some DNS checks to be disabled."); + ServerInstance->Log(DEFAULT," This should not cause a problem, however it is recommended you migrate"); + ServerInstance->Log(DEFAULT," to a true IPv6 environment."); + this->ip6munge = true; } - /* Initialize mastersocket */ - this->SetFd(socket(PF_PROTOCOL, SOCK_DGRAM, 0)); - if (this->GetFd() != -1) + this->socketfamily = AF_INET; +#ifdef IPV6 + if (strchr(ServerInstance->Config->DNSServer,':')) { - /* Did it succeed? */ - if (fcntl(this->GetFd(), F_SETFL, O_NONBLOCK) != 0) - { - /* Couldn't make the socket nonblocking */ - shutdown(this->GetFd(),2); - close(this->GetFd()); - this->SetFd(-1); - } + this->socketfamily = AF_INET6; + inet_pton(AF_INET6, ServerInstance->Config->DNSServer, &this->myserver6); + } + else + { + inet_aton(ServerInstance->Config->DNSServer, &this->myserver4); + portpass = -1; } +#else + inet_aton(ServerInstance->Config->DNSServer, &this->myserver4); +#endif + + /* Initialize mastersocket */ + int s = OpenTCPSocket(ServerInstance->Config->DNSServer, SOCK_DGRAM); + this->SetFd(s); /* Have we got a socket and is it nonblocking? */ if (this->GetFd() != -1) { -#ifdef IPV6 - insp_sockaddr addr; - memset(&addr,0,sizeof(addr)); - addr.sin6_family = AF_FAMILY; - addr.sin6_port = 0; - addr.sin6_addr = in6addr_any; -#else - insp_sockaddr addr; - memset(&addr,0,sizeof(addr)); - addr.sin_family = AF_FAMILY; - addr.sin_port = 0; - addr.sin_addr.s_addr = INADDR_ANY; -#endif - /* Bind the port */ - if (bind(this->GetFd(),(sockaddr *)&addr,sizeof(addr)) != 0) + /* Bind the port - port 0 INADDR_ANY */ + if (!ServerInstance->BindSocket(this->GetFd(), portpass, "", false)) { /* Failed to bind */ shutdown(this->GetFd(),2); @@ -606,17 +610,22 @@ DNSResult DNS::GetResult() DNSHeader header; DNSRequest *req; unsigned char buffer[sizeof(DNSHeader)]; - sockaddr from; - socklen_t x = sizeof(from); - const char* ipaddr_from = ""; + sockaddr* from = new sockaddr[2]; +#ifdef IPV6 + socklen_t x = this->socketfamily == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); +#else + socklen_t x = sizeof(sockaddr_in); +#endif + const char* ipaddr_from; unsigned short int port_from = 0; - int length = recvfrom(this->GetFd(),buffer,sizeof(DNSHeader),0,&from,&x); + int length = recvfrom(this->GetFd(),buffer,sizeof(DNSHeader),0,from,&x); /* Did we get the whole header? */ if (length < 12) { /* Nope - something screwed up. */ + delete[] from; return DNSResult(-1,"",0,""); } @@ -630,13 +639,24 @@ DNSResult DNS::GetResult() * -- Thanks jilles for pointing this one out. */ #ifdef IPV6 - ipaddr_from = insp_ntoa(((sockaddr_in6*)&from)->sin6_addr); - port_from = ntohs(((sockaddr_in6*)&from)->sin6_port); + char nbuf[MAXBUF]; + if (this->socketfamily == AF_INET6) + { + ipaddr_from = inet_ntop(AF_INET6, &((sockaddr_in6*)from)->sin6_addr, nbuf, sizeof(nbuf)); + port_from = ntohs(((sockaddr_in6*)from)->sin6_port); + } + else + { + ipaddr_from = inet_ntoa(((sockaddr_in*)from)->sin_addr); + port_from = ntohs(((sockaddr_in*)from)->sin_port); + } #else - ipaddr_from = insp_ntoa(((sockaddr_in*)&from)->sin_addr); - port_from = ntohs(((sockaddr_in*)&from)->sin_port); + ipaddr_from = inet_ntoa(((sockaddr_in*)from)->sin_addr); + port_from = ntohs(((sockaddr_in*)from)->sin_port); #endif + delete[] from; + /* We cant perform this security check if you're using 4in6. * Tough luck to you, choose one or't other! */