diff options
-rw-r--r-- | include/dns.h | 44 | ||||
-rw-r--r-- | src/dns.cpp | 153 |
2 files changed, 154 insertions, 43 deletions
diff --git a/include/dns.h b/include/dns.h index 9d6f161df..7b96f792d 100644 --- a/include/dns.h +++ b/include/dns.h @@ -88,6 +88,25 @@ typedef std::map<int,DNSRequest*> requestlist; typedef requestlist::iterator requestlist_iter; /** + * Query and resource record types + */ +enum QueryType +{ + DNS_QUERY_A = 1, /* 'A' record: an ipv4 address */ + DNS_QUERY_CNAME = 5, /* 'CNAME' record: An alias */ + DNS_QUERY_PTR = 12, /* 'PTR' record: a hostname */ + DNS_QUERY_AAAA = 28, /* 'AAAA' record: an ipv6 address */ +}; + +#ifdef IPV6 +const QueryType DNS_QUERY_FORWARD = DNS_QUERY_AAAA; +const QueryType DNS_QUERY_REVERSE = DNS_QUERY_PTR; +#else +const QueryType DNS_QUERY_FORWARD = DNS_QUERY_A; +const QueryType DNS_QUERY_REVERSE = DNS_QUERY_PTR; +#endif + +/** * The Resolver class is a high-level abstraction for resolving DNS entries. * It can do forward and reverse IPv4 lookups, and where IPv6 is supported, will * also be able to do those, transparent of protocols. Module developers must @@ -107,7 +126,7 @@ class Resolver : public Extensible /** * True if a forward lookup is being performed, false if otherwise */ - bool fwd; + QueryType querytype; /** * The DNS erver being used for lookups. If this is an empty string, * the value of ServerConfig::DNSServer is used instead. @@ -137,7 +156,7 @@ class Resolver : public Extensible * event a lookup could not be allocated, or a similar hard error occurs such as * the network being down. */ - Resolver(const std::string &source, bool forward); + Resolver(const std::string &source, QueryType qt); /** * The default destructor does nothing. */ @@ -165,15 +184,6 @@ class Resolver : public Extensible int GetId(); }; -/** - * Query and resource record types - */ -enum QueryType -{ - DNS_QUERY_A = 1, /* 'A' record: an IP address */ - DNS_QUERY_PTR = 12 /* 'PTR' record: a hostname */ -}; - /** DNS is a singleton class used by the core to dispatch dns * requests to the dns server, and route incoming dns replies * back to Resolver objects, based upon the request ID. You @@ -244,7 +254,7 @@ class DNS : public Extensible static int GetMasterSocket(); /** - * Start the lookup of an ip from a hostname + * Start the lookup of an ipv4 from a hostname */ int GetIP(const char* name); @@ -254,6 +264,16 @@ class DNS : public Extensible int GetName(const insp_inaddr* ip); /** + * Start lookup of an ipv6 from a hostname + */ + int GetIP6(const char *name); + + /** + * Start lookup of a CNAME from another hostname + */ + int GetCName(const char* alias); + + /** * Fetch the result string (an ip or host) * and/or an error message to go with it. */ diff --git a/src/dns.cpp b/src/dns.cpp index 1ce68f186..2980a2502 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -360,6 +360,42 @@ int DNS::GetIP(const char *name) return id; } +/* Start lookup of an hostname to an IPv6 address */ +int DNS::GetIP6(const char *name) +{ + DNSHeader h; + int id; + int length; + + if ((length = this->MakePayload(name, DNS_QUERY_AAAA, 1, (unsigned char*)&h.payload)) == -1) + return -1; + + DNSRequest* req = this->AddQuery(&h, id); + + if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_AAAA) == -1)) + return -1; + + return id; +} + +/* Start lookup of a cname to another name */ +int DNS::GetCName(const char *alias) +{ + DNSHeader h; + int id; + int length; + + if ((length = this->MakePayload(alias, DNS_QUERY_CNAME, 1, (unsigned char*)&h.payload)) == -1) + return -1; + + DNSRequest* req = this->AddQuery(&h, id); + + if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_CNAME) == -1)) + return -1; + + return id; +} + /* Start lookup of an IP address to a hostname */ int DNS::GetName(const insp_inaddr *ip) { @@ -471,17 +507,53 @@ DNSResult DNS::GetResult() } else { + char formatted[128]; + /* Forward lookups come back as binary data. We must format them into ascii */ - if (req->type == DNS_QUERY_A) + switch (req->type) { - char formatted[16]; - snprintf(formatted,16,"%u.%u.%u.%u",data.first[0],data.first[1],data.first[2],data.first[3]); - resultstr = formatted; - } - else - { - /* Reverse lookups just come back as char* */ - resultstr = std::string((const char*)data.first); + case DNS_QUERY_A: + snprintf(formatted,16,"%u.%u.%u.%u",data.first[0],data.first[1],data.first[2],data.first[3]); + resultstr = formatted; + break; + + case DNS_QUERY_AAAA: + { + in6_addr* ip = (in6_addr*)&data.first; + + snprintf(formatted,40,"%x:%x:%x:%x:%x:%x:%x:%x", + ntohs(*((unsigned short *)&ip->s6_addr[0])), + ntohs(*((unsigned short *)&ip->s6_addr[2])), + ntohs(*((unsigned short *)&ip->s6_addr[4])), + ntohs(*((unsigned short *)&ip->s6_addr[6])), + ntohs(*((unsigned short *)&ip->s6_addr[8])), + ntohs(*((unsigned short *)&ip->s6_addr[10])), + ntohs(*((unsigned short *)&ip->s6_addr[12])), + ntohs(*((unsigned short *)&ip->s6_addr[14]))); + char* c = strstr(formatted,":0:"); + if (c != NULL) + { + memmove(c+1,c+2,strlen(c+2) + 1); + c += 2; + while (memcmp(c,"0:",2) == 0) + memmove(c,c+2,strlen(c+2) + 1); + if (memcmp(c,"0",2) == 0) + *c = 0; + if (memcmp(formatted,"0::",3) == 0) + memmove(formatted,formatted + 1, strlen(formatted + 1) + 1); + } + resultstr = formatted; + } + break; + + case DNS_QUERY_CNAME: + /* Identical handling to PTR */ + + case DNS_QUERY_PTR: + /* Reverse lookups just come back as char* */ + resultstr = std::string((const char*)data.first); + break; + } /* Build the reply with the id and hostname/ip in it */ @@ -582,6 +654,8 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length) switch (rr.type) { + case DNS_QUERY_CNAME: + /* CNAME and PTR have the same processing code */ case DNS_QUERY_PTR: o = 0; q = 0; @@ -611,14 +685,18 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length) } res[o] = 0; break; + case DNS_QUERY_AAAA: + memcpy(res,&header.payload[i],rr.rdlength); + res[rr.rdlength] = 0; + break; case DNS_QUERY_A: memcpy(res,&header.payload[i],rr.rdlength); res[rr.rdlength] = 0; - break; + break; default: memcpy(res,&header.payload[i],rr.rdlength); res[rr.rdlength] = 0; - break; + break; } return std::make_pair(res,"No error");; } @@ -631,28 +709,41 @@ DNS::~DNS() } /* High level abstraction of dns used by application at large */ -Resolver::Resolver(const std::string &source, bool forward) : input(source), fwd(forward) +Resolver::Resolver(const std::string &source, QueryType qt) : input(source), querytype(qt) { - if (forward) - { - log(DEBUG,"Resolver: Forward lookup on %s",source.c_str()); - this->myid = ServerInstance->Res->GetIP(source.c_str()); - } - else + insp_inaddr binip; + + switch (querytype) { - log(DEBUG,"Resolver: Reverse lookup on %s",source.c_str()); - insp_inaddr binip; - if (insp_aton(source.c_str(), &binip) > 0) - { - /* Valid ip address */ - this->myid = ServerInstance->Res->GetName(&binip); - } - else - { - this->OnError(RESOLVER_BADIP, "Bad IP address for reverse lookup"); - throw ModuleException("Resolver: Bad IP address"); - return; - } + case DNS_QUERY_A: + this->myid = ServerInstance->Res->GetIP(source.c_str()); + break; + + case DNS_QUERY_PTR: + if (insp_aton(source.c_str(), &binip) > 0) + { + /* Valid ip address */ + this->myid = ServerInstance->Res->GetName(&binip); + } + else + { + this->OnError(RESOLVER_BADIP, "Bad IP address for reverse lookup"); + throw ModuleException("Resolver: Bad IP address"); + return; + } + break; + + case DNS_QUERY_AAAA: + this->myid = ServerInstance->Res->GetIP6(source.c_str()); + break; + + case DNS_QUERY_CNAME: + this->myid = ServerInstance->Res->GetCName(source.c_str()); + break; + + default: + this->myid = -1; + break; } if (this->myid == -1) { |