php dns更新,php dns解析类

分享一个php操作dns的类,可用于dns的查询、dns解析等操作,有需要的朋友参考下。

php实现的dns解析类,如下:

name = $name;

$this->type = $type;

$this->dclass = $dclass;

$this->ttl = $ttl;

$this->specific_fields = $specific_fields;

}

function &getTypeSpecificField( $name ) {

if( $this->specific_fields ) {

return $this->specific_fields[$name];

}

return false;

}

}

class DNSResolver

{

var $port;

var $nameserver;

var $timeout;

function DNSResolver( $nameserver, $port = 53, $timeout = 1000000 ) {

$this->port = $port;

$this->nameserver = $nameserver;

$this->timeout = $timeout;

}

function sendQuery( $dnsquery, $useTCP = false ) {

$answer = false;

$out_buf = $dnsquery->asOctets( false );

$out_buf_len = strlen( $out_buf );

if( $out_buf ) {

if( $useTCP == false && $out_buf_len <= DNS_UDP_PACKET_MAX_LENGTH ) {

/* connection by UDP */

if( ( $sock = fsockopen( 'udp://'.$this->nameserver, $this->port, $this->timeout ) ) === false ) {

return false;

}

socket_set_blocking( $sock, true );

if( fwrite( $sock, $out_buf ) == $out_buf_len ) {

$answer = new DNSAnswer( $sock, DNS_UDP_PACKET_MAX_LENGTH );

}

fclose( $sock );

} else {

/* connection by TCP */

if( ( $sock = fsockopen( $this->nameserver, $this->port, $this->timeout ) ) === false ) {

return false;

}

socket_set_blocking( $sock, true );

if( fwrite( $sock, pack( 'n', $out_buf_len ) ) == 2 &&

fwrite( $sock, $out_buf ) == $out_buf_len ) {

$tmp = unpack( 'nl', fread( $sock, 2 ) );

$limit_length = $tmp['l'];

print $limit_length;

$answer = new DNSAnswer( $sock, $limit_length );

}

fclose( $sock );

}

}

return $answer;

}

}

class DNSQuery

{

var $id; // 1 - 65535

var $header_opcode;

var $query_record;

var $flags;

function DNSQuery( &$dnsrecord, $flags = DNS_HEADERSPEC_RECURSION_DESIRED )

{

$this->id = rand( 1, 255 ) | ( rand( 0, 255 ) << 8 );

$this->flags = $flags & DNS_HEADERSPEC_QUERY_SPEC_MASK;

$this->header_opcode = DNS_OPCODE_QUERY;

$this->query_record = &$dnsrecord;

}

function asOctets() {

if( $this->query_record->name === false ) { return false; }

$buf = '';

$buf .= pack( "nnnnnn", $this->id, DNS_OPCODE_QUERY | $this->flags, 1, 0, 0, 0 );

$buf .= $this->query_record->name->asOctets();

$buf .= pack( "nn", $this->query_record->type, $this->query_record->dclass );

return $buf;

}

}

class DNSMessageParser

{

var $stream;

var $nbytes_read;

var $octets;

var $limit;

function DNSMessageParser( $stream, $limit ) {

$this->stream = $stream;

$this->nbytes_read = 0;

$this->octets = '';

$this->limit = $limit;

}

function readStreamDirectly( $nbytes ) {

if( ( $this->limit -= $nbytes ) < 0 ) {

return false;

}

$buf = fread( $this->stream, $nbytes );

$this->octets .= $buf;

$this->nbytes_read += $nbytes;

return $buf;

}

function readBufferedStream( $nbytes, $offset ) {

if( $offset < $this->nbytes_read ) {

$diff = $this->nbytes_read - $offset;

if( $nbytes <= $diff ) {

return substr( $this->octets, $offset, $nbytes );

} else {

$buf = substr( $this->octets, $offset, $diff );

$nbytes -= $diff;

}

} else {

$buf = '';

while( $offset > $this->nbytes_read ) {

if( $this->readStreamDirectly( $offset - $this->nbytes_read ) === false ) {

return false;

}

}

}

if( ( $_buf = $this->readStreamDirectly( $nbytes ) ) === false ) {

return false;

}

$buf .= $_buf;

return $buf;

}

function getHeaderInfo() {

if( ( $buf = $this->readStreamDirectly( 12 ) ) === false ) {

$this = false;

return;

}

return unpack( "nid/nspec/nqdcount/nancount/nnscount/narcount", $buf );

}

function getQueryRecords( $nrecs ) {

$recs = array();

while( --$nrecs >= 0 ) {

if( ( $labels = $this->getLabels() ) === false ) {

$this = false;

return;

}

if( ( $buf = $this->readStreamDirectly( 4 ) ) === false ) {

$this = false;

return;

}

$info = unpack( "ntype/ndclass", $buf );

$recs[] = new DNSRecord(

new DNSName( $labels ),

$info['type'],

$info['dclass']

);

}

return $recs;

}

function getResourceRecords( $nrecs ) {

$recs = array();

while( --$nrecs >= 0 ) {

if( ( $labels = $this->getLabels() ) === false ) {

return false;

}

if( ( $buf = $this->readStreamDirectly( 10 ) ) === false ) {

return false;

}

$info = unpack( "ntype/ndclass/Nttl/nrdlength", $buf );

switch( $info['type'] ) {

case DNS_RECORDTYPE_CNAME:

case DNS_RECORDTYPE_NS:

case DNS_RECORDTYPE_PTR:

if( ($_labels = $this->getLabels($info['rdlength']) ) === false ) {

return false;

}

$specific_fields = array( 'dname' => new DNSName( $_labels ) );

break;

case DNS_RECORDTYPE_TXT:

if( ($_labels = $this->getLabels($info['rdlength']) ) === false ) {

return false;

}

$specific_fields = array( 'text' => $_labels );

break;

case DNS_RECORDTYPE_MX:

if( ( $buf = $this->readStreamDirectly(2) ) === false ) {

return false;

}

$specific_fields = unpack( 'npreference', $buf );

if( ( $_labels = $this->getLabels($info['rdlength']-2) ) === false ) {

return false;

}

$specific_fields['exchange'] = new DNSName( $_labels );

break;

case DNS_RECORDTYPE_A:

if( ( $buf = $this->readStreamDirectly(4) ) === false ) {

return false;

}

$specific_fields = array( 'address' => DNSName::newFromString( implode( '.', unpack( 'Ca/Cb/Cc/Cd', $buf ) ) ) );

break;

case DNS_RECORDTYPE_AAAA:

if( ( $buf = $this->readStreamDirectly(16) ) === false ) {

return false;

}

$specific_fields = array( 'address' => DNSName::newFromString( implode( '.', unpack(

'Ca/Cb/Cc/Cd/Ce/Cf/Cg/Ch/Ci/Cj/Ck/Cl/Cm/Cn/Co/Cp', $buf ) ).'.IP6.ARPA' ) );

break;

case DNS_RECORDTYPE_SOA:

$specific_fields = array();

if( ($_labels = $this->getLabels($info['rdlength']) ) === false ) {

return false;

}

$specific_fields['source'] = new DNSName( $_labels );

if( ($_labels = $this->getLabels($info['rdlength']) ) === false ) {

return false;

}

$specific_fields['resp_person'] = array_shift( $_labels ).'@';

$specific_fields['resp_person'] .= implode( '.', $_labels );

if( ( $buf = $this->readStreamDirectly(20) ) === false ) {

return false;

}

$specific_fields = array_merge(

$specific_fields,

unpack( 'Nserial/Nrefresh/Nretry/Nexpire/Nminttl', $buf )

);

break;

default:

if( $this->readStreamDirectly( $info['rdlength'] ) === false ) {

return false;

}

$specific_fields = false;

}

$recs[] = new DNSRecord(

new DNSName( $labels ),

$info['type'],

$info['dclass'],

$info['ttl'],

$specific_fields

);

}

return $recs;

}

function getLabels( $max_length = 255, $offset = -1 ) {

if( $offset < 0 ) { $offset = $this->nbytes_read; }

$labels = array();

for(;;) {

if( --$max_length < 0 ) { return false; }

if( ( $buf = $this->readBufferedStream( 1, $offset ) ) === false ) {

return false;

}

$label_len = ord( $buf );

++$offset;

if( $label_len < 64 ) {

/* uncompressed */

if( ( $max_length -= $label_len ) < 0 ) { return false; }

if( ( $labels[] = $this->readBufferedStream( $label_len, $offset ) ) === false ) {

return false;

}

$offset += $label_len;

if( $label_len == 0 ) { break; }

} else {

/* compressed */

if( ( $buf = $this->readBufferedStream( 1, $offset ) ) === false ) {

return false;

}

if( --$max_length < 0 ) {

return false;

}

$_offset = ( ( $label_len & 0x3f ) << 8 ) + ord( $buf );

if( ($_labels = $this->getLabels( $offset - $_offset, $_offset )) === false ) {

return false;

}

$labels = array_merge( $labels, $_labels );

break;

}

}

return $labels;

}

}

class DNSAnswer

{

var $id;

var $result_code;

var $flags;

var $rec_query;

var $rec_answer;

var $rec_authority;

var $rec_additional;

function DNSAnswer( &$stream, $limit ) {

$msgparser = new DNSMessageParser( $stream, $limit );

$info = & $msgparser->getHeaderInfo();

$this->id = $info['id'];

$this->result_code = $info['spec'] & DNS_HEADERSPEC_RESULT_CODE_MASK;

$this->flags = $info['spec'] & DNS_HEADERSPEC_RESPONSE_SPEC_MASK;

$nrec_query = $info['qdcount'];

$nrec_answer = $info['ancount'];

$nrec_authority = $info['nscount'];

$nrec_additional = $info['arcount'];

if( ( $this->rec_query = &$msgparser->getQueryRecords( $nrec_query ) ) === false ) {

$this = false;

return;

}

if( ( $this->rec_answer = &$msgparser->getResourceRecords( $nrec_answer ) ) === false ) {

$this = false;

return;

}

if( ( $this->rec_authority = &$msgparser->getResourceRecords( $nrec_authority ) ) === false ) {

$this = false;

return;

}

if( ( $this->rec_additional = &$msgparser->getResourceRecords( $nrec_additional ) ) === false ) {

$this = false;

return;

}

}

}

class DNSName

{

var $labels;

function DNSName( $labels ) {

$this->labels = & $labels;

}

function isRealDomainName() {

$i = count( $this->labels ) - 1;

if( $i >= 1 && strtoupper($this->labels[$i-1]) == 'ARPA' ) {

return false;

}

return true;

}

function newFromString( $domain_name ) {

if( strpos( $domain_name, ':' ) !== false && !ereg( '[^0-9a-fA-f:.]', $domain_name ) ) {

/* IPv6 address literal expression spec */

$labels = array();

$components = explode( ':', $domain_name );

$ncomponents = count($components);

$offset = $ncomponents;

while( --$offset >= 0 ) {

$subcomps = explode( '.', $components[$offset] );

$nsubcomps = count( $subcomps );

if( $nsubcomps == 1 ) {

if( $subcomps[0] == '' ) {

$_offset = 0;

while( $components[$_offset] != '' ) {

++$_offset;

}

$count = 9-($ncomponents-$offset)+$_offset;

while( --$count >= 0 ) {

$labels[] = '0';

$labels[] = '0';

$labels[] = '0';

$labels[] = '0';

}

if( $_offset < $offset ) {

$offset = $_offset;

}

} else {

$compval = hexdec( $subcomps[0] );

$labels[] = dechex( $compval & 0x0f );

$compval >>= 4;

$labels[] = dechex( $compval & 0x0f );

$compval >>= 4;

$labels[] = dechex( $compval & 0x0f );

$compval >>= 4;

$labels[] = dechex( $compval & 0x0f );

$compval >>= 4;

}

} elseif( $nsubcomps == 4 ) {

$labels[] = dechex( $subcomps[3] );

$labels[] = dechex( $subcomps[2] );

$labels[] = dechex( $subcomps[1] );

$labels[] = dechex( $subcomps[0] );

} else {

return false;

}

}

$labels[] = 'IP6';

$labels[] = 'ARPA';

$labels[] = '';

} else {

if( substr( $domain_name, -1, 1 ) != '.' ) {

$domain_name .= '.';

}

$labels = explode( '.', $domain_name );

$nlabels = count( $labels );

if( $nlabels == 5 && !ereg( '[^0-9.]', $domain_name ) ) {

/* IPv4 raw address literal representation spec */

$tmp = (string)$labels[0];

$labels[0] = (string)$labels[3];

$labels[3] = $tmp;

$tmp = (string)$labels[1];

$labels[1] = (string)$labels[2];

$labels[2] = $tmp;

$labels[4] = 'IN-ADDR';

$labels[5] = 'ARPA';

$labels[6] = '';

}

}

return new DNSName( $labels );

}

function asOctets() {

$upto = count( $this->labels );

$buf = '';

for( $offset = 0; $offset < $upto; ++$offset ) {

$label_len = strlen( $this->labels[$offset] );

$buf .= pack( "C", $label_len ).$this->labels[$offset];

}

return $buf;

}

function getCanonicalName() {

return implode( ".", $this->labels );

}

}

?>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值