#endif
if (sendto(DNS::GetMasterSocket(), payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) == -1)
{
- log(DEBUG,"Error in sendto!");
+ log(DEBUG,"Error in sendto! (%s)",strerror(errno));
return -1;
}
/* Convert the nameserver address into an insp_inaddr */
if (insp_aton(Config->DNSServer,&addr) > 0)
+ {
memcpy(&myserver,&addr,sizeof(insp_inaddr));
+ if ((strstr(Config->DNSServer,"::ffff:") == (char*)&Config->DNSServer) || (strstr(Config->DNSServer,"::FFFF:") == (char*)&Config->DNSServer))
+ {
+ /* These dont come back looking like they did when they went in.
+ * We're forced to turn some checks off.
+ * If anyone knows how to fix this, let me know. --Brain
+ */
+ log(DEFAULT,"WARNING: Using IPv4 addresses over IPv6 forces some DNS checks to be disabled.");
+ log(DEFAULT," This should not cause a problem, however it is recommended you migrate");
+ log(DEFAULT," to a true IPv6 environment.");
+ this->ip6munge = true;
+ }
+ log(DEBUG,"Added nameserver '%s'",Config->DNSServer);
+ }
+ else
+ {
+ log(DEBUG,"GACK! insp_aton says the nameserver '%s' is invalid!",Config->DNSServer);
+ }
/* Initialize mastersocket */
MasterSocket = socket(PF_PROTOCOL, SOCK_DGRAM, 0);
MasterSocket = -1;
}
}
+ else
+ {
+ log(DEBUG,"I cant socket() this socket! (%s)",strerror(errno));
+ }
/* Have we got a socket and is it nonblocking? */
if (MasterSocket != -1)
{
memset(&addr,0,sizeof(addr));
addr.sin6_family = AF_FAMILY;
addr.sin6_port = 0;
- memset(&addr.sin6_addr,255,sizeof(in6_addr));
+ addr.sin6_addr = in6addr_any;
#else
insp_sockaddr addr;
memset(&addr,0,sizeof(addr));
if (MasterSocket >= 0)
{
+ log(DEBUG,"Add master socket %d",MasterSocket);
/* Hook the descriptor into the socket engine */
if (ServerInstance && ServerInstance->SE)
ServerInstance->SE->AddFd(MasterSocket,true,X_ESTAB_DNS);
return id;
}
+/* Start lookup of an IP address to a hostname */
+int DNS::GetNameForce(const char *ip, ForceProtocol fp)
+{
+ char query[128];
+ DNSHeader h;
+ int id;
+ int length;
+#ifdef SUPPORT_IP6LINKS
+ if (fp == PROTOCOL_IPV6)
+ {
+ in6_addr i;
+ if (inet_pton(AF_INET6, ip, &i) > 0)
+ {
+ DNS::MakeIP6Int(query, &i);
+ }
+ else
+ /* Invalid IP address */
+ return -1;
+ }
+ else
+#endif
+ {
+ in_addr i;
+ if (inet_aton(ip, &i))
+ {
+ unsigned char* c = (unsigned char*)&i.s_addr;
+ sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[3],c[2],c[1],c[0]);
+ }
+ else
+ /* Invalid IP address */
+ return -1;
+ }
+
+ log(DEBUG,"DNS::GetNameForce: %s %d",query, fp);
+
+ if ((length = this->MakePayload(query, DNS_QUERY_PTR, 1, (unsigned char*)&h.payload)) == -1)
+ return -1;
+
+ DNSRequest* req = this->AddQuery(&h, id);
+
+ if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_PTR) == -1))
+ return -1;
+
+ return id;
+}
+
void DNS::MakeIP6Int(char* query, const in6_addr *ip)
{
- sprintf(query,"%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.%0x.ip6.int",
- ip->s6_addr[15] & 0x0f,
- (ip->s6_addr[15] & 0xf0) >> 4,
- ip->s6_addr[14] & 0x0f,
- (ip->s6_addr[14] & 0xf0) >> 4,
- ip->s6_addr[13] & 0x0f,
- (ip->s6_addr[13] & 0xf0) >> 4,
- ip->s6_addr[12] & 0x0f,
- (ip->s6_addr[12] & 0xf0) >> 4,
- ip->s6_addr[11] & 0x0f,
- (ip->s6_addr[11] & 0xf0) >> 4,
- ip->s6_addr[10] & 0x0f,
- (ip->s6_addr[10] & 0xf0) >> 4,
- ip->s6_addr[9] & 0x0f,
- (ip->s6_addr[9] & 0xf0) >> 4,
- ip->s6_addr[8] & 0x0f,
- (ip->s6_addr[8] & 0xf0) >> 4,
- ip->s6_addr[7] & 0x0f,
- (ip->s6_addr[7] & 0xf0) >> 4,
- ip->s6_addr[6] & 0x0f,
- (ip->s6_addr[6] & 0xf0) >> 4,
- ip->s6_addr[5] & 0x0f,
- (ip->s6_addr[5] & 0xf0) >> 4,
- ip->s6_addr[4] & 0x0f,
- (ip->s6_addr[4] & 0xf0) >> 4,
- ip->s6_addr[3] & 0x0f,
- (ip->s6_addr[3] & 0xf0) >> 4,
- ip->s6_addr[2] & 0x0f,
- (ip->s6_addr[2] & 0xf0) >> 4,
- ip->s6_addr[1] & 0x0f,
- (ip->s6_addr[1] & 0xf0) >> 4,
- ip->s6_addr[0] & 0x0f,
- (ip->s6_addr[0] & 0xf0) >> 4
- );
+#ifdef SUPPORT_IP6LINKS
+ const char* hex = "0123456789abcdef";
+ for (int index = 31; index >= 0; index--) /* for() loop steps twice per byte */
+ {
+ if (index % 2)
+ /* low nibble */
+ *query++ = hex[ip->s6_addr[index / 2] & 0x0F];
+ else
+ /* high nibble */
+ *query++ = hex[(ip->s6_addr[index / 2] & 0xF0) >> 4];
+ *query++ = '.'; /* Seperator */
+ }
+ strcpy(query,"ip6.arpa"); /* Suffix the string */
+#else
+ *query = 0;
+#endif
}
/* Return the next id which is ready, and the result attached to it */
int length = recvfrom(MasterSocket,buffer,sizeof(DNSHeader),0,&from,&x);
+ if (length < 0)
+ log(DEBUG,"Error in recvfrom()! (%s)",strerror(errno));
+
/* Did we get the whole header? */
if (length < 12)
+ {
/* Nope - something screwed up. */
+ log(DEBUG,"Whole header not read!");
return std::make_pair(-1,"");
+ }
/* Check wether the reply came from a different DNS
* server to the one we sent it to, or the source-port
port_from = ntohs(((sockaddr_in*)&from)->sin_port);
#endif
- if ((port_from != DNS::QUERY_PORT) || (strcasecmp(ipaddr_from, Config->DNSServer)))
- return std::make_pair(-1,"");
+ /* We cant perform this security check if you're using 4in6.
+ * Tough luck to you, choose one or't other!
+ */
+ if (!ip6munge)
+ {
+ if ((port_from != DNS::QUERY_PORT) || (strcasecmp(ipaddr_from, Config->DNSServer)))
+ {
+ log(DEBUG,"port %d is not 53, or %s is not %s",port_from, ipaddr_from, Config->DNSServer);
+ return std::make_pair(-1,"");
+ }
+ }
/* Put the read header info into a header class */
DNS::FillHeader(&header,buffer,length - 12);
memmove(formatted,formatted + 1, strlen(formatted + 1) + 1);
}
resultstr = formatted;
+
+ /* Special case. Sending ::1 around between servers
+ * and to clients is dangerous, because the : on the
+ * start makes the client or server interpret the IP
+ * as the last parameter on the line with a value ":1".
+ */
+ if (*formatted == ':')
+ resultstr = "0" + resultstr;
}
break;
/* Reverse lookups just come back as char* */
resultstr = std::string((const char*)data.first);
break;
+
+ default:
+ log(DEBUG,"WARNING: Somehow we made a request for a DNS_QUERY_PTR4 or DNS_QUERY_PTR6, but these arent real rr types!");
+ break;
}
}
break;
+ case DNS_QUERY_PTR4:
+ querytype = DNS_QUERY_PTR;
+ this->myid = ServerInstance->Res->GetNameForce(source.c_str(), PROTOCOL_IPV4);
+ break;
+
+ case DNS_QUERY_PTR6:
+ querytype = DNS_QUERY_PTR;
+ this->myid = ServerInstance->Res->GetNameForce(source.c_str(), PROTOCOL_IPV6);
+ break;
+
case DNS_QUERY_AAAA:
this->myid = ServerInstance->Res->GetIP6(source.c_str());
break;
/* Process a socket read event */
void DNS::MarshallReads(int fd)
{
+ log(DEBUG,"Marshall reads: %d %d",fd,GetMasterSocket());
/* We are only intrested in our single fd */
if (fd == GetMasterSocket())
{