Net_DNS
[ class tree: Net_DNS ] [ index: Net_DNS ] [ all elements ]

Source for file Resolver.php

Documentation is available at Resolver.php

  1. <?php
  2. /*
  3.  *  License Information:
  4.  *
  5.  *    Net_DNS:  A resolver library for PHP
  6.  *    Copyright (c) 2002-2003 Eric Kilfoil eric@ypass.net
  7.  *
  8.  *    This library is free software; you can redistribute it and/or
  9.  *    modify it under the terms of the GNU Lesser General Public
  10.  *    License as published by the Free Software Foundation; either
  11.  *    version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  *    This library is distributed in the hope that it will be useful,
  14.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  *    Lesser General Public License for more details.
  17.  *
  18.  *    You should have received a copy of the GNU Lesser General Public
  19.  *    License along with this library; if not, write to the Free Software
  20.  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21.  */
  22.  
  23.  
  24. /* Net_DNS_Resolver object definition {{{ */
  25. /**
  26.  * A DNS Resolver library
  27.  *
  28.  * Resolver library.  Builds a DNS query packet, sends the packet to the
  29.  * server and parses the reponse.
  30.  *
  31.  * @package Net_DNS
  32.  */
  33. {
  34.     /* class variable definitions {{{ */
  35.     /**
  36.      * An array of all nameservers to query
  37.      *
  38.      * @var array $nameservers 
  39.      * @access public
  40.      */
  41.     var $nameservers;
  42.     /**
  43.      * The UDP port to use for the query (default = 53)
  44.      *
  45.      * @var integer $port 
  46.      * @access public
  47.      */
  48.     var $port;
  49.     /**
  50.      * The domain in which the resolver client host resides.
  51.      *
  52.      * @var string $domain 
  53.      * @access public
  54.      */
  55.     var $domain;
  56.     /**
  57.      * The searchlist to apply to unqualified hosts
  58.      *
  59.      * An array of strings containg domains to apply to unqualified hosts
  60.      * passed to the resolver.
  61.      *
  62.      * @var array $searchlist 
  63.      * @access public
  64.      */
  65.     var $searchlist;
  66.     /**
  67.      * The number of seconds between retransmission of unaswered queries
  68.      *
  69.      * @var integer $retrans 
  70.      * @access public
  71.      */
  72.     var $retrans;
  73.     /**
  74.      * The number of times unanswered requests should be retried
  75.      *
  76.      * @var integer $retry 
  77.      * @access public
  78.      */
  79.     var $retry;
  80.     /**
  81.      * Whether or not to use TCP (Virtual Circuits) instead of UDP
  82.      *
  83.      * If set to 0, UDP will be used unless TCP is required.  TCP is
  84.      * required for questions or responses greater than 512 bytes.
  85.      *
  86.      * @var boolean $usevc 
  87.      * @access public
  88.      */
  89.     var $usevc;
  90.     /**
  91.      * Unknown
  92.      */
  93.     var $stayopen;
  94.     /**
  95.      * Ignore TC (truncated) bit
  96.      *
  97.      * If the server responds with the TC bit set on a response, and $igntc
  98.      * is set to 0, the resolver will automatically retransmit the request
  99.      * using virtual circuits (TCP).
  100.      *
  101.      * @access public
  102.      * @var boolean $igntc 
  103.      */
  104.     var $igntc;
  105.     /**
  106.      * Recursion Desired
  107.      *
  108.      * Sets the value of the RD (recursion desired) bit in the header. If
  109.      * the RD bit is set to 0, the server will not perform recursion on the
  110.      * request.
  111.      *
  112.      * @var boolean $recurse 
  113.      * @access public
  114.      */
  115.     var $recurse;
  116.     /**
  117.      * Unknown
  118.      */
  119.     var $defnames;
  120.     /**
  121.      * Unknown
  122.      */
  123.     var $dnsrch;
  124.     /**
  125.      * Contains the value of the last error returned by the resolver.
  126.      *
  127.      * @var string $errorstring 
  128.      * @access public
  129.      */
  130.     var $errorstring;
  131.     /**
  132.      * The origin of the packet.
  133.      *
  134.      * This contains a string containing the IP address of the name server
  135.      * from which the answer was given.
  136.      *
  137.      * @var string $answerfrom 
  138.      * @access public
  139.      */
  140.     var $answerfrom;
  141.     /**
  142.      * The size of the answer packet.
  143.      *
  144.      * This contains a integer containing the size of the DNS packet the
  145.      * server responded with.
  146.      *
  147.      * @var string $answersize 
  148.      * @access public
  149.      */
  150.     var $answersize;
  151.     /**
  152.      * The number of seconds after which a TCP connection should timeout
  153.      *
  154.      * @var integer $tcp_timeout 
  155.      * @access public
  156.      */
  157.     var $tcp_timeout;
  158.     /**
  159.      * The location of the system resolv.conf file.
  160.      *
  161.      * @var string $resolv_conf 
  162.      */
  163.     var $resolv_conf = '/etc/resolv.conf';
  164.     /**
  165.      * The name of the user defined resolv.conf
  166.      *
  167.      * The resolver will attempt to look in both the current directory as
  168.      * well as the user's home directory for a user defined resolver
  169.      * configuration file
  170.      *
  171.      * @var string $dotfile 
  172.      * @see Net_DNS_Resolver::$confpath
  173.      */
  174.     var $dotfile = '.resolv.conf';
  175.     /**
  176.      * A array of directories to search for the user's resolver config
  177.      *
  178.      * @var string $confpath 
  179.      * @see Net_DNS_Resolver::$dotfile
  180.      */
  181.     var $confpath;
  182.     /**
  183.      * debugging flag
  184.      *
  185.      * If set to true (non-zero), debugging code will be displayed as the
  186.      * resolver makes the request.
  187.      *
  188.      * @var boolean $debug; 
  189.      * @access public
  190.      */
  191.     var $debug;
  192.     /**
  193.      * use the (currently) experimental PHP socket library
  194.      *
  195.      * If set to true (non-zero), the Resolver will attempt to use the
  196.      * much more effecient PHP sockets extension (if available).
  197.      *
  198.      * @var boolean $useEnhancedSockets; 
  199.      * @access public
  200.      */
  201.     var $useEnhancedSockets = true;
  202.     /**
  203.      * An array of sockets connected to a name servers
  204.      *
  205.      * @var array $sockets 
  206.      * @access private
  207.      */
  208.     var $sockets;
  209.     /**
  210.      * axfr tcp socket
  211.      *
  212.      * Used to store a PHP socket resource for a connection to a server
  213.      *
  214.      * @var resource $_axfr_sock; 
  215.      * @access private
  216.      */
  217.     var $_axfr_sock;
  218.     /**
  219.      * axfr resource record list
  220.      *
  221.      * Used to store a resource record list from a zone transfer
  222.      *
  223.      * @var resource $_axfr_rr; 
  224.      * @access private
  225.      */
  226.     var $_axfr_rr;
  227.     /**
  228.      * axfr soa count
  229.      *
  230.      * Used to store the number of soa records received from a zone transfer
  231.      *
  232.      * @var resource $_axfr_soa_count; 
  233.      * @access private
  234.      */
  235.     var $_axfr_soa_count;
  236.  
  237.  
  238.     /* }}} */
  239.     /* class constructor - Net_DNS_Resolver() {{{ */
  240.     /**
  241.      * Initializes the Resolver Object
  242.      *
  243.      * @return Net_DNS_Resolver 
  244.      */
  245.     function Net_DNS_Resolver($defaults = array())
  246.     {
  247.         $mydefaults = array(
  248.                 'nameservers' => array(),
  249.                 'port'        => '53',
  250.                 'domain'      => '',
  251.                 'searchlist'  => array(),
  252.                 'retrans'     => 5,
  253.                 'retry'       => 4,
  254.                 'usevc'       => 0,
  255.                 'stayopen'    => 0,
  256.                 'igntc'       => 0,
  257.                 'recurse'     => 1,
  258.                 'defnames'    => 1,
  259.                 'dnsrch'      => 1,
  260.                 'debug'       => 0,
  261.                 'errorstring' => 'unknown error or no error',
  262.                 'answerfrom'  => '',
  263.                 'answersize'  => 0,
  264.                 'tcp_timeout' => 120
  265.                 );
  266.         foreach ($mydefaults as $k => $v{
  267.             $this->{$k= isset($defaults[$k]$defaults[$k$v;
  268.         }
  269.         $this->confpath[0= getenv('HOME');
  270.         $this->confpath[1'.';
  271.         $this->res_init();
  272.     }
  273.  
  274.     /* }}} */
  275.     /* Net_DNS_Resolver::res_init() {{{ */
  276.     /**
  277.      * Initalizes the resolver library
  278.      *
  279.      * res_init() searches for resolver library configuration files and
  280.      * initializes the various properties of the resolver object.
  281.      *
  282.      * @see Net_DNS_Resolver::$resolv_conf, Net_DNS_Resolver::$dotfile,
  283.      *       Net_DNS_Resolver::$confpath, Net_DNS_Resolver::$searchlist,
  284.      *       Net_DNS_Resolver::$domain, Net_DNS_Resolver::$nameservers
  285.      * @access public
  286.      */
  287.     function res_init()
  288.     {
  289.         $err error_reporting(0);
  290.         if (file_exists($this->resolv_conf&& is_readable($this->resolv_conf)) {
  291.             $this->read_config($this->resolv_conf);
  292.         }
  293.  
  294.         foreach ($this->confpath as $dir{
  295.             $file $dir.DIRECTORY_SEPARATOR.$this->dotfile;
  296.             if (file_exists($file&& is_readable($file)) {
  297.                 $this->read_config($file);
  298.             }
  299.         }
  300.  
  301.         $this->read_env();
  302.  
  303.         if (!strlen($this->domain&& sizeof($this->searchlist)) {
  304.             $this->domain = $this->searchlist[0];
  305.         else if (sizeof($this->searchlist&& strlen($this->domain)) {
  306.             $this->searchlist = array($this->domain);
  307.         }
  308.         error_reporting($err);
  309.     }
  310.  
  311.     /* }}} */
  312.     /* Net_DNS_Resolver::read_config {{{ */
  313.     /**
  314.      * Reads and parses a resolver configuration file
  315.      *
  316.      * @param string $file The name of the file to open and parse
  317.      */
  318.     function read_config($file)
  319.     {
  320.         if (is_readable($file)) {
  321.             if (($f fopen($file'r'))) {
  322.                 $this->error = "can't open $file";
  323.             }
  324.         }
  325.  
  326.         if (!is_resource($f)) {
  327.             $this->error = "can't open $file";
  328.         else {
  329.             while (feof($f)) {
  330.                 $line chop(fgets($f10240));
  331.                 $line ereg_replace('(.*)[;#].*''\\1'$line);
  332.                 if (ereg("^[ \t]*$"$line$regs)) {
  333.                     continue;
  334.                 }
  335.                 ereg("^[ \t]*([^ \t]+)[ \t]+([^ \t]+)"$line$regs);
  336.                 $option $regs[1];
  337.                 $value $regs[2];
  338.  
  339.                 switch ($option{
  340.                     case 'domain':
  341.                         $this->domain = $regs[2];
  342.                         break;
  343.                     case 'search':
  344.                         $this->searchlist[count($this->searchlist)$regs[2];
  345.                         break;
  346.                     case 'nameserver':
  347.                         foreach (split(' '$regs[2]as $ns{
  348.                             $this->nameservers[count($this->nameservers)$ns;
  349.                         }
  350.                         break;
  351.                 }
  352.             }
  353.             fclose($f);
  354.         }
  355.     }
  356.  
  357.     /* }}} */
  358.     /* Net_DNS_Resolver::read_env() {{{ */
  359.     /**
  360.      * Examines the environment for resolver config information
  361.      */
  362.     function read_env()
  363.     {
  364.         if (getenv('RES_NAMESERVERS')) {
  365.             $this->nameservers = split(' 'getenv('RES_NAMESERVERS'));
  366.         }
  367.  
  368.         if (getenv('RES_SEARCHLIST')) {
  369.             $this->searchlist = split(' 'getenv('RES_SEARCHLIST'));
  370.         }
  371.  
  372.         if (getenv('LOCALDOMAIN')) {
  373.             $this->domain = getenv('LOCALDOMAIN');
  374.         }
  375.  
  376.         if (getenv('RES_OPTIONS')) {
  377.             $env split(' 'getenv('RES_OPTIONS'));
  378.             foreach ($env as $opt{
  379.                 list($name$valsplit(':'$opt);
  380.                 if ($val == ''{
  381.                     $val = 1;
  382.                 }
  383.                 $this->{$name$val;
  384.             }
  385.         }
  386.     }
  387.  
  388.     /* }}} */
  389.     /* Net_DNS_Resolver::string() {{{ */
  390.     /**
  391.      * Builds a string containing the current state of the resolver
  392.      *
  393.      * Builds formatted string containing the state of the resolver library suited
  394.      * for display.
  395.      *
  396.      * @access public
  397.      */
  398.     function string()
  399.     {
  400.         $state  ";; Net_DNS_Resolver state:\n";
  401.         $state .= ';;  domain       = ' $this->domain . "\n";
  402.         $state .= ';;  searchlist   = ' implode(' '$this->searchlist"\n";
  403.         $state .= ';;  nameservers  = ' implode(' '$this->nameservers"\n";
  404.         $state .= ';;  port         = ' $this->port . "\n";
  405.         $state .= ';;  tcp_timeout  = ';
  406.         $state .= ($this->tcp_timeout ? $this->tcp_timeout : 'indefinite'"\n";
  407.         $state .= ';;  retrans  = ' $this->retrans . '  ';
  408.         $state .= 'retry    = ' $this->retry . "\n";
  409.         $state .= ';;  usevc    = ' $this->usevc . '  ';
  410.         $state .= 'stayopen = ' $this->stayopen . '    ';
  411.         $state .= 'igntc = ' $this->igntc . "\n";
  412.         $state .= ';;  defnames = ' $this->defnames . '  ';
  413.         $state .= 'dnsrch   = ' $this->dnsrch . "\n";
  414.         $state .= ';;  recurse  = ' $this->recurse . '  ';
  415.         $state .= 'debug    = ' $this->debug . "\n";
  416.         return $state;
  417.     }
  418.  
  419.     /* }}} */
  420.     /* Net_DNS_Resolver::nextid() {{{ */
  421.     /**
  422.      * Returns the next request Id to be used for the DNS packet header
  423.      */
  424.     function nextid()
  425.     {
  426.         if ($GLOBALS['_Net_DNS_packet_id']++ > 65535{
  427.             $GLOBALS['_Net_DNS_packet_id']= 1;
  428.         }
  429.         return $GLOBALS['_Net_DNS_packet_id'];
  430.     }
  431.     /* }}} */
  432.     /* Net_DNS_Resolver::nameservers() {{{ */
  433.     /**
  434.      * Gets or sets the nameservers to be queried.
  435.      *
  436.      * Returns the current nameservers if an array of new nameservers is not
  437.      * given as the argument OR sets the nameservers to the given nameservers.
  438.      *
  439.      * Nameservers not specified by ip address must be able to be resolved by
  440.      * the default settings of a new Net_DNS_Resolver.
  441.      *
  442.      * @access public
  443.      */
  444.     function nameservers($nsa = array())
  445.     {
  446.         $defres = new Net_DNS_Resolver();
  447.  
  448.         if (is_array($nsa)) {
  449.             $a = array();
  450.             foreach ($nsa as $ns{
  451.                 if (preg_match('/^(\d+(:?\.\d+){0,3})$/'$ns)) {
  452.                     $a[($ns == 0'0.0.0.0' $ns;
  453.                 else {
  454.                     $names = array();
  455.                     if (!preg_match('/\./'$ns)) {
  456.                         if (!empty($defres->searchlist)) {
  457.                             foreach ($defres->searchlist as $suffix{
  458.                                 $names[$ns .'.' $suffix;
  459.                             }
  460.                         elseif (!empty($defres->domain)) {
  461.                             $names[$ns .'.'$defres->domain;
  462.                         }
  463.                     else {
  464.                         $names[$ns;
  465.                     }
  466.                     $packet $defres->search($ns);
  467.                     if (is_object($packet)) {
  468.                         $addresses $this->cname_addr($names$packet);
  469.                         foreach ($addresses as $b{
  470.                             $a[$b;
  471.                         }
  472.                         $a array_unique($a);
  473.                     }
  474.                 }
  475.             }
  476.             if (count($a)) {
  477.                 $this->nameservers = $a;
  478.             }
  479.         }
  480.         return $this->nameservers;
  481.     }
  482.  
  483.     /* }}} */
  484.     /* not tested -- Net_DNS_Resolver::cname_addr() {{{ */
  485.     function cname_addr($names$packet)
  486.     {
  487.         $addr = array();
  488.         //my $oct2 = '(?:2[0-4]\d|25[0-5]|[0-1]?\d\d|\d)';
  489.         foreach ($packet->answer as $rr{
  490.             if (in_array($rr->name$names)) {
  491.                 if ($rr->type == 'CNAME'{
  492.                     $names[$rr->cname;
  493.                 elseif ($rr->type == 'A'{
  494.                     // Run a basic taint check.
  495.                     //next RR unless $rr->address =~ m/^($oct2\.$oct2\.$oct2\.$oct2)$/o;
  496.  
  497.                     $addr[$rr->address;
  498.                 }
  499.             }
  500.         }
  501.         return $addr;
  502.     }
  503.  
  504.     /* }}} */
  505.     /* Net_DNS_Resolver::search() {{{ */
  506.     /**
  507.      * Searches nameservers for an answer
  508.      *
  509.      * Goes through the search list and attempts to resolve name based on
  510.      * the information in the search list.
  511.      *
  512.      * @param string $name The name (LHS) of a resource record to query.
  513.      * @param string $type The type of record to query.
  514.      * @param string $class The class of record to query.
  515.      * @return mixed    an object of type Net_DNS_Packet on success,
  516.      *                   or false on failure.
  517.      * @see Net_DNS::typesbyname(), Net_DNS::classesbyname()
  518.      * @access public
  519.      */
  520.     function search($name$type 'A'$class 'IN')
  521.     {
  522.         /*
  523.          * If the name looks like an IP address then do an appropriate
  524.          * PTR query.
  525.          */
  526.         if (preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/'$name$regs)) {
  527.             $name $regs[4].'.'.$regs[3].'.'.$regs[2].'.'.$regs[1].'.in-addr.arpa.';
  528.             $type 'PTR';
  529.         }
  530.  
  531.         /*
  532.          * If the name contains at least one dot then try it as is first.
  533.          */
  534.         if (strstr($name'.')) {
  535.             if ($this->debug{
  536.                 echo ";; search($name$type$class)\n";
  537.             }
  538.             $ans $this->query($name$type$class);
  539.             if (is_object($ans&& ($ans->header->ancount > 0)) {
  540.                 return $ans;
  541.             }
  542.         }
  543.  
  544.         /*
  545.          * If the name does not end in a dot then apply the search list.
  546.          */
  547.         $domain '';
  548.         if ((preg_match('/\.$/'$name)) && $this->dnsrch{
  549.             foreach ($this->searchlist as $domain{
  550.                 $newname = "$name.$domain";
  551.                 if ($this->debug{
  552.                     echo ";; search($newname$type$class)\n";
  553.                 }
  554.                 $ans $this->query($newname$type$class);
  555.                 if (is_object($ans&& ($ans->header->ancount > 0)) {
  556.                     return $ans;
  557.                 }
  558.             }
  559.         }
  560.  
  561.         /*
  562.          * Finally, if the name has no dots then try it as is.
  563.          */
  564.         if (strpos($name'.'=== false{
  565.             if ($this->debug{
  566.                 echo ";; search($name$type$class)\n";
  567.             }
  568.             $ans $this->query($name.'.'$type$class);
  569.             if (is_object($ans&& ($ans->header->ancount > 0)) {
  570.                 return $ans;
  571.             }
  572.         }
  573.  
  574.         /*
  575.          * No answer was found.
  576.          */
  577.         return false;
  578.     }
  579.  
  580.     /* }}} */
  581.     /* Net_DNS_Resolver::rawQuery() {{{ */
  582.     /**
  583.      * Queries nameservers for an answer
  584.      *
  585.      * Queries the nameservers listed in the resolver configuration for an
  586.      * answer to a question packet.
  587.      *
  588.      * @param string $name The name (LHS) of a resource record to query.
  589.      * @param string $type The type of record to query.
  590.      * @param string $class The class of record to query.
  591.      * @return mixed an object of type Net_DNS_Packet, regardless of whether the packet
  592.      *                has an answer or not
  593.      * @see Net_DNS::typesbyname(), Net_DNS::classesbyname()
  594.      * @access public
  595.      */
  596.     function rawQuery($name$type 'A'$class 'IN')
  597.     {
  598.         /*
  599.          * If the name does not contain any dots then append the default domain.
  600.          */
  601.         if ((strchr($name'.'< 0&& $this->defnames{
  602.             $name .= '.' $this->domain;
  603.         }
  604.  
  605.         /*
  606.          * If the name looks like an IP address then do an appropriate
  607.          * PTR query.
  608.          */
  609.         if (preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/'$name$regs)) {
  610.             $name $regs[4].'.'.$regs[3].'.'.$regs[2].'.'.$regs[1].'.in-addr.arpa.';
  611.             $type 'PTR';
  612.         }
  613.  
  614.         if ($this->debug{
  615.             echo ";; query($name$type$class)\n";
  616.         }
  617.         $packet = new Net_DNS_Packet($this->debug);
  618.         $packet->buildQuestion($name$type$class);
  619.         $packet->header->rd = $this->recurse;
  620.         $ans $this->send($packet);
  621.         return $ans;
  622.     }
  623.  
  624.     /* }}} */
  625.     /* Net_DNS_Resolver::query() {{{ */
  626.     /**
  627.      * Queries nameservers for an answer
  628.      *
  629.      * Queries the nameservers listed in the resolver configuration for an
  630.      * answer to a question packet.
  631.      *
  632.      * @param string $name The name (LHS) of a resource record to query.
  633.      * @param string $type The type of record to query.
  634.      * @param string $class The class of record to query.
  635.      * @return mixed    an object of type Net_DNS_Packet on success,
  636.      *                   or false on failure.
  637.      * @see Net_DNS::typesbyname(), Net_DNS::classesbyname()
  638.      * @access public
  639.      */
  640.     function query($name$type 'A'$class 'IN')
  641.     {
  642.         $ans $this->rawQuery($name$type$class);
  643.         if (is_object($ans&& $ans->header->ancount > 0{
  644.             return $ans;
  645.         }
  646.         return false;
  647.     }
  648.  
  649.     /* }}} */
  650.     /* Net_DNS_Resolver::send($packetORname, $qtype = '', $qclass = '') {{{ */
  651.     /**
  652.      * Sends a packet to a nameserver
  653.      *
  654.      * Determines the appropriate communication method (UDP or TCP) and
  655.      * sends a DNS packet to a nameserver.  Use of the this function
  656.      * directly  is discouraged. $packetORname should always be a properly
  657.      * formatted binary DNS packet.  However, it is possible to send a
  658.      * query here and bypass Net_DNS_Resolver::query()
  659.      *
  660.      * @param string $packetORname      A binary DNS packet stream or a
  661.      *                                   hostname to query
  662.      * @param string $qtype     This should not be used
  663.      * @param string $qclass    This should not be used
  664.      * @return object Net_DNS_Packet    An answer packet object
  665.      */
  666.     function send($packetORname$qtype ''$qclass '')
  667.     {
  668.         $packet $this->make_query_packet($packetORname$qtype$qclass);
  669.         $packet_data $packet->data();
  670.  
  671.         if ($this->usevc != 0 || strlen($packet_data > 512)) {
  672.             $ans $this->send_tcp($packet$packet_data);
  673.         else {
  674.             $ans $this->send_udp($packet$packet_data);
  675.  
  676.             if ($ans && $ans->header->tc && $this->igntc != 0{
  677.                 if ($this->debug{
  678.                     echo ";;\n;; packet truncated: retrying using TCP\n";
  679.                 }
  680.                 $ans $this->send_tcp($packet$packet_data);
  681.             }
  682.         }
  683.         return $ans;
  684.     }
  685.  
  686.     /* }}} */
  687.     /* Net_DNS_Resolver::printhex($packet_data) {{{ */
  688.     /**
  689.      * Prints packet data as hex code.
  690.      */
  691.     function printhex($data)
  692.     {
  693.         $data '  ' $data;
  694.         $start = 0;
  695.         while ($start strlen($data)) {
  696.             printf(';; %03d: '$start);
  697.             for ($ctr $start$ctr $start+16; $ctr++{
  698.                 if ($ctr strlen($data)) {
  699.                     printf('%02x 'ord($data[$ctr]));
  700.                 else {
  701.                     echo '   ';
  702.                 }
  703.             }
  704.             echo '   ';
  705.             for ($ctr $start$ctr $start+16; $ctr++{
  706.                 if (ord($data[$ctr]< 32 || ord($data[$ctr]> 127{
  707.                     echo '.';
  708.                 else {
  709.                     echo $data[$ctr];
  710.                 }
  711.             }
  712.             echo "\n";
  713.             $start += 16;
  714.         }
  715.     }
  716.     /* }}} */
  717.     /* Net_DNS_Resolver::send_tcp($packet, $packet_data) {{{ */
  718.     /**
  719.      * Sends a packet via TCP to the list of name servers.
  720.      *
  721.      * @param string $packet    A packet object to send to the NS list
  722.      * @param string $packet_data   The data in the packet as returned by
  723.      *                               the Net_DNS_Packet::data() method
  724.      * @return object Net_DNS_Packet Returns an answer packet object
  725.      * @see Net_DNS_Resolver::send_udp(), Net_DNS_Resolver::send()
  726.      */
  727.     function send_tcp($packet$packet_data)
  728.     {
  729.         if (count($this->nameservers)) {
  730.             $this->errorstring = 'no nameservers';
  731.             if ($this->debug{
  732.                 echo ";; ERROR: send_tcp: no nameservers\n";
  733.             }
  734.             return null;
  735.         }
  736.         $timeout $this->tcp_timeout;
  737.  
  738.         foreach ($this->nameservers as $ns{
  739.             $dstport $this->port;
  740.             if ($this->debug{
  741.                 echo ";; send_tcp($ns:$dstport)\n";
  742.             }
  743.             $sock_key = "$ns:$dstport";
  744.             if (isset($this->sockets[$sock_key]&& is_resource($this->sockets[$sock_key])) {
  745.                 $sock &$this->sockets[$sock_key];
  746.             else {
  747.                 if (($sock @fsockopen($ns$dstport$errno,
  748.                                 $errstr$timeout))) {
  749.                     $this->errorstring = 'connection failed';
  750.                     if ($this->debug{
  751.                         echo ";; ERROR: send_tcp: connection failed: $errstr\n";
  752.                     }
  753.                     continue;
  754.                 }
  755.                 $this->sockets[$sock_key$sock;
  756.                 unset($sock);
  757.                 $sock &$this->sockets[$sock_key];
  758.             }
  759.             $lenmsg pack('n'strlen($packet_data));
  760.             if ($this->debug{
  761.                 echo ';; sending ' strlen($packet_data" bytes\n";
  762.             }
  763.  
  764.             if (($sent fwrite($sock$lenmsg)) == -1{
  765.                 $this->errorstring = 'length send failed';
  766.                 if ($this->debug{
  767.                     echo ";; ERROR: send_tcp: length send failed\n";
  768.                 }
  769.                 continue;
  770.             }
  771.  
  772.             if (($sent fwrite($sock$packet_data)) == -1{
  773.                 $this->errorstring = 'packet send failed';
  774.                 if ($this->debug{
  775.                     echo ";; ERROR: send_tcp: packet data send failed\n";
  776.                 }
  777.             }
  778.  
  779.             socket_set_timeout($sock$timeout);
  780.             $buf fread($sock2);
  781.             $e socket_get_status($sock);
  782.             /* If $buf is empty, we want to supress errors
  783.                long enough to reach the continue; down the line */
  784.             $len @unpack('nint'$buf);
  785.             $len @$len['int'];
  786.             if (!$len{
  787.                 continue;
  788.             }
  789.             $buf fread($sock$len);
  790.             $actual strlen($buf);
  791.             $this->answerfrom = $ns;
  792.             $this->answersize = $len;
  793.             if ($this->debug{
  794.                 echo ";; received $actual bytes\n";
  795.             }
  796.             if ($actual != $len{
  797.                 $this->errorstring = "expected $len bytes, received $buf";
  798.                 if ($this->debug{
  799.                     echo ';; send_tcp: ' $this->errorstring;
  800.                 }
  801.                 continue;
  802.             }
  803.  
  804.             $ans = new Net_DNS_Packet($this->debug);
  805.             if (is_null($ans->parse($buf))) {
  806.                 continue;
  807.             }
  808.             $this->errorstring = $ans->header->rcode;
  809.             $ans->answerfrom = $this->answerfrom;
  810.             $ans->answersize = $this->answersize;
  811.             return $ans;
  812.         }
  813.     }
  814.  
  815.     /* }}} */
  816.     /* Net_DNS_Resolver::send_udp_no_sock_lib($packet, $packet_data) {{{ */
  817.     /**
  818.      * Sends a packet via UDP to the list of name servers.
  819.      *
  820.      * This function sends a packet to a nameserver.  It is called by
  821.      * send_udp if the sockets PHP extension is not compiled into PHP.
  822.      *
  823.      * @param string $packet    A packet object to send to the NS list
  824.      * @param string $packet_data   The data in the packet as returned by
  825.      *                               the Net_DNS_Packet::data() method
  826.      * @return object Net_DNS_Packet Returns an answer packet object
  827.      * @see Net_DNS_Resolver::send_tcp(), Net_DNS_Resolver::send(),
  828.      *       Net_DNS_Resolver::send_udp(), Net_DNS_Resolver::send_udp_with_sock_lib()
  829.      */
  830.     function send_udp_no_sock_lib($packet$packet_data)
  831.     {
  832.         $retrans $this->retrans;
  833.         $timeout $retrans;
  834.  
  835.         /*
  836.          * PHP doesn't have excellent socket support as of this writing.
  837.          * This needs to be rewritten when PHP POSIX socket support is
  838.          * complete.
  839.          * Obviously, this code is MUCH different than the PERL implementation
  840.          */
  841.  
  842.         $w error_reporting(0);
  843.         $ctr = 0;
  844.         // Create a socket handle for each nameserver
  845.         foreach ($this->nameservers as $nameserver{
  846.             if ($sock[$ctr++fsockopen("udp://$nameserver"$this->port)) {
  847.                 $peerhost[$ctr-1$nameserver;
  848.                 $peerport[$ctr-1$this->port;
  849.                 socket_set_blocking($sock[$ctr-1]false);
  850.             else {
  851.                 $ctr--;
  852.             }
  853.         }
  854.         error_reporting($w);
  855.  
  856.         if ($ctr == 0{
  857.             $this->errorstring = 'no nameservers';
  858.             return null;
  859.         }
  860.  
  861.         for ($i = 0; $i $this->retry$i++$retrans *= 2,
  862.                 $timeout = (int) ($retrans $ctr)) {
  863.             if ($timeout < 1{
  864.                 $timeout = 1;
  865.             }
  866.  
  867.             foreach ($sock as $k => $s{
  868.                 if ($this->debug{
  869.                     echo ';; send_udp(' $peerhost[$k':' $peerport[$k'): sending ' strlen($packet_data" bytes\n";
  870.                 }
  871.  
  872.                 if (fwrite($s$packet_data)) {
  873.                     if ($this->debug{
  874.                         echo ";; send error\n";
  875.                     }
  876.                 }
  877.  
  878.                 /*
  879.                  *  Here's where it get's really nasty.  We don't have a select()
  880.                  *  function here, so we have to poll for a response... UGH!
  881.                  */
  882.  
  883.                 $timetoTO  time(+ (double)microtime($timeout;
  884.  
  885.                 /*
  886.                  * let's sleep for a few hundred microseconds to let the
  887.                  * data come in from the network...
  888.                  */
  889.                 usleep(500);
  890.                 $buf '';
  891.                 while (strlen($buf&& $timetoTO (time(+
  892.                             (double)microtime())) {
  893.                     socket_set_blocking($sfalse);
  894.                     if ($buf fread($s512)) {
  895.                         $this->answerfrom = $peerhost[$k];
  896.                         $this->answersize = strlen($buf);
  897.                         if ($this->debug{
  898.                             echo ';; answer from ' $peerhost[$k':' .
  899.                                 $peerport[$k.  ': ' strlen($buf" bytes\n";
  900.                         }
  901.                         $ans = new Net_DNS_Packet($this->debug);
  902.                         if ($ans->parse($buf)) {
  903.                             if ($ans->header->qr != '1'{
  904.                                 continue;
  905.                             }
  906.                             if ($ans->header->id != $packet->header->id{
  907.                                 continue;
  908.                             }
  909.                             $this->errorstring = $ans->header->rcode;
  910.                             $ans->answerfrom = $this->answerfrom;
  911.                             $ans->answersize = $this->answersize;
  912.                             return $ans;
  913.                         }
  914.                     }
  915.                     // Sleep another 1/100th of a second... this sucks...
  916.                     usleep(1000);
  917.                 }
  918.  
  919.             }
  920.             
  921.             $this->errorstring = 'query timed out';
  922.             return null;
  923.         }
  924.     }
  925.  
  926.     /* }}} */
  927.     /* Net_DNS_Resolver::send_udp_with_sock_lib($packet, $packet_data) {{{ */
  928.     /**
  929.      * Sends a packet via UDP to the list of name servers.
  930.      *
  931.      * This function sends a packet to a nameserver.  It is called by
  932.      * send_udp if the sockets PHP extension is compiled into PHP.
  933.      *
  934.      * @param string $packet    A packet object to send to the NS list
  935.      * @param string $packet_data   The data in the packet as returned by
  936.      *                               the Net_DNS_Packet::data() method
  937.      * @return object Net_DNS_Packet Returns an answer packet object
  938.      * @see Net_DNS_Resolver::send_tcp(), Net_DNS_Resolver::send(),
  939.      *       Net_DNS_Resolver::send_udp(), Net_DNS_Resolver::send_udp_no_sock_lib()
  940.      */
  941.     function send_udp_with_sock_lib($packet$packet_data)
  942.     {
  943.         $retrans $this->retrans;
  944.         $timeout $retrans;
  945.  
  946.         //$w = error_reporting(0);
  947.         $ctr = 0;
  948.         // Create a socket handle for each nameserver
  949.         foreach ($this->nameservers as $nameserver{
  950.             if ((($sock[$ctr++socket_create(AF_INETSOCK_DGRAMSOL_UDP))) &&
  951.                   socket_connect($sock[$ctr-1]$nameserver$this->port))
  952.             {
  953.                 $peerhost[$ctr-1$nameserver;
  954.                 $peerport[$ctr-1$this->port;
  955.                 socket_set_nonblock($sock[$ctr-1]);
  956.             else {
  957.                 $ctr--;
  958.             }
  959.         }
  960.         //error_reporting($w);
  961.  
  962.         if ($ctr == 0{
  963.             $this->errorstring = 'no nameservers';
  964.             return null;
  965.         }
  966.         // Try each nameserver up to $this->retry times
  967.         for ($i = 0; $i $this->retry$i++{
  968.             if ($i != 0{
  969.                 // Set the timeout for each retry based on the number of
  970.                 // nameservers there is a connected socket for.
  971.                 $retrans *= 2;
  972.                 $timeout = (int) ($retrans $ctr);
  973.             }
  974.             // Make sure the timeout is at least 1 second
  975.             if ($timeout < 1{
  976.                 $timeout = 1;
  977.             }
  978.  
  979.             // Try each nameserver
  980.             foreach ($sock as $k => $s{
  981.                 if ($this->debug{
  982.                     echo "\n;; send_udp(" $peerhost[$k':' $peerport[$k'): sending ' strlen($packet_data" bytes\n";
  983.                 }
  984.  
  985.                 if (socket_write($s$packet_data)) {
  986.                     if ($this->debug{
  987.                         echo ";; send error\n";
  988.                     }
  989.                 }
  990.  
  991.                 $set = array($s);
  992.                 if ($this->debug{
  993.                     echo ";; timeout set to $timeout seconds\n";
  994.                 }
  995.                 $changed socket_select($set$w = null$e = null$timeout);
  996.                 if ($changed{
  997.                     // Test to see if the connection was refused.  Linux servers will send
  998.                     // an ICMP message which will cause the client's next system call to
  999.                     // return ECONNREFUSED if the server is not listening on the ip:port queried
  1000.                     if (socket_get_option($sSOL_SOCKETSO_ERROR== SOCKET_ECONNREFUSED{
  1001.                         // Unix socket connection was refused
  1002.                         if ($this->debug{
  1003.                             echo ';; connection to ' $peerhost[$k':' $peerport[$k" was refused\n";
  1004.                         }
  1005.                         // Try the next server.
  1006.                         continue;
  1007.                     }
  1008.  
  1009.                     // Read the response
  1010.                     $buf @socket_read($s512);
  1011.                     if ($buf === false{
  1012.                         // No data could be read from socket
  1013.                         if ($this->debug{
  1014.                             echo ';; no data could be read from ' $peerhost[$k':' $peerport[$k"\n";
  1015.                             echo ';; socket_error: ' socket_strerror(socket_last_error()) "\n";
  1016.                         }
  1017.                         // Reset the non-specific socket error status
  1018.                         socket_clear_error();
  1019.                         // Try the next server.
  1020.                         continue;
  1021.                     }
  1022.  
  1023.                     $this->answerfrom = $peerhost[$k];
  1024.                     $this->answersize = strlen($buf);
  1025.                     if ($this->debug{
  1026.                         echo ';; answer from ' $peerhost[$k':' .
  1027.                             $peerport[$k.  ': ' strlen($buf" bytes\n";
  1028.                     }
  1029.                     $ans = new Net_DNS_Packet($this->debug);
  1030.                     if ($ans->parse($buf)) {
  1031.                         if ($ans->header->qr != '1'{
  1032.                             // Ignore packet if it is not a response
  1033.                             continue;
  1034.                         elseif ($ans->header->id != $packet->header->id{
  1035.                             // Ignore packet if the response id does not match the query id
  1036.                             continue;
  1037.                         else {
  1038.                             // Return the DNS response packet
  1039.                             $this->errorstring = $ans->header->rcode;
  1040.                             $ans->answerfrom = $this->answerfrom;
  1041.                             $ans->answersize = $this->answersize;
  1042.                             return $ans;
  1043.                         }
  1044.                     }
  1045.                 elseif ($this->debug{
  1046.                     echo ";; query to "$peerhost[$k':' $peerport[$k" timed out\n";
  1047.                 }
  1048.             }
  1049.         }
  1050.         $this->errorstring = 'query timed out';
  1051.         return null;
  1052.     }
  1053.  
  1054.     /* }}} */
  1055.     /* Net_DNS_Resolver::send_udp($packet, $packet_data) {{{ */
  1056.     /**
  1057.      * Sends a packet via UDP to the list of name servers.
  1058.      *
  1059.      * This function sends a packet to a nameserver.  send_udp calls
  1060.      * either Net_DNS_Resolver::send_udp_no_sock_lib() or
  1061.      * Net_DNS_Resolver::send_udp_with_sock_lib() depending on whether or
  1062.      * not the sockets extension is compiled into PHP.  Note that using the
  1063.      * sockets extension is MUCH more efficient.
  1064.      *
  1065.      * @param object Net_DNS_Packet $packet A packet object to send to the NS list
  1066.      * @param string $packet_data   The data in the packet as returned by
  1067.      *                               the Net_DNS_Packet::data() method
  1068.      * @return object Net_DNS_Packet Returns an answer packet object
  1069.      * @see Net_DNS_Resolver::send_tcp(), Net_DNS_Resolver::send(),
  1070.      *       Net_DNS_Resolver::send_udp(), Net_DNS_Resolver::send_udp_no_sock_lib()
  1071.      */
  1072.     function send_udp($packet$packet_data)
  1073.     {
  1074.         if (extension_loaded('sockets'&& $this->useEnhancedSockets{
  1075.             if ($this->debug{
  1076.                 echo "\n;; using extended PHP sockets\n";
  1077.             }
  1078.             return $this->send_udp_with_sock_lib($packet$packet_data);
  1079.         else {
  1080.             if ($this->debug{
  1081.                 echo "\n;; using simple sockets\n";
  1082.             }
  1083.             return $this->send_udp_no_sock_lib($packet$packet_data);
  1084.         }
  1085.     }
  1086.  
  1087.     /* }}} */
  1088.     /* Net_DNS_Resolver::make_query_packet($packetORname, $type = '', $class = '') {{{ */
  1089.     /**
  1090.      * Unknown
  1091.      */
  1092.     function make_query_packet($packetORname$type ''$class '')
  1093.     {
  1094.         if (is_object($packetORname&& strcasecmp(get_class($packetORname)'net_dns_packet'== 0{
  1095.             $packet $packetORname;
  1096.         else {
  1097.             $name $packetORname;
  1098.             if ($type == ''{
  1099.                 $type 'A';
  1100.             }
  1101.             if ($class == ''{
  1102.                 $class 'IN';
  1103.             }
  1104.  
  1105.             /*
  1106.              * If the name looks like an IP address then do an appropriate
  1107.              * PTR query.
  1108.              */
  1109.             if (preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/'$name$regs)) {
  1110.                 $name $regs[4].'.'.$regs[3].'.'.$regs[2].'.'.$regs[1].'.in-addr.arpa.';
  1111.                 $type 'PTR';
  1112.             }
  1113.  
  1114.             if ($this->debug{
  1115.                 echo ";; query($name$type$class)\n";
  1116.             }
  1117.             $packet = new Net_DNS_Packet($this->debug);
  1118.             $packet->buildQuestion($name$type$class);
  1119.         }
  1120.  
  1121.         $packet->header->rd = $this->recurse;
  1122.         return $packet;
  1123.     }
  1124.  
  1125.     /* }}} */
  1126.     /* Net_DNS_Resolver::axfr_old($dname, $class = 'IN') {{{ */
  1127.     /**
  1128.      * Performs an AXFR query (zone transfer) (OLD BUGGY STYLE)
  1129.      *
  1130.      * This is deprecated and should not be used!
  1131.      *
  1132.      * @param string $dname The domain (zone) to transfer
  1133.      * @param string $class The class in which to look for the zone.
  1134.      * @return object Net_DNS_Packet 
  1135.      * @access public
  1136.      */
  1137.     function axfr_old($dname$class 'IN')
  1138.     {
  1139.         return $this->axfr($dname$classtrue);
  1140.     }
  1141.     /* }}} */
  1142.     /* Net_DNS_Resolver::axfr($dname, $class = 'IN', $old = false) {{{ */
  1143.     /**
  1144.      * Performs an AXFR query (zone transfer)
  1145.      *
  1146.      * Requests a zone transfer from the nameservers. Note that zone
  1147.      * transfers will ALWAYS use TCP regardless of the setting of the
  1148.      * Net_DNS_Resolver::$usevc flag.  If $old is set to true, Net_DNS requires
  1149.      * a nameserver that supports the many-answers style transfer format.  Large
  1150.      * zone transfers will not function properly.  Setting $old to true is _NOT_
  1151.      * recommended and should only be used for backwards compatibility.
  1152.      *
  1153.      * @param string $dname The domain (zone) to transfer
  1154.      * @param string $class The class in which to look for the zone.
  1155.      * @param boolean $old Requires 'old' style many-answer format to function.
  1156.                            Used for backwards compatibility only.
  1157.      * @return object Net_DNS_Packet 
  1158.      * @access public
  1159.      */
  1160.     function axfr($dname$class 'IN'$old = false)
  1161.     {
  1162.         if ($old{
  1163.             if ($this->debug{
  1164.                 echo ";; axfr_start($dname$class)\n";
  1165.             }
  1166.             if (count($this->nameservers)) {
  1167.                 $this->errorstring = 'no nameservers';
  1168.                 if ($this->debug{
  1169.                     echo ";; ERROR: no nameservers\n";
  1170.                 }
  1171.                 return null;
  1172.             }
  1173.             $packet $this->make_query_packet($dname'AXFR'$class);
  1174.             $packet_data $packet->data();
  1175.             $ans $this->send_tcp($packet$packet_data);
  1176.             return $ans;
  1177.         else {
  1178.             if ($this->axfr_start($dname$class=== null{
  1179.                 return null;
  1180.             }
  1181.             $ret = array();
  1182.             while (($ans $this->axfr_next()) !== null{
  1183.                 if ($ans === null{
  1184.                     return null;
  1185.                 }
  1186.                 array_push($ret$ans);
  1187.             }
  1188.             return $ret;
  1189.         }
  1190.     }
  1191.  
  1192.     /* }}} */
  1193.     /* Net_DNS_Resolver::axfr_start($dname, $class = 'IN') {{{ */
  1194.     /**
  1195.      * Sends a packet via TCP to the list of name servers.
  1196.      *
  1197.      * @param string $packet    A packet object to send to the NS list
  1198.      * @param string $packet_data   The data in the packet as returned by
  1199.      *                               the Net_DNS_Packet::data() method
  1200.      * @return object Net_DNS_Packet Returns an answer packet object
  1201.      * @see Net_DNS_Resolver::send_tcp()
  1202.      */
  1203.     function axfr_start($dname$class 'IN')
  1204.     {
  1205.         if ($this->debug{
  1206.             echo ";; axfr_start($dname$class)\n";
  1207.         }
  1208.  
  1209.         if (count($this->nameservers)) {
  1210.             $this->errorstring = "no nameservers";
  1211.             if ($this->debug{
  1212.                 echo ";; ERROR: axfr_start: no nameservers\n";
  1213.             }
  1214.             return null;
  1215.         }
  1216.         $packet $this->make_query_packet($dname"AXFR"$class);
  1217.         $packet_data $packet->data();
  1218.  
  1219.         $timeout $this->tcp_timeout;
  1220.  
  1221.         foreach ($this->nameservers as $ns{
  1222.             $dstport $this->port;
  1223.             if ($this->debug{
  1224.                 echo ";; axfr_start($ns:$dstport)\n";
  1225.             }
  1226.             $sock_key = "$ns:$dstport";
  1227.             if (is_resource($this->sockets[$sock_key])) {
  1228.                 $sock &$this->sockets[$sock_key];
  1229.             else {
  1230.                 if (($sock fsockopen($ns$dstport$errno,
  1231.                                 $errstr$timeout))) {
  1232.                     $this->errorstring = "connection failed";
  1233.                     if ($this->debug{
  1234.                         echo ";; ERROR: axfr_start: connection failed: $errstr\n";
  1235.                     }
  1236.                     continue;
  1237.                 }
  1238.                 $this->sockets[$sock_key$sock;
  1239.                 unset($sock);
  1240.                 $sock &$this->sockets[$sock_key];
  1241.             }
  1242.             $lenmsg pack("n"strlen($packet_data));
  1243.             if ($this->debug{
  1244.                 echo ";; sending " strlen($packet_data" bytes\n";
  1245.             }
  1246.  
  1247.             if (($sent fwrite($sock$lenmsg)) == -1{
  1248.                 $this->errorstring = "length send failed";
  1249.                 if ($this->debug{
  1250.                     echo ";; ERROR: axfr_start: length send failed\n";
  1251.                 }
  1252.                 continue;
  1253.             }
  1254.  
  1255.             if (($sent fwrite($sock$packet_data)) == -1{
  1256.                 $this->errorstring = "packet send failed";
  1257.                 if ($this->debug{
  1258.                     echo ";; ERROR: axfr_start: packet data send failed\n";
  1259.                 }
  1260.             }
  1261.  
  1262.             socket_set_timeout($sock$timeout);
  1263.  
  1264.             $this->_axfr_sock = $sock;
  1265.             $this->_axfr_rr = array();
  1266.             $this->_axfr_soa_count = 0;
  1267.             return $sock;
  1268.         }
  1269.     }
  1270.  
  1271.     /* }}} */
  1272.     /* Net_DNS_Resolver::axfr_next() {{{ */
  1273.     /**
  1274.      * Requests the next RR from a existing transfer started with axfr_start
  1275.      *
  1276.      * @return object Net_DNS_RR Returns a Net_DNS_RR object of the next RR
  1277.      *                            from a zone transfer.
  1278.      * @see Net_DNS_Resolver::send_tcp()
  1279.      */
  1280.     function axfr_next()
  1281.     {
  1282.         if (count($this->_axfr_rr)) {
  1283.             if (isset($this->_axfr_sock|| is_resource($this->_axfr_sock)) {
  1284.                 $this->errorstring = 'no zone transfer in progress';
  1285.                 return null;
  1286.             }
  1287.             $timeout $this->tcp_timeout;
  1288.             $buf $this->read_tcp($this->_axfr_sock2$this->debug);
  1289.             if (strlen($buf)) {
  1290.                 $this->errorstring = 'truncated zone transfer';
  1291.                 return null;
  1292.             }
  1293.             $len unpack('n1len'$buf);
  1294.             $len $len['len'];
  1295.             if ($len{
  1296.                 $this->errorstring = 'truncated zone transfer';
  1297.                 return null;
  1298.             }
  1299.             $buf $this->read_tcp($this->_axfr_sock$len$this->debug);
  1300.             if ($this->debug{
  1301.                 echo ';; received ' strlen($buf"bytes\n";
  1302.             }
  1303.             if (strlen($buf!= $len{
  1304.                 $this->errorstring = 'expected ' $len ' bytes, received ' strlen($buf);
  1305.                 if ($this->debug{
  1306.                     echo ';; ' $err "\n";
  1307.                 }
  1308.                 return null;
  1309.             }
  1310.             $ans = new Net_DNS_Packet($this->debug);
  1311.             if ($ans->parse($buf)) {
  1312.                 if ($this->errorstring{
  1313.                     $this->errorstring = 'unknown error during packet parsing';
  1314.                 }
  1315.                 return null;
  1316.             }
  1317.             if ($ans->header->ancount < 1{
  1318.                 $this->errorstring = 'truncated zone transfer';
  1319.                 return null;
  1320.             }
  1321.             if ($ans->header->rcode != 'NOERROR'{
  1322.                 $this->errorstring = 'errorcode ' $ans->header->rcode . ' returned';
  1323.                 return null;
  1324.             }
  1325.             foreach ($ans->answer as $rr{
  1326.                 if ($rr->type == 'SOA'{
  1327.                     if (++$this->_axfr_soa_count < 2{
  1328.                         array_push($this->_axfr_rr$rr);
  1329.                     }
  1330.                 else {
  1331.                     array_push($this->_axfr_rr$rr);
  1332.                 }
  1333.             }
  1334.             if ($this->_axfr_soa_count >= 2{
  1335.                 unset($this->_axfr_sock);
  1336.             }
  1337.         }
  1338.         $rr array_shift($this->_axfr_rr);
  1339.         return $rr;
  1340.     }
  1341.  
  1342.     /* }}} */
  1343.     /* Net_DNS_Resolver::read_tcp() {{{ */
  1344.     /**
  1345.      * Unknown - not ported yet
  1346.      */
  1347.     function read_tcp($sock$nbytes$debug = 0)
  1348.     {
  1349.         $buf '';
  1350.         while (strlen($buf$nbytes{
  1351.             $nread $nbytes strlen($buf);
  1352.             $read_buf '';
  1353.             if ($debug{
  1354.                 echo ";; read_tcp: expecting $nread bytes\n";
  1355.             }
  1356.             $read_buf fread($sock$nread);
  1357.             if (strlen($read_buf)) {
  1358.                 if ($debug{
  1359.                     echo ";; ERROR: read_tcp: fread failed\n";
  1360.                 }
  1361.                 break;
  1362.             }
  1363.             if ($debug{
  1364.                 echo ';; read_tcp: received ' strlen($read_buf" bytes\n";
  1365.             }
  1366.             if (!strlen($read_buf)) {
  1367.                 break;
  1368.             }
  1369.  
  1370.             $buf .= $read_buf;
  1371.         }
  1372.         return $buf;
  1373.     }
  1374.     /* }}} */
  1375. }
  1376. /* }}} */
  1377. /* VIM settings {{{
  1378.  * Local variables:
  1379.  * tab-width: 4
  1380.  * c-basic-offset: 4
  1381.  * soft-stop-width: 4
  1382.  * c indent on
  1383.  * expandtab on
  1384.  * End:
  1385.  * vim600: sw=4 ts=4 sts=4 cindent fdm=marker et
  1386.  * vim<600: sw=4 ts=4
  1387.  * }}} */
  1388. ?>

Documentation generated on Mon, 11 Mar 2019 14:47:59 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.