|
Server IP : 127.0.0.1 / Your IP : 127.0.0.1 Web Server : Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.6.3 System : Windows NT WIN-R7LTCC7BPLI 6.3 build 9200 (Windows Server 2012 R2 Datacenter Edition) i586 User : GerbangSIPAD ( 0) PHP Version : 5.6.3 Disable Function : NONE MySQL : ON | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF Directory (0777) : C:/xampp5/php/pear/Net/ |
| [ Home ] | [ C0mmand ] | [ Upload File ] |
|---|
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* DNS Library for handling lookups and updates.
*
* PHP Version 5
*
* Copyright (c) 2010, Mike Pultz <mike@mikepultz.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Pultz nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2010 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id: DNS2.php 137 2011-12-05 02:51:34Z mike.pultz $
* @link http://pear.php.net/package/Net_DNS2
* @since File available since Release 0.6.0
*
*/
/*
* register the auto-load function
*
*/
spl_autoload_register('Net_DNS2::autoload');
/**
* This is the base class for the Net_DNS2_Resolver and Net_DNS2_Updater
* classes.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://pear.php.net/package/Net_DNS2
* @see Net_DNS2_Resolver, Net_DNS2_Updater
*
*/
class Net_DNS2
{
/*
* the current version of this library
*/
const VERSION = '1.2.0';
/*
* the default path to a resolv.conf file
*/
const RESOLV_CONF = '/etc/resolv.conf';
/*
* use TCP only (true/false)
*/
public $use_tcp = false;
/*
* DNS Port to use (53)
*/
public $dns_port = 53;
/*
* the ip/port for use as a local socket
*/
public $local_host = '';
public $local_port = 0;
/*
* timeout value for socket connections
*/
public $timeout = 5;
/*
* randomize the name servers list
*/
public $ns_random = false;
/*
* default domains
*/
public $domain = '';
/*
* domain search list - not actually used right now
*/
public $search_list = array();
/*
* enable cache; either "shared", "file" or "none"
*/
public $cache_type = 'none';
/*
* file name to use for shared memory segment or file cache
*/
public $cache_file = '/tmp/net_dns2.cache';
/*
* the max size of the cache file (in bytes)
*/
public $cache_size = 10000;
/*
* the method to use for storing cache data; either "serialize" or "json"
*
* json is faster, but can't remember the class names (everything comes back as a
* "stdClass Object"; all the data is the same though. serialize is slower, but will
* have all the class info.
*
* defaults to 'serialize'
*/
public $cache_serializer = 'serialize';
/*
* local sockets
*/
protected $sock = array('udp' => array(), 'tcp' => array());
/*
* name server list
*/
protected $nameservers = array();
/*
* if the socket extension is loaded
*/
protected $sockets_enabled = false;
/*
* the TSIG or SIG RR object for authentication
*/
protected $auth_signature = null;
/*
* the shared memory segment id for the local cache
*/
protected $cache = null;
/*
* internal setting for enabling cache
*/
protected $use_cache = false;
/*
* the last erro message returned by the sockets class
*/
private $_last_socket_error = '';
/**
* Constructor - base constructor for the Resolver and Updater
*
* @param mixed $options array of options or null for none
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct(array $options = null)
{
//
// check for the sockets extension
//
$this->sockets_enabled = extension_loaded('sockets');
//
// load any options that were provided
//
if (!empty($options)) {
foreach ($options as $key => $value) {
if ($key == 'nameservers') {
$this->setServers($value);
} else {
$this->$key = $value;
}
}
}
//
// if we're set to use the local shared memory cache, then
// make sure it's been initialized
//
switch($this->cache_type) {
case 'shared':
if (extension_loaded('shmop')) {
$this->cache = new Net_DNS2_Cache_Shm;
$this->use_cache = true;
} else {
throw new Net_DNS2_Exception(
'shmop library is not available for cache',
Net_DNS2_Lookups::E_CACHE_SHM_UNAVAIL
);
}
break;
case 'file':
$this->cache = new Net_DNS2_Cache_File;
$this->use_cache = true;
break;
case 'none':
$this->use_cache = false;
break;
default:
throw new Net_DNS2_Exception(
'un-supported cache type: ' . $this->cache_type,
Net_DNS2_Lookups::E_CACHE_UNSUPPORTED
);
}
}
/**
* autoload call-back function; used to auto-load classes
*
* @param string $name the name of the class
*
* @return void
* @access public
*
*/
static public function autoload($name)
{
//
// only auto-load our classes
//
if (strncmp($name, 'Net_DNS2', 8) == 0) {
include str_replace('_', '/', $name) . '.php';
}
return;
}
/**
* sets the name servers to be used
*
* @param mixed $nameservers either an array of name servers, or a file name
* to parse, assuming it's in the resolv.conf format
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function setServers($nameservers)
{
//
// if it's an array, then use it directly
//
// otherwise, see if it's a path to a resolv.conf file and if so, load it
//
if (is_array($nameservers)) {
$this->nameservers = $nameservers;
} else {
//
// check to see if the file is readable
//
if (is_readable($nameservers) === true) {
$data = file_get_contents($nameservers);
if ($data === false) {
throw new Net_DNS2_Exception(
'failed to read contents of file: ' . $nameservers,
Net_DNS2_Lookups::E_NS_INVALID_FILE
);
}
$lines = explode("\n", $data);
foreach ($lines as $line) {
$line = trim($line);
//
// ignore empty lines, and lines that are commented out
//
if ( (strlen($line) == 0)
|| ($line[0] == '#')
|| ($line[0] == ';')
) {
continue;
}
list($key, $value) = preg_split('/\s+/', $line, 2);
$key = trim(strtolower($key));
$value = trim(strtolower($value));
switch($key) {
case 'nameserver':
//
// nameserver can be a IPv4 or IPv6 address
//
if ( (self::isIPv4($value) == true)
|| (self::isIPv6($value) == true)
) {
$this->nameservers[] = $value;
} else {
throw new Net_DNS2_Exception(
'invalid nameserver entry: ' . $value,
Net_DNS2_Lookups::E_NS_INVALID_ENTRY
);
}
break;
case 'domain':
$this->domain = $value;
break;
case 'search':
$this->search_list = preg_split('/\s+/', $value);
break;
default:
;
}
}
//
// if we don't have a domain, but we have a search list, then
// take the first entry on the search list as the domain
//
if ( (strlen($this->domain) == 0)
&& (count($this->search_list) > 0)
) {
$this->domain = $this->search_list[0];
}
} else {
throw new Net_DNS2_Exception(
'resolver file file provided is not readable: ' . $nameservers,
Net_DNS2_Lookups::E_NS_INVALID_FILE
);
}
}
//
// check the name servers
//
$this->checkServers();
return true;
}
/**
* checks the list of name servers to make sure they're set
*
* @param mixed $default a path to a resolv.conf file or an array of servers.
*
* @return boolean
* @throws Net_DNS2_Exception
* @access protected
*
*/
protected function checkServers($default = null)
{
if (empty($this->nameservers)) {
if (isset($default)) {
$this->setServers($default);
} else {
throw new Net_DNS2_Exception(
'empty name servers list; you must provide a list of name '.
'servers, or the path to a resolv.conf file.',
Net_DNS2_Lookups::E_NS_INVALID_ENTRY
);
}
}
return true;
}
/**
* adds a TSIG RR object for authentication
*
* @param string $keyname the key name to use for the TSIG RR
* @param string $signature the key to sign the request.
*
* @return boolean
* @access public
* @since function available since release 1.1.0
*
*/
public function signTSIG($keyname, $signature = '')
{
//
// if the TSIG was pre-created and passed in, then we can just used
// it as provided.
//
if ($keyname instanceof Net_DNS2_RR_TSIG) {
$this->auth_signature = $keyname;
} else {
//
// otherwise create the TSIG RR, but don't add it just yet; TSIG needs
// to be added as the last additional entry- so we'll add it just
// before we send.
//
$this->auth_signature = Net_DNS2_RR::fromString(
strtolower(trim($keyname)) .
' TSIG '. $signature
);
}
return true;
}
/**
* adds a SIG RR object for authentication
*
* @param string $filename the name of a file to load the signature from.
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
* @since function available since release 1.1.0
*
*/
public function signSIG0($filename)
{
//
// check for OpenSSL
//
if (extension_loaded('openssl') === false) {
throw new Net_DNS2_Exception(
'the OpenSSL extension is required to use SIG(0).',
Net_DNS2_Lookups::E_OPENSSL_UNAVAIL
);
}
//
// if the SIG was pre-created, then use it as-is
//
if ($filename instanceof Net_DNS2_RR_SIG) {
$this->auth_signature = $filename;
} else {
//
// otherwise, it's filename which needs to be parsed and processed.
//
$private = new Net_DNS2_PrivateKey($filename);
//
// create a new Net_DNS2_RR_SIG object
//
$this->auth_signature = new Net_DNS2_RR_SIG();
//
// reset some values
//
$this->auth_signature->name = $private->signname;
$this->auth_signature->ttl = 0;
$this->auth_signature->class = 'ANY';
//
// these values are pulled from the private key
//
$this->auth_signature->algorithm = $private->algorithm;
$this->auth_signature->keytag = $private->keytag;
$this->auth_signature->signname = $private->signname;
//
// these values are hard-coded for SIG0
//
$this->auth_signature->typecovered = 'SIG0';
$this->auth_signature->labels = 0;
$this->auth_signature->origttl = 0;
//
// generate the dates
//
$t = time();
$this->auth_signature->sigincep = gmdate('YmdHis', $t);
$this->auth_signature->sigexp = gmdate('YmdHis', $t + 500);
//
// store the private key in the SIG object for later.
//
$this->auth_signature->private_key = $private;
}
//
// only RSAMD5 and RSASHA1 are supported for SIG(0)
//
switch($this->auth_signature->algorithm) {
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSAMD5:
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA1:
break;
default:
throw new Net_DNS2_Exception(
'only asymmetric algorithms work with SIG(0)!',
Net_DNS2_Lookups::E_OPENSSL_INV_ALGO
);
}
return true;
}
/**
* returns true/false if the given address is a valid IPv4 address
*
* @param string $_address the IPv4 address to check
*
* @return boolean returns true/false if the address is IPv4 address
* @access public
*
*/
public static function isIPv4($_address)
{
//
// use filter_var() if it's available; it's faster than preg
//
if (extension_loaded('filter') == true) {
if (filter_var(
$_address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4
) == false) {
return false;
}
} else {
//
// do the main check here;
//
if (inet_pton($_address) === false) {
return false;
}
//
// then make sure we're not a IPv6 address
//
if (preg_match(
'/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',
$_address
) == 0) {
return false;
}
}
return true;
}
/**
* returns true/false if the given address is a valid IPv6 address
*
* @param string $_address the IPv6 address to check
*
* @return boolean returns true/false if the address is IPv6 address
* @access public
*
*/
public static function isIPv6($_address)
{
//
// use filter_var() if it's available; it's faster than preg
//
if (extension_loaded('filter') == true) {
if (filter_var(
$_address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6
) == false) {
return false;
}
} else {
//
// do the main check here
//
if (inet_pton($_address) === false) {
return false;
}
//
// then make sure it doesn't match a IPv4 address
//
if (preg_match(
'/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $_address
) == 1) {
return false;
}
}
return true;
}
/**
* formats the given IPv6 address as a fully expanded IPv6 address
*
* @param string $_address the IPv6 address to expand
*
* @return string the fully expanded IPv6 address
* @access public
*
*/
public static function expandIPv6($_address)
{
if (strpos($_address, '::') !== false) {
$part = explode('::', $_address);
$part[0] = explode(':', $part[0]);
$part[1] = explode(':', $part[1]);
$missing = array();
$x = (8 - (count($part[0]) + count($part[1])));
for ($i = 0; $i < $x; $i++) {
array_push($missing, '0000');
}
$missing = array_merge($part[0], $missing);
$part = array_merge($missing, $part[1]);
} else {
$part = explode(':', $_address);
}
foreach ($part as &$p) {
while (strlen($p) < 4) {
$p = '0' . $p;
}
}
unset($p);
$result = implode(':', $part);
if (strlen($result) == 39) {
return $result;
} else {
return false;
}
}
/**
* 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;
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>