function Query($question, $type = "A") { $this->ClearError(); $typeid = $this->types->GetByName($type); if ($typeid === false) { $this->SetError("Invalid Query Type " . $type); return false; } if ($this->udp) { $host = "udp://" . $this->server; } else { $host = $this->server; } if (!($socket = fsockopen($host, $this->port, $this->timeout))) { $this->SetError("Failed to Open Socket"); return false; } // Split Into Labels if (preg_match("/[a-z|A-Z]/", $question) == 0) { $labeltmp = explode(".", $question); // reverse ARPA format for ($i = count($labeltmp) - 1; $i >= 0; $i--) { $labels[] = $labeltmp[$i]; } $labels[] = "IN-ADDR"; $labels[] = "ARPA"; } else { // hostname $labels = explode(".", $question); } $question_binary = ""; for ($a = 0; $a < count($labels); $a++) { $size = strlen($labels[$a]); $question_binary .= pack("C", $size); // size byte first $question_binary .= $labels[$a]; // then the label } $question_binary .= pack("C", 0); // end it off $this->Debug("Question: " . $question . " (type=" . $type . "/" . $typeid . ")"); $id = rand(1, 255) | rand(0, 255) << 8; // generate the ID // Set standard codes and flags $flags = 0x100 & 0x300; // recursion & queryspecmask $opcode = 0x0; // opcode // Build the header $header = ""; $header .= pack("n", $id); $header .= pack("n", $opcode | $flags); $header .= pack("nnnn", 1, 0, 0, 0); $header .= $question_binary; $header .= pack("n", $typeid); $header .= pack("n", 0x1); // internet class $headersize = strlen($header); $headersizebin = pack("n", $headersize); $this->Debug("Header Length: " . $headersize . " Bytes"); $this->DebugBinary($header); if ($this->udp && $headersize >= 512) { $this->SetError("Question too big for UDP (" . $headersize . " bytes)"); fclose($socket); return false; } if ($this->udp) { if (!fwrite($socket, $header, $headersize)) { $this->SetError("Failed to write question to socket"); fclose($socket); return false; } if (!($this->rawbuffer = fread($socket, 4096))) { $this->SetError("Failed to write read data buffer"); fclose($socket); return false; } } else { if (!fwrite($socket, $headersizebin)) { $this->SetError("Failed to write question length to TCP socket"); fclose($socket); return false; } if (!fwrite($socket, $header, $headersize)) { $this->SetError("Failed to write question to TCP socket"); fclose($socket); return false; } if (!($returnsize = fread($socket, 2))) { $this->SetError("Failed to read size from TCP socket"); fclose($socket); return false; } $tmplen = unpack("nlength", $returnsize); $datasize = $tmplen['length']; $this->Debug("TCP Stream Length Limit " . $datasize); if (!($this->rawbuffer = fread($socket, $datasize))) { $this->SetError("Failed to read data buffer"); fclose($socket); return false; } } fclose($socket); $buffersize = strlen($this->rawbuffer); $this->Debug("Read Buffer Size " . $buffersize); if ($buffersize < 12) { $this->SetError("Return Buffer too Small"); return false; } $this->rawheader = substr($this->rawbuffer, 0, 12); // first 12 bytes is the header $this->rawresponse = substr($this->rawbuffer, 12); // after that the response $this->responsecounter = 12; // start parsing response counter from 12 - no longer using response so can do pointers $this->DebugBinary($this->rawbuffer); $this->header = unpack("nid/nspec/nqdcount/nancount/nnscount/narcount", $this->rawheader); $answers = $this->header['ancount']; $this->Debug("Query Returned " . $answers . " Answers"); $dns_answer = new DNSAnswer(); // Deal with the header question data if ($this->header['qdcount'] > 0) { $this->Debug("Found " . $this->header['qdcount'] . " Questions"); for ($a = 0; $a < $this->header['qdcount']; $a++) { $c = 1; while ($c != 0) { $c = hexdec(bin2hex($this->ReadResponse(1))); } $extradata = $this->ReadResponse(4); } } // New Functional Method for ($a = 0; $a < $this->header['ancount']; $a++) { $record = $this->ReadRecord(); $dns_answer->AddResult($record['header']['type'], $record['typeid'], $record['header']['class'], $record['header']['ttl'], $record['data'], $record['domain'], $record['string'], $record['extras']); } $this->lastnameservers = new DNSAnswer(); for ($a = 0; $a < $this->header['nscount']; $a++) { $record = $this->ReadRecord(); $this->lastnameservers->AddResult($record['header']['type'], $record['typeid'], $record['header']['class'], $record['header']['ttl'], $record['data'], $record['domain'], $record['string'], $record['extras']); } $this->lastadditional = new DNSAnswer(); for ($a = 0; $a < $this->header['arcount']; $a++) { $record = $this->ReadRecord(); $this->lastadditional->AddResult($record['header']['type'], $record['typeid'], $record['header']['class'], $record['header']['ttl'], $record['data'], $record['domain'], $record['string'], $record['extras']); } return $dns_answer; }