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 lsit
  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  an
  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/" . $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.                     break;
  359.             }
  360.         }
  361.         fclose($f);
  362.     }
  363.  
  364.     /* }}} */
  365.     /* Net_DNS_Resolver::read_env() {{{ */
  366.     /**
  367.      * Examines the environment for resolver config information
  368.      */
  369.     function read_env()
  370.     {
  371.         if (getenv('RES_NAMESERVERS')) {
  372.             $this->nameservers = split(' 'getenv('RES_NAMESERVERS'));
  373.         }
  374.  
  375.         if (getenv('RES_SEARCHLIST')) {
  376.             $this->searchlist = split(' 'getenv('RES_SEARCHLIST'));
  377.         }
  378.  
  379.         if (getenv('LOCALDOMAIN')) {
  380.             $this->domain = getenv('LOCALDOMAIN');
  381.         }
  382.  
  383.         if (getenv('RES_OPTIONS')) {
  384.             $env split(' 'getenv('RES_OPTIONS'));
  385.             foreach ($env as $opt{
  386.                 list($name$valsplit(':'$opt);
  387.                 if ($val == ''{
  388.                     $val = 1;
  389.                 }
  390.                 $this->{$name$val;
  391.             }
  392.         }
  393.     }
  394.  
  395.     /* }}} */
  396.     /* Net_DNS_Resolver::string() {{{ */
  397.     /**
  398.      * Builds a string containing the current state of the resolver
  399.      *
  400.      * Builds formatted string containing the state of the resolver library suited
  401.      * for display.
  402.      *
  403.      * @access public
  404.      */
  405.     function string()
  406.     {
  407.         $state  ";; Net_DNS_Resolver state:\n";
  408.         $state .= ';;  domain       = ' $this->domain . "\n";
  409.         $state .= ';;  searchlist   = ' implode(' '$this->searchlist"\n";
  410.         $state .= ';;  nameservers  = ' implode(' '$this->nameservers"\n";
  411.         $state .= ';;  port         = ' $this->port . "\n";
  412.         $state .= ';;  tcp_timeout  = ';
  413.         $state .= ($this->tcp_timeout ? $this->tcp_timeout : 'indefinite'"\n";
  414.         $state .= ';;  retrans  = ' $this->retrans . '  ';
  415.         $state .= 'retry    = ' $this->retry . "\n";
  416.         $state .= ';;  usevc    = ' $this->usevc . '  ';
  417.         $state .= 'stayopen = ' $this->stayopen . '    ';
  418.         $state .= 'igntc = ' $this->igntc . "\n";
  419.         $state .= ';;  defnames = ' $this->defnames . '  ';
  420.         $state .= 'dnsrch   = ' $this->dnsrch . "\n";
  421.         $state .= ';;  recurse  = ' $this->recurse . '  ';
  422.         $state .= 'debug    = ' $this->debug . "\n";
  423.         return($state);
  424.     }
  425.  
  426.     /* }}} */
  427.     /* Net_DNS_Resolver::nextid() {{{ */
  428.     /**
  429.      * Returns the next request Id to be used for the DNS packet header
  430.      */
  431.     function nextid()
  432.     {
  433.         if ($GLOBALS['_Net_DNS_packet_id']++ > 65535{
  434.             $GLOBALS['_Net_DNS_packet_id']= 1;
  435.         }
  436.         return $GLOBALS['_Net_DNS_packet_id'];
  437.     }
  438.     /* }}} */
  439.     /* Net_DNS_Resolver::nameservers() {{{ */
  440.     /**
  441.      * Gets or sets the nameservers to be queried.
  442.      *
  443.      * Returns the current nameservers if an array of new nameservers is not
  444.      * given as the argument OR sets the nameservers to the given nameservers.
  445.      *
  446.      * Nameservers not specified by ip address must be able to be resolved by
  447.      * your systems default resolver to be used.
  448.      *
  449.      * @access public
  450.      */
  451.     function nameservers($nsa = array())
  452.     {
  453.         $defres = new Net_DNS_Resolver();
  454.  
  455.         if (is_array($nsa)) {
  456.             $a = array();
  457.             foreach ($nsa as $ns{
  458.                 if (preg_match('/^(\d+(:?\.\d+){0,3})$/'$ns)) {
  459.                     $a[($ns == 0'0.0.0.0' $ns;
  460.                 else {
  461.                     $names = array();
  462.                     if (!preg_match('/\./'$ns)) {
  463.                         if (!empty($defres->searchlist)) {
  464.                             foreach ($defres->searchlist as $suffix{
  465.                                 $names[$ns .'.' $suffix;
  466.                             }
  467.                         elseif (!empty($defres->domain)) {
  468.                             $names[$ns .'.'$defres->domain;
  469.                         }
  470.                     else {
  471.                         $names[$ns;
  472.                     }
  473.                     $packet $defres->search($ns);
  474.                     if (is_object($packet)) {
  475.                         $addresses $this->cname_addr($names$packet);
  476.                         foreach ($addresses as $b{
  477.                             $a[$b;
  478.                         }
  479.                         $a array_unique($a);
  480.                     }
  481.                 }
  482.             }
  483.             if (count($a)) {
  484.                 $this->nameservers = $a;
  485.             }
  486.         }
  487.         return $this->nameservers;
  488.     }
  489.  
  490.     /* }}} */
  491.     /* not tested -- Net_DNS_Resolver::cname_addr() {{{ */
  492.     function cname_addr($names$packet)
  493.     {
  494.         $addr = array();
  495.         //my $oct2 = '(?:2[0-4]\d|25[0-5]|[0-1]?\d\d|\d)';
  496.         foreach ($packet->answer as $rr{
  497.             if (in_array($rr->name$names)) {
  498.                 if ($rr->type == 'CNAME'{
  499.                     $names[$rr->cname;
  500.                 elseif ($rr->type == 'A'{
  501.                     // Run a basic taint check.
  502.                     //next RR unless $rr->address =~ m/^($oct2\.$oct2\.$oct2\.$oct2)$/o;
  503.  
  504.                     $addr[$rr->address;
  505.                 }
  506.             }
  507.         }
  508.         return $addr;
  509.     }
  510.  
  511.     /* }}} */
  512.     /* Net_DNS_Resolver::search() {{{ */
  513.     /**
  514.      * Searches nameservers for an answer
  515.      *
  516.      * Goes through the search list and attempts to resolve name based on
  517.      * the information in the search list.
  518.      *
  519.      * @param string $name The name (LHS) of a resource record to query.
  520.      * @param string $type The type of record to query.
  521.      * @param string $class The class of record to query.
  522.      * @return mixed    an object of type Net_DNS_Packet on success,
  523.      *                   or FALSE on failure.
  524.      * @see Net_DNS::typesbyname(), Net_DNS::classesbyname()
  525.      * @access public
  526.      */
  527.     function search($name$type 'A'$class 'IN')
  528.     {
  529.         /*
  530.          * If the name looks like an IP address then do an appropriate
  531.          * PTR query.
  532.          */
  533.         if (preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/'$name$regs)) {
  534.             $name $regs[4].'.'.$regs[3].'.'.$regs[2].'.'.$regs[1].'.in-addr.arpa.';
  535.             $type 'PTR';
  536.         }
  537.  
  538.         /*
  539.          * If the name contains at least one dot then try it as is first.
  540.          */
  541.         if (strstr($name'.')) {
  542.             if ($this->debug{
  543.                 echo ";; search($name$type$class)\n";
  544.             }
  545.             $ans $this->query($name$type$class);
  546.             if ((is_object($ans)) && $ans->header->ancount > 0{
  547.                 return $ans;
  548.             }
  549.         }
  550.  
  551.         /*
  552.          * If the name doesn't end in a dot then apply the search list.
  553.          */
  554.         $domain '';
  555.         if ((preg_match('/\.$/'$name)) && $this->dnsrch{
  556.             foreach ($this->searchlist as $domain{
  557.                 $newname = "$name.$domain";
  558.                 if ($this->debug{
  559.                     echo ";; search($newname$type$class)\n";
  560.                 }
  561.                 $ans $this->query($newname$type$class);
  562.                 if ((is_object($ans)) && $ans->header->ancount > 0{
  563.                     return $ans;
  564.                 }
  565.             }
  566.         }
  567.  
  568.         /*
  569.          * Finally, if the name has no dots then try it as is.
  570.          */
  571.         if (strlen(strstr($name'.'))) {
  572.             if ($this->debug{
  573.                 echo ";; search($name$type$class)\n";
  574.             }
  575.             $ans $this->query("$name."$type$class);
  576.             if (($ans $this->query($name$type$class)) &&
  577.                     $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, regarless 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 doesn't 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.      * send 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.      * Sends a packet via TCP to the list of name servers.
  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.             echo '   ';
  712.             for ($ctr $start$ctr $start+16; $ctr++{
  713.                 if (ord($data[$ctr]< 32 || ord($data[$ctr]> 127{
  714.                     echo '.';
  715.                 else {
  716.                     echo $data[$ctr];
  717.                 }
  718.             }
  719.             echo "\n";
  720.             $start += 16;
  721.         }
  722.     }
  723.     /* }}} */
  724.     /* Net_DNS_Resolver::send_tcp($packet, $packet_data) {{{ */
  725.     /**
  726.      * Sends a packet via TCP to the list of name servers.
  727.      *
  728.      * @param string $packet    A packet object to send to the NS list
  729.      * @param string $packet_data   The data in the packet as returned by
  730.      *                               the Net_DNS_Packet::data() method
  731.      * @return object Net_DNS_Packet Returns an answer packet object
  732.      * @see Net_DNS_Resolver::send_udp(), Net_DNS_Resolver::send()
  733.      */
  734.     function send_tcp($packet$packet_data)
  735.     {
  736.         if (count($this->nameservers)) {
  737.             $this->errorstring = 'no nameservers';
  738.             if ($this->debug{
  739.                 echo ";; ERROR: send_tcp: no nameservers\n";
  740.             }
  741.             return(NULL);
  742.         }
  743.         $timeout $this->tcp_timeout;
  744.  
  745.         foreach ($this->nameservers as $ns{
  746.             $dstport $this->port;
  747.             if ($this->debug{
  748.                 echo ";; send_tcp($ns:$dstport)\n";
  749.             }
  750.             $sock_key = "$ns:$dstport";
  751.             if (isset($this->sockets[$sock_key]&& is_resource($this->sockets[$sock_key])) {
  752.                 $sock &$this->sockets[$sock_key];
  753.             else {
  754.                 if (($sock @fsockopen($ns$dstport$errno,
  755.                                 $errstr$timeout))) {
  756.                     $this->errorstring = 'connection failed';
  757.                     if ($this->debug{
  758.                         echo ";; ERROR: send_tcp: connection failed: $errstr\n";
  759.                     }
  760.                     continue;
  761.                 }
  762.                 $this->sockets[$sock_key$sock;
  763.                 unset($sock);
  764.                 $sock &$this->sockets[$sock_key];
  765.             }
  766.             $lenmsg pack('n'strlen($packet_data));
  767.             if ($this->debug{
  768.                 echo ';; sending ' strlen($packet_data" bytes\n";
  769.             }
  770.  
  771.             if (($sent fwrite($sock$lenmsg)) == -1{
  772.                 $this->errorstring = 'length send failed';
  773.                 if ($this->debug{
  774.                     echo ";; ERROR: send_tcp: length send failed\n";
  775.                 }
  776.                 continue;
  777.             }
  778.  
  779.             if (($sent fwrite($sock$packet_data)) == -1{
  780.                 $this->errorstring = 'packet send failed';
  781.                 if ($this->debug{
  782.                     echo ";; ERROR: send_tcp: packet data send failed\n";
  783.                 }
  784.             }
  785.  
  786.             socket_set_timeout($sock$timeout);
  787.             $buf fread($sock2);
  788.             $e socket_get_status($sock);
  789.             /* If $buf is empty, we want to supress errors
  790.                long enough to reach the continue; down the line */
  791.             $len @unpack('nint'$buf);
  792.             $len @$len['int'];
  793.             if (!$len{
  794.                 continue;
  795.             }
  796.             $buf fread($sock$len);
  797.             $actual strlen($buf);
  798.             $this->answerfrom = $ns;
  799.             $this->answersize = $len;
  800.             if ($this->debug{
  801.                 echo ";; received $actual bytes\n";
  802.             }
  803.             if ($actual != $len{
  804.                 $this->errorstring = "expected $len bytes, received $buf";
  805.                 if ($this->debug{
  806.                     echo ';; send_tcp: ' $this->errorstring;
  807.                 }
  808.                 continue;
  809.             }
  810.  
  811.             $ans = new Net_DNS_Packet($this->debug);
  812.             if (is_null($ans->parse($buf))) {
  813.                 continue;
  814.             }
  815.             $this->errorstring = $ans->header->rcode;
  816.             $ans->answerfrom = $this->answerfrom;
  817.             $ans->answersize = $this->answersize;
  818.             return($ans);
  819.         }
  820.     }
  821.  
  822.     /* }}} */
  823.     /* Net_DNS_Resolver::send_udp_no_sock_lib($packet, $packet_data) {{{ */
  824.     /**
  825.      * Sends a packet via UDP to the list of name servers.
  826.      *
  827.      * This function sends a packet to a nameserver.  It is called by
  828.      * send_udp if the sockets PHP extension is not compiled into PHP.
  829.      *
  830.      * @param string $packet    A packet object to send to the NS list
  831.      * @param string $packet_data   The data in the packet as returned by
  832.      *                               the Net_DNS_Packet::data() method
  833.      * @return object Net_DNS_Packet Returns an answer packet object
  834.      * @see Net_DNS_Resolver::send_tcp(), Net_DNS_Resolver::send(),
  835.      *       Net_DNS_Resolver::send_udp(), Net_DNS_Resolver::send_udp_with_sock_lib()
  836.      */
  837.     function send_udp_no_sock_lib($packet$packet_data)
  838.     {
  839.         $retrans $this->retrans;
  840.         $timeout $retrans;
  841.  
  842.         /*
  843.          * PHP doesn't have excellent socket support as of this writing.
  844.          * This needs to be rewritten when PHP POSIX socket support is
  845.          * complete.
  846.          * Obviously, this code is MUCH different than the PERL implementation
  847.          */
  848.  
  849.         $w error_reporting(0);
  850.         $ctr = 0;
  851.         // Create a socket handle for each nameserver
  852.         foreach ($this->nameservers as $nameserver{
  853.             if ($sock[$ctr++fsockopen("udp://$nameserver"$this->port)) {
  854.                 $peerhost[$ctr-1$nameserver;
  855.                 $peerport[$ctr-1$this->port;
  856.                 socket_set_blocking($sockFALSE);
  857.             else {
  858.                 $ctr--;
  859.             }
  860.         }
  861.         error_reporting($w);
  862.  
  863.         if ($ctr == 0{
  864.             $this->errorstring = 'no nameservers';
  865.             return(NULL);
  866.         }
  867.  
  868.         for ($i = 0; $i $this->retry$i++$retrans *= 2,
  869.                 $timeout = (int) ($retrans (count($ns)+1))) {
  870.             if ($timeout < 1{
  871.                 $timeout = 1;
  872.             }
  873.  
  874.             foreach ($sock as $k => $s{
  875.                 if ($this->debug{
  876.                     echo ';; send_udp(' $peerhost[$k':' $peerport[$k'): sending ' strlen($packet_data" bytes\n";
  877.                 }
  878.  
  879.                 if (fwrite($s$packet_data)) {
  880.                     if ($this->debug{
  881.                         echo ";; send error\n";
  882.                     }
  883.                 }
  884.  
  885.                 /*
  886.                  *  Here's where it get's really nasty.  We don't have a select()
  887.                  *  function here, so we have to poll for a response... UGH!
  888.                  */
  889.  
  890.                 $timetoTO  time(+ (double)microtime($timeout;
  891.  
  892.                 /*
  893.                  * let's sleep for a few hundred microseconds to let the
  894.                  * data come in from the network...
  895.                  */
  896.                 usleep(500);
  897.                 $buf '';
  898.                 while (strlen($buf&& $timetoTO (time(+
  899.                             (double)microtime())) {
  900.                     socket_set_blocking($sFALSE);
  901.                     if ($buf fread($s512)) {
  902.                         $this->answerfrom = $peerhost[$k];
  903.                         $this->answersize = strlen($buf);
  904.                         if ($this->debug{
  905.                             echo ';; answer from ' $peerhost[$k':' .
  906.                                 $peerport[$k.  ': ' strlen($buf" bytes\n";
  907.                         }
  908.                         $ans = new Net_DNS_Packet($this->debug);
  909.                         if ($ans->parse($buf)) {
  910.                             if ($ans->header->qr != '1'{
  911.                                 continue;
  912.                             }
  913.                             if ($ans->header->id != $packet->header->id{
  914.                                 continue;
  915.                             }
  916.                             $this->errorstring = $ans->header->rcode;
  917.                             $ans->answerfrom = $this->answerfrom;
  918.                             $ans->answersize = $this->answersize;
  919.                             return($ans);
  920.                         }
  921.                     }
  922.                     // Sleep another 1/100th of a second... this sucks...
  923.                     usleep(1000);
  924.                 }
  925.  
  926.                 $this->errorstring = 'query timed out';
  927.                 return(NULL);
  928.             }
  929.         }
  930.     }
  931.  
  932.     /* }}} */
  933.     /* Net_DNS_Resolver::send_udp_with_sock_lib($packet, $packet_data) {{{ */
  934.     /**
  935.      * Sends a packet via UDP to the list of name servers.
  936.      *
  937.      * This function sends a packet to a nameserver.  It is called by
  938.      * send_udp if the sockets PHP extension is compiled into PHP.
  939.      *
  940.      * @param string $packet    A packet object to send to the NS list
  941.      * @param string $packet_data   The data in the packet as returned by
  942.      *                               the Net_DNS_Packet::data() method
  943.      * @return object Net_DNS_Packet Returns an answer packet object
  944.      * @see Net_DNS_Resolver::send_tcp(), Net_DNS_Resolver::send(),
  945.      *       Net_DNS_Resolver::send_udp(), Net_DNS_Resolver::send_udp_no_sock_lib()
  946.      */
  947.     function send_udp_with_sock_lib($packet$packet_data)
  948.     {
  949.         $retrans $this->retrans;
  950.         $timeout $retrans;
  951.  
  952.         //$w = error_reporting(0);
  953.         $ctr = 0;
  954.         // Create a socket handle for each nameserver
  955.         foreach ($this->nameservers as $nameserver{
  956.             if ((($sock[$ctr++socket_create(AF_INETSOCK_DGRAMSOL_UDP))) &&
  957.                   socket_connect($sock[$ctr-1]$nameserver$this->port))
  958.             {
  959.                 $peerhost[$ctr-1$nameserver;
  960.                 $peerport[$ctr-1$this->port;
  961.                 socket_set_nonblock($sock[$ctr-1]);
  962.             else {
  963.                 $ctr--;
  964.             }
  965.         }
  966.         //error_reporting($w);
  967.  
  968.         if ($ctr == 0{
  969.             $this->errorstring = 'no nameservers';
  970.             return(NULL);
  971.         }
  972.  
  973.         for ($i = 0; $i $this->retry$i++$retrans *= 2,
  974.                 $timeout = (int) ($retrans (count($ns)+1))) {
  975.             if ($timeout < 1{
  976.                 $timeout = 1;
  977.             }
  978.  
  979.             foreach ($sock as $k => $s{
  980.                 if ($this->debug{
  981.                     echo ';; send_udp(' $peerhost[$k':' $peerport[$k'): sending ' strlen($packet_data" bytes\n";
  982.                 }
  983.  
  984.                 if (socket_write($s$packet_data)) {
  985.                     if ($this->debug{
  986.                         echo ";; send error\n";
  987.                     }
  988.                 }
  989.  
  990.                 $set = array($s);
  991.                 if ($this->debug{
  992.                     echo ";; timeout set to $timeout seconds\n";
  993.                 }
  994.                 $changed socket_select($set$w = null$e = null$timeout);
  995.                 if ($changed{
  996.                     $buf socket_read($set[0]512);
  997.                     $this->answerfrom = $peerhost[$k];
  998.                     $this->answersize = strlen($buf);
  999.                     if ($this->debug{
  1000.                         echo ';; answer from ' $peerhost[$k':' .
  1001.                             $peerport[$k.  ': ' strlen($buf" bytes\n";
  1002.                     }
  1003.                     $ans = new Net_DNS_Packet($this->debug);
  1004.                     if ($ans->parse($buf)) {
  1005.                         if ($ans->header->qr != '1'{
  1006.                             continue;
  1007.                         }
  1008.                         if ($ans->header->id != $packet->header->id{
  1009.                             continue;
  1010.                         }
  1011.                         $this->errorstring = $ans->header->rcode;
  1012.                         $ans->answerfrom = $this->answerfrom;
  1013.                         $ans->answersize = $this->answersize;
  1014.                         return($ans);
  1015.                     }
  1016.                 }
  1017.  
  1018.                 $this->errorstring = 'query timed out';
  1019.                 return(NULL);
  1020.             }
  1021.         }
  1022.     }
  1023.  
  1024.     /* }}} */
  1025.     /* Net_DNS_Resolver::send_udp($packet, $packet_data) {{{ */
  1026.     /**
  1027.      * Sends a packet via UDP to the list of name servers.
  1028.      *
  1029.      * This function sends a packet to a nameserver.  send_udp calls
  1030.      * either Net_DNS_Resolver::send_udp_no_sock_lib() or
  1031.      * Net_DNS_Resolver::send_udp_with_sock_lib() depending on whether or
  1032.      * not the sockets extension is compiled into PHP.  Note that using the
  1033.      * sockets extension is MUCH more effecient.
  1034.      *
  1035.      * @param object Net_DNS_Packet $packet A packet object to send to the NS list
  1036.      * @param string $packet_data   The data in the packet as returned by
  1037.      *                               the Net_DNS_Packet::data() method
  1038.      * @return object Net_DNS_Packet Returns an answer packet object
  1039.      * @see Net_DNS_Resolver::send_tcp(), Net_DNS_Resolver::send(),
  1040.      *       Net_DNS_Resolver::send_udp(), Net_DNS_Resolver::send_udp_no_sock_lib()
  1041.      */
  1042.     function send_udp($packet$packet_data)
  1043.     {
  1044.         if (extension_loaded('sockets'&& $this->useEnhancedSockets{
  1045.             if ($this->debug{
  1046.                 echo "\n;; using extended PHP sockets\n";
  1047.             }
  1048.             return($this->send_udp_with_sock_lib($packet$packet_data));
  1049.         else {
  1050.             if ($this->debug{
  1051.                 echo "\n;; using simple sockets\n";
  1052.             }
  1053.             return($this->send_udp_no_sock_lib($packet$packet_data));
  1054.         }
  1055.     }
  1056.  
  1057.     /* }}} */
  1058.     /* Net_DNS_Resolver::make_query_packet($packetORname, $type = '', $class = '') {{{ */
  1059.     /**
  1060.      * Unknown
  1061.      */
  1062.     function make_query_packet($packetORname$type ''$class '')
  1063.     {
  1064.         if (is_object($packetORname&& strcasecmp(get_class($packetORname)'net_dns_packet'== 0{
  1065.             $packet $packetORname;
  1066.         else {
  1067.             $name $packetORname;
  1068.             if ($type == ''{
  1069.                 $type 'A';
  1070.             }
  1071.             if ($class == ''{
  1072.                 $class 'IN';
  1073.             }
  1074.  
  1075.             /*
  1076.              * If the name looks like an IP address then do an appropriate
  1077.              * PTR query.
  1078.              */
  1079.             if (preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/'$name$regs)) {
  1080.                 $name = "$regs[4].$regs[3].$regs[2].$regs[1].in-addr.arpa";
  1081.                 $type 'PTR';
  1082.             }
  1083.  
  1084.             if ($this->debug{
  1085.                 echo ";; query($name$type$class)\n";
  1086.             }
  1087.             $packet = new Net_DNS_Packet($this->debug);
  1088.             $packet->buildQuestion($name$type$class);
  1089.         }
  1090.  
  1091.         $packet->header->rd = $this->recurse;
  1092.  
  1093.         return($packet);
  1094.     }
  1095.  
  1096.     /* }}} */
  1097.     /* Net_DNS_Resolver::axfr_old($dname, $class = 'IN') {{{ */
  1098.     /**
  1099.      * Performs an AXFR query (zone transfer) (OLD BUGGY STYLE)
  1100.      *
  1101.      * This is deprecated and should not be used!
  1102.      *
  1103.      * @param string $dname The domain (zone) to transfer
  1104.      * @param string $class The class in which to look for the zone.
  1105.      * @return object Net_DNS_Packet 
  1106.      * @access public
  1107.      */
  1108.     function axfr_old($dname$class 'IN')
  1109.     {
  1110.         return($this->axfr($dname$classTRUE));
  1111.     }
  1112.     /* }}} */
  1113.     /* Net_DNS_Resolver::axfr($dname, $class = 'IN', $old = FALSE) {{{ */
  1114.     /**
  1115.      * Performs an AXFR query (zone transfer)
  1116.      *
  1117.      * Requests a zone transfer from the nameservers. Note that zone
  1118.      * transfers will ALWAYS use TCP regardless of the setting of the
  1119.      * Net_DNS_Resolver::$usevc flag.  If $old is set to TRUE, Net_DNS requires
  1120.      * a nameserver that supports the many-answers style transfer format.  Large
  1121.      * zone transfers will not function properly.  Setting $old to TRUE is _NOT_
  1122.      * recommended and should only be used for backwards compatibility.
  1123.      *
  1124.      * @param string $dname The domain (zone) to transfer
  1125.      * @param string $class The class in which to look for the zone.
  1126.      * @param boolean $old Requires 'old' style many-answer format to function.  Used for backwards compatibility only.
  1127.      * @return object Net_DNS_Packet 
  1128.      * @access public
  1129.      */
  1130.     function axfr($dname$class 'IN'$old = FALSE)
  1131.     {
  1132.         if ($old{
  1133.             if ($this->debug{
  1134.                 echo ";; axfr_start($dname$class)\n";
  1135.             }
  1136.             if (count($this->nameservers)) {
  1137.                 $this->errorstring = 'no nameservers';
  1138.                 if ($this->debug{
  1139.                     echo ";; ERROR: no nameservers\n";
  1140.                 }
  1141.                 return(NULL);
  1142.             }
  1143.             $packet $this->make_query_packet($dname'AXFR'$class);
  1144.             $packet_data $packet->data();
  1145.             $ans $this->send_tcp($packet$packet_data);
  1146.             return($ans);
  1147.         else {
  1148.             if ($this->axfr_start($dname$class=== NULL{
  1149.                 return(NULL);
  1150.             }
  1151.             $ret = array();
  1152.             while (($ans $this->axfr_next()) !== NULL{
  1153.                 if ($ans === NULL{
  1154.                     return(NULL);
  1155.                 }
  1156.                 array_push($ret$ans);
  1157.             }
  1158.             return($ret);
  1159.         }
  1160.     }
  1161.  
  1162.     /* }}} */
  1163.     /* Net_DNS_Resolver::axfr_start($dname, $class = 'IN') {{{ */
  1164.     /**
  1165.      * Sends a packet via TCP to the list of name servers.
  1166.      *
  1167.      * @param string $packet    A packet object to send to the NS list
  1168.      * @param string $packet_data   The data in the packet as returned by
  1169.      *                               the Net_DNS_Packet::data() method
  1170.      * @return object Net_DNS_Packet Returns an answer packet object
  1171.      * @see Net_DNS_Resolver::send_tcp()
  1172.      */
  1173.     function axfr_start($dname$class 'IN')
  1174.     {
  1175.         if ($this->debug{
  1176.             echo ";; axfr_start($dname$class)\n";
  1177.         }
  1178.  
  1179.         if (count($this->nameservers)) {
  1180.             $this->errorstring = "no nameservers";
  1181.             if ($this->debug{
  1182.                 echo ";; ERROR: axfr_start: no nameservers\n";
  1183.             }
  1184.             return(NULL);
  1185.         }
  1186.         $packet $this->make_query_packet($dname"AXFR"$class);
  1187.         $packet_data $packet->data();
  1188.  
  1189.         $timeout $this->tcp_timeout;
  1190.  
  1191.         foreach ($this->nameservers as $ns{
  1192.             $dstport $this->port;
  1193.             if ($this->debug{
  1194.                 echo ";; axfr_start($ns:$dstport)\n";
  1195.             }
  1196.             $sock_key = "$ns:$dstport";
  1197.             if (is_resource($this->sockets[$sock_key])) {
  1198.                 $sock &$this->sockets[$sock_key];
  1199.             else {
  1200.                 if (($sock fsockopen($ns$dstport$errno,
  1201.                                 $errstr$timeout))) {
  1202.                     $this->errorstring = "connection failed";
  1203.                     if ($this->debug{
  1204.                         echo ";; ERROR: axfr_start: connection failed: $errstr\n";
  1205.                     }
  1206.                     continue;
  1207.                 }
  1208.                 $this->sockets[$sock_key$sock;
  1209.                 unset($sock);
  1210.                 $sock &$this->sockets[$sock_key];
  1211.             }
  1212.             $lenmsg pack("n"strlen($packet_data));
  1213.             if ($this->debug{
  1214.                 echo ";; sending " strlen($packet_data" bytes\n";
  1215.             }
  1216.  
  1217.             if (($sent fwrite($sock$lenmsg)) == -1{
  1218.                 $this->errorstring = "length send failed";
  1219.                 if ($this->debug{
  1220.                     echo ";; ERROR: axfr_start: length send failed\n";
  1221.                 }
  1222.                 continue;
  1223.             }
  1224.  
  1225.             if (($sent fwrite($sock$packet_data)) == -1{
  1226.                 $this->errorstring = "packet send failed";
  1227.                 if ($this->debug{
  1228.                     echo ";; ERROR: axfr_start: packet data send failed\n";
  1229.                 }
  1230.             }
  1231.  
  1232.             socket_set_timeout($sock$timeout);
  1233.  
  1234.             $this->_axfr_sock = $sock;
  1235.             $this->_axfr_rr = array();
  1236.             $this->_axfr_soa_count = 0;
  1237.             return($sock);
  1238.         }
  1239.     }
  1240.  
  1241.     /* }}} */
  1242.     /* Net_DNS_Resolver::axfr_next() {{{ */
  1243.     /**
  1244.      * Requests the next RR from a existing transfer started with axfr_start
  1245.      *
  1246.      * @return object Net_DNS_RR Returns a Net_DNS_RR object of the next RR
  1247.      *                            from a zone transfer.
  1248.      * @see Net_DNS_Resolver::send_tcp()
  1249.      */
  1250.     function axfr_next()
  1251.     {
  1252.         if (count($this->_axfr_rr)) {
  1253.             if (isset($this->_axfr_sock|| is_resource($this->_axfr_sock)) {
  1254.                 $this->errorstring = 'no zone transfer in progress';
  1255.                 return(NULL);
  1256.             }
  1257.             $timeout $this->tcp_timeout;
  1258.             $buf $this->read_tcp($this->_axfr_sock2$this->debug);
  1259.             if (strlen($buf)) {
  1260.                 $this->errorstring = 'truncated zone transfer';
  1261.                 return(NULL);
  1262.             }
  1263.             $len unpack('n1len'$buf);
  1264.             $len $len['len'];
  1265.             if ($len{
  1266.                 $this->errorstring = 'truncated zone transfer';
  1267.                 return(NULL);
  1268.             }
  1269.             $buf $this->read_tcp($this->_axfr_sock$len$this->debug);
  1270.             if ($this->debug{
  1271.                 echo ';; received ' strlen($buf"bytes\n";
  1272.             }
  1273.             if (strlen($buf!= $len{
  1274.                 $this->errorstring = 'expected ' $len ' bytes, received ' strlen($buf);
  1275.                 if ($this->debug{
  1276.                     echo ';; ' $err "\n";
  1277.                 }
  1278.                 return(NULL);
  1279.             }
  1280.             $ans = new Net_DNS_Packet($this->debug);
  1281.             if ($ans->parse($buf)) {
  1282.                 if ($this->errorstring{
  1283.                     $this->errorstring = 'unknown error during packet parsing';
  1284.                 }
  1285.                 return(NULL);
  1286.             }
  1287.             if ($ans->header->ancount < 1{
  1288.                 $this->errorstring = 'truncated zone transfer';
  1289.                 return(NULL);
  1290.             }
  1291.             if ($ans->header->rcode != 'NOERROR'{
  1292.                 $this->errorstring = 'errorcode ' $ans->header->rcode . ' returned';
  1293.                 return(NULL);
  1294.             }
  1295.             foreach ($ans->answer as $rr{
  1296.                 if ($rr->type == 'SOA'{
  1297.                     if (++$this->_axfr_soa_count < 2{
  1298.                         array_push($this->_axfr_rr$rr);
  1299.                     }
  1300.                 else {
  1301.                     array_push($this->_axfr_rr$rr);
  1302.                 }
  1303.             }
  1304.             if ($this->_axfr_soa_count >= 2{
  1305.                 unset($this->_axfr_sock);
  1306.             }
  1307.         }
  1308.         $rr array_shift($this->_axfr_rr);
  1309.         return($rr);
  1310.     }
  1311.  
  1312.     /* }}} */
  1313.     /* Net_DNS_Resolver::read_tcp() {{{ */
  1314.     /**
  1315.      * Unknown - not ported yet
  1316.      */
  1317.     function read_tcp($sock$nbytes$debug = 0)
  1318.     {
  1319.         $buf '';
  1320.         while (strlen($buf$nbytes{
  1321.             $nread $nbytes strlen($buf);
  1322.             $read_buf '';
  1323.             if ($debug{
  1324.                 echo ";; read_tcp: expecting $nread bytes\n";
  1325.             }
  1326.             $read_buf fread($sock$nread);
  1327.             if (strlen($read_buf)) {
  1328.                 if ($debug{
  1329.                     echo ";; ERROR: read_tcp: fread failed\n";
  1330.                 }
  1331.                 break;
  1332.             }
  1333.             if ($debug{
  1334.                 echo ';; read_tcp: received ' strlen($read_buf" bytes\n";
  1335.             }
  1336.             if (!strlen($read_buf)) {
  1337.                 break;
  1338.             }
  1339.  
  1340.             $buf .= $read_buf;
  1341.         }
  1342.         return($buf);
  1343.     }
  1344.     /* }}} */
  1345. }
  1346. /* }}} */
  1347. /* VIM settings {{{
  1348.  * Local variables:
  1349.  * tab-width: 4
  1350.  * c-basic-offset: 4
  1351.  * soft-stop-width: 4
  1352.  * c indent on
  1353.  * expandtab on
  1354.  * End:
  1355.  * vim600: sw=4 ts=4 sts=4 cindent fdm=marker et
  1356.  * vim<600: sw=4 ts=4
  1357.  * }}} */
  1358. ?>

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