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

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