Exemplo n.º 1
0
 /**
  * sends a standard Net_DNS2_Packet_Request packet
  *
  * @param Net_DNS2_Packet $request a Net_DNS2_Packet_Request object
  * @param boolean         $use_tcp true/false if the function should
  *                                 use TCP for the request
  *
  * @return mixed returns a Net_DNS2_Packet_Response object, or false on error
  * @throws Net_DNS2_Exception
  * @access protected
  *
  */
 protected function sendPacket(Net_DNS2_Packet $request, $use_tcp)
 {
     //
     // get the data from the packet
     //
     $data = $request->get();
     if (strlen($data) < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
         throw new Net_DNS2_Exception('invalid or empty packet for sending!', Net_DNS2_Lookups::E_PACKET_INVALID, null, $request);
     }
     reset($this->nameservers);
     //
     // randomize the name server list if it's asked for
     //
     if ($this->ns_random == true) {
         shuffle($this->nameservers);
     }
     //
     // loop so we can handle server errors
     //
     $response = null;
     $ns = '';
     while (1) {
         //
         // grab the next DNS server
         //
         $ns = each($this->nameservers);
         if ($ns === false) {
             if (is_null($this->last_exception) == false) {
                 throw $this->last_exception;
             } else {
                 throw new Net_DNS2_Exception('every name server provided has failed', Net_DNS2_Lookups::E_NS_FAILED);
             }
         }
         $ns = $ns[1];
         //
         // if the use TCP flag (force TCP) is set, or the packet is bigger than our
         // max allowed UDP size- which is either 512, or if this is DNSSEC request,
         // then whatever the configured dnssec_payload_size is.
         //
         $max_udp_size = Net_DNS2_Lookups::DNS_MAX_UDP_SIZE;
         if ($this->dnssec == true) {
             $max_udp_size = $this->dnssec_payload_size;
         }
         if ($use_tcp == true || strlen($data) > $max_udp_size) {
             try {
                 $response = $this->sendTCPRequest($ns, $data, $request->question[0]->qtype == 'AXFR' ? true : false);
             } catch (Net_DNS2_Exception $e) {
                 $this->last_exception = $e;
                 $this->last_exception_list[$ns] = $e;
                 continue;
             }
             //
             // otherwise, send it using UDP
             //
         } else {
             try {
                 $response = $this->sendUDPRequest($ns, $data);
                 //
                 // check the packet header for a trucated bit; if it was truncated,
                 // then re-send the request as TCP.
                 //
                 if ($response->header->tc == 1) {
                     $response = $this->sendTCPRequest($ns, $data);
                 }
             } catch (Net_DNS2_Exception $e) {
                 $this->last_exception = $e;
                 $this->last_exception_list[$ns] = $e;
                 continue;
             }
         }
         //
         // make sure header id's match between the request and response
         //
         if ($request->header->id != $response->header->id) {
             $this->last_exception = new Net_DNS2_Exception('invalid header: the request and response id do not match.', Net_DNS2_Lookups::E_HEADER_INVALID, null, $request, $response);
             $this->last_exception_list[$ns] = $this->last_exception;
             continue;
         }
         //
         // make sure the response is actually a response
         //
         // 0 = query, 1 = response
         //
         if ($response->header->qr != Net_DNS2_Lookups::QR_RESPONSE) {
             $this->last_exception = new Net_DNS2_Exception('invalid header: the response provided is not a response packet.', Net_DNS2_Lookups::E_HEADER_INVALID, null, $request, $response);
             $this->last_exception_list[$ns] = $this->last_exception;
             continue;
         }
         //
         // make sure the response code in the header is ok
         //
         if ($response->header->rcode != Net_DNS2_Lookups::RCODE_NOERROR) {
             $this->last_exception = new Net_DNS2_Exception('DNS request failed: ' . Net_DNS2_Lookups::$result_code_messages[$response->header->rcode], $response->header->rcode, null, $request, $response);
             $this->last_exception_list[$ns] = $this->last_exception;
             continue;
         }
         break;
     }
     return $response;
 }
Exemplo n.º 2
0
 /**
  * sends a standard Net_DNS2_Packet_Request packet
  *
  * @param Net_DNS2_Packet $request a Net_DNS2_Packet_Request object
  * @param boolean         $use_tcp true/false if the function should
  *                                 use TCP for the request
  *
  * @return mixed returns a Net_DNS2_Packet_Response object, or false on error
  * @throws Net_DNS2_Exception
  * @access protected
  *
  */
 protected function sendPacket(Net_DNS2_Packet $request, $use_tcp)
 {
     //
     // get the data from the packet
     //
     $data = $request->get();
     if (strlen($data) < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
         throw new Net_DNS2_Exception('invalid or empty packet for sending!', Net_DNS2_Lookups::E_PACKET_INVALID, null, $request);
     }
     reset($this->nameservers);
     //
     // randomize the name server list if it's asked for
     //
     if ($this->ns_random == true) {
         shuffle($this->nameservers);
     }
     //
     // loop so we can handle server errors
     //
     $response = null;
     $ns = '';
     $socket_type = null;
     $tcp_fallback = false;
     while (1) {
         //
         // grab the next DNS server
         //
         if ($tcp_fallback == false) {
             $ns = each($this->nameservers);
             if ($ns === false) {
                 throw new Net_DNS2_Exception('every name server provided has failed: ' . $this->_last_socket_error, Net_DNS2_Lookups::E_NS_FAILED);
             }
             $ns = $ns[1];
         }
         //
         // if the use TCP flag (force TCP) is set, or the packet is bigger
         // than 512 bytes, use TCP for sending the packet
         //
         if ($use_tcp == true || strlen($data) > Net_DNS2_Lookups::DNS_MAX_UDP_SIZE || $tcp_fallback == true) {
             $tcp_fallback = false;
             $socket_type = Net_DNS2_Socket::SOCK_STREAM;
             //
             // create the socket object
             //
             if (!isset($this->sock['tcp'][$ns]) || !$this->sock['tcp'][$ns] instanceof Net_DNS2_Socket) {
                 if ($this->sockets_enabled === true) {
                     $this->sock['tcp'][$ns] = new Net_DNS2_Socket_Sockets(Net_DNS2_Socket::SOCK_STREAM, $ns, $this->dns_port, $this->timeout);
                 } else {
                     $this->sock['tcp'][$ns] = new Net_DNS2_Socket_Streams(Net_DNS2_Socket::SOCK_STREAM, $ns, $this->dns_port, $this->timeout);
                 }
             }
             //
             // if a local IP address / port is set, then add it
             //
             if (strlen($this->local_host) > 0) {
                 $this->sock['tcp'][$ns]->bindAddress($this->local_host, $this->local_port);
             }
             //
             // open it; if it fails, continue in the while loop
             //
             if ($this->sock['tcp'][$ns]->open() === false) {
                 $this->_last_socket_error = $this->sock['tcp'][$ns]->last_error;
                 continue;
             }
             //
             // write the data to the socket; if it fails, continue on
             // the while loop
             //
             if ($this->sock['tcp'][$ns]->write($data) === false) {
                 $this->_last_socket_error = $this->sock['tcp'][$ns]->last_error;
                 continue;
             }
             //
             // read the content, using select to wait for a response
             //
             $size = 0;
             $result = null;
             //
             // handle zone transfer requests differently than other requests.
             //
             if ($request->question[0]->qtype == 'AXFR') {
                 $soa_count = 0;
                 while (1) {
                     //
                     // read the data off the socket
                     //
                     $result = $this->sock['tcp'][$ns]->read($size);
                     if ($result === false || $size < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
                         $this->_last_socket_error = $this->sock['tcp'][$ns]->last_error;
                         break;
                     }
                     //
                     // parse the first chunk as a packet
                     //
                     $chunk = new Net_DNS2_Packet_Response($result, $size);
                     //
                     // if this is the first packet, then clone it directly, then
                     // go through it to see if there are two SOA records
                     // (indicating that it's the only packet)
                     //
                     if (is_null($response) == true) {
                         $response = clone $chunk;
                         //
                         // look for a failed response; if the zone transfer
                         // failed, then we don't need to do anything else at this
                         // point, and we should just break out.
                         //
                         if ($response->header->rcode != Net_DNS2_Lookups::RCODE_NOERROR) {
                             break;
                         }
                         //
                         // go through each answer
                         //
                         foreach ($response->answer as $index => $rr) {
                             //
                             // count the SOA records
                             //
                             if ($rr->type == 'SOA') {
                                 $soa_count++;
                             }
                         }
                         //
                         // if we have 2 or more SOA records, then we're done;
                         // otherwise continue out so we read the rest of the
                         // packets off the socket
                         //
                         if ($soa_count >= 2) {
                             break;
                         } else {
                             continue;
                         }
                     } else {
                         //
                         // go through all these answers, and look for SOA records
                         //
                         foreach ($chunk->answer as $index => $rr) {
                             //
                             // count the number of SOA records we find
                             //
                             if ($rr->type == 'SOA') {
                                 $soa_count++;
                             }
                             //
                             // add the records to a single response object
                             //
                             $response->answer[] = $rr;
                         }
                         //
                         // if we've found the second SOA record, we're done
                         //
                         if ($soa_count >= 2) {
                             break;
                         }
                     }
                 }
             } else {
                 $result = $this->sock['tcp'][$ns]->read($size);
                 if ($result === false || $size < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
                     $this->_last_socket_error = $this->sock['tcp'][$ns]->last_error;
                     continue;
                 }
                 //
                 // create the packet object
                 //
                 $response = new Net_DNS2_Packet_Response($result, $size);
             }
             break;
         } else {
             $socket_type = Net_DNS2_Socket::SOCK_DGRAM;
             //
             // create the socket object
             //
             if (!isset($this->sock['udp'][$ns]) || !$this->sock['udp'][$ns] instanceof Net_DNS2_Socket) {
                 if ($this->sockets_enabled === true) {
                     $this->sock['udp'][$ns] = new Net_DNS2_Socket_Sockets(Net_DNS2_Socket::SOCK_DGRAM, $ns, $this->dns_port, $this->timeout);
                 } else {
                     $this->sock['udp'][$ns] = new Net_DNS2_Socket_Streams(Net_DNS2_Socket::SOCK_DGRAM, $ns, $this->dns_port, $this->timeout);
                 }
             }
             //
             // if a local IP address / port is set, then add it
             //
             if (strlen($this->local_host) > 0) {
                 $this->sock['udp'][$ns]->bindAddress($this->local_host, $this->local_port);
             }
             //
             // open it
             //
             if ($this->sock['udp'][$ns]->open() === false) {
                 $this->_last_socket_error = $this->sock['udp'][$ns]->last_error;
                 continue;
             }
             //
             // write the data to the socket
             //
             if ($this->sock['udp'][$ns]->write($data) === false) {
                 $this->_last_socket_error = $this->sock['udp'][$ns]->last_error;
                 continue;
             }
             //
             // read the content, using select to wait for a response
             //
             $size = 0;
             $result = $this->sock['udp'][$ns]->read($size);
             if ($result === false || $size < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
                 $this->_last_socket_error = $this->sock['udp'][$ns]->last_error;
                 continue;
             }
             //
             // create the packet object
             //
             $response = new Net_DNS2_Packet_Response($result, $size);
             if (is_null($response)) {
                 throw new Net_DNS2_Exception('empty response object', Net_DNS2_Lookups::E_NS_FAILED, null, $request);
             }
             //
             // check the packet header for a trucated bit; if it was truncated,
             // then re-send the request as TCP.
             //
             if ($response->header->tc == 1) {
                 $tcp_fallback = true;
                 continue;
             }
             break;
         }
     }
     //
     // if $response is null, then we didn't even try once; which shouldn't
     // actually ever happen
     //
     if (is_null($response)) {
         throw new Net_DNS2_Exception('empty response object', Net_DNS2_Lookups::E_NS_FAILED, null, $request);
     }
     //
     // add the name server that the response came from to the response object,
     // and the socket type that was used.
     //
     $response->answer_from = $ns;
     $response->answer_socket_type = $socket_type;
     //
     // make sure header id's match between the request and response
     //
     if ($request->header->id != $response->header->id) {
         throw new Net_DNS2_Exception('invalid header: the request and response id do not match.', Net_DNS2_Lookups::E_HEADER_INVALID, null, $request, $response);
     }
     //
     // make sure the response is actually a response
     //
     // 0 = query, 1 = response
     //
     if ($response->header->qr != Net_DNS2_Lookups::QR_RESPONSE) {
         throw new Net_DNS2_Exception('invalid header: the response provided is not a response packet.', Net_DNS2_Lookups::E_HEADER_INVALID, null, $request, $response);
     }
     //
     // make sure the response code in the header is ok
     //
     if ($response->header->rcode != Net_DNS2_Lookups::RCODE_NOERROR) {
         throw new Net_DNS2_Exception('DNS request failed: ' . Net_DNS2_Lookups::$result_code_messages[$response->header->rcode], $response->header->rcode, null, $request, $response);
     }
     return $response;
 }
Exemplo n.º 3
0
 /**
  * sends a standard Net_DNS2_Packet_Request packet
  *
  * @param Net_DNS2_Packet $request a Net_DNS2_Packet_Request object
  * @param boolean         $use_tcp true/false if the function should
  *                                 use TCP for the request
  *
  * @return mixed returns a Net_DNS2_Packet_Response object, or false on error
  * @throws Net_DNS2_Exception
  * @access protected
  *
  */
 protected function sendPacket(Net_DNS2_Packet $request, $use_tcp)
 {
     //
     // get the data from the packet
     //
     $data = $request->get();
     if (strlen($data) < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
         throw new Net_DNS2_Exception('invalid or empty packet for sending!', Net_DNS2_Lookups::E_PACKET_INVALID);
     }
     reset($this->nameservers);
     //
     // randomize the name server list if it's asked for
     //
     if ($this->ns_random == true) {
         shuffle($this->nameservers);
     }
     //
     // loop so we can handle server errors
     //
     $response = null;
     $ns = '';
     $tcp_fallback = false;
     while (1) {
         //
         // grab the next DNS server
         //
         if ($tcp_fallback == false) {
             $ns = each($this->nameservers);
             if ($ns === false) {
                 throw new Net_DNS2_Exception('every name server provided has failed: ' . $this->_last_socket_error, Net_DNS2_Lookups::E_NS_FAILED);
             }
             $ns = $ns[1];
         }
         //
         // if the use TCP flag (force TCP) is set, or the packet is bigger
         // than 512 bytes, use TCP for sending the packet
         //
         if ($use_tcp == true || strlen($data) > Net_DNS2_Lookups::DNS_MAX_UDP_SIZE || $tcp_fallback == true) {
             $tcp_fallback = false;
             //
             // create the socket object
             //
             if (!isset($this->sock['tcp'][$ns]) || !$this->sock['tcp'][$ns] instanceof Net_DNS2_Socket) {
                 if ($this->sockets_enabled === true) {
                     $this->sock['tcp'][$ns] = new Net_DNS2_Socket_Sockets(SOCK_STREAM, $ns, $this->dns_port, $this->timeout);
                 } else {
                     $this->sock['tcp'][$ns] = new Net_DNS2_Socket_Streams(SOCK_STREAM, $ns, $this->dns_port, $this->timeout);
                 }
             }
             //
             // if a local IP address / port is set, then add it
             //
             if (strlen($this->local_host) > 0) {
                 $this->sock['tcp'][$ns]->bindAddress($this->local_host, $this->local_port);
             }
             //
             // open it; if it fails, continue in the while loop
             //
             if ($this->sock['tcp'][$ns]->open() === false) {
                 $this->_last_socket_error = $this->sock['tcp'][$ns]->last_error;
                 continue;
             }
             //
             // write the data to the socket; if it fails, continue on
             // the while loop
             //
             if ($this->sock['tcp'][$ns]->write($data) === false) {
                 $this->_last_socket_error = $this->sock['tcp'][$ns]->last_error;
                 continue;
             }
             //
             // read the content, using select to wait for a response
             //
             $size = 0;
             $result = $this->sock['tcp'][$ns]->read($size);
             if ($result === false || $size < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
                 $this->_last_socket_error = $this->sock['tcp'][$ns]->last_error;
                 continue;
             }
             //
             // create the packet object
             //
             $response = new Net_DNS2_Packet_Response($result, $size);
             break;
         } else {
             //
             // create the socket object
             //
             if (!isset($this->sock['udp'][$ns]) || !$this->sock['udp'][$ns] instanceof Net_DNS2_Socket) {
                 if ($this->sockets_enabled === true) {
                     $this->sock['udp'][$ns] = new Net_DNS2_Socket_Sockets(SOCK_DGRAM, $ns, $this->dns_port, $this->timeout);
                 } else {
                     $this->sock['udp'][$ns] = new Net_DNS2_Socket_Streams(SOCK_DGRAM, $ns, $this->dns_port, $this->timeout);
                 }
             }
             //
             // if a local IP address / port is set, then add it
             //
             if (strlen($this->local_host) > 0) {
                 $this->sock['udp'][$ns]->bindAddress($this->local_host, $this->local_port);
             }
             //
             // open it
             //
             if ($this->sock['udp'][$ns]->open() === false) {
                 $this->_last_socket_error = $this->sock['udp'][$ns]->last_error;
                 continue;
             }
             //
             // write the data to the socket
             //
             if ($this->sock['udp'][$ns]->write($data) === false) {
                 $this->_last_socket_error = $this->sock['udp'][$ns]->last_error;
                 continue;
             }
             //
             // read the content, using select to wait for a response
             //
             $size = 0;
             $result = $this->sock['udp'][$ns]->read($size);
             if ($result === false || $size < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
                 $this->_last_socket_error = $this->sock['udp'][$ns]->last_error;
                 continue;
             }
             //
             // create the packet object
             //
             $response = new Net_DNS2_Packet_Response($result, $size);
             //
             // check the packet header for a trucated bit; if it was truncated,
             // then re-send the request as TCP.
             //
             if ($response->header->tc == 1) {
                 $tcp_fallback = true;
                 continue;
             }
             break;
         }
     }
     if (is_null($response)) {
         return false;
     }
     //
     // make sure header id's match between the request and response
     //
     if ($request->header->id != $response->header->id) {
         throw new Net_DNS2_Exception('invalid header: the request and response id do not match.', Net_DNS2_Lookups::E_HEADER_INVALID);
     }
     //
     // make sure the response is actually a response
     //
     // 0 = query, 1 = response
     //
     if ($response->header->qr != Net_DNS2_Lookups::QR_RESPONSE) {
         throw new Net_DNS2_Exception('invalid header: the response provided is not a response packet.', Net_DNS2_Lookups::E_HEADER_INVALID);
     }
     //
     // make sure the response code in the header is ok
     //
     if ($response->header->rcode != Net_DNS2_Lookups::RCODE_NOERROR) {
         throw new Net_DNS2_Exception('DNS request failed: ' . Net_DNS2_Lookups::$result_code_messages[$response->header->rcode], $response->header->rcode);
     }
     return $response;
 }