....................................../////.===Shadow-Here===./////................................................ > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < ------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RIFF¤ WEBPVP8 ˜ ðÑ *ôô>‘HŸK¥¤"§£±¨àð enü¹%½_F‘åè¿2ºQú³íªú`N¿­3ÿƒügµJžaÿ¯ÿ°~¼ÎùnúîÞÖô•òíôÁÉß®Sm¥Ü/ ‡ó˜f£Ùà<˜„xëJ¢Ù€SO3x<ªÔ©4¿+ç¶A`q@Ì“Úñè™ÍÿJÌ´ª-˜ÆtÊÛL]Ïq*‘Ý”ì#ŸÌÏãY]@ê`¿ /ªfkØB4·®£ó z—Üw¥Pxù–ÞLШKÇN¾AkÙTf½è'‰g gÆv›Øuh~ a˜Z— ïj*á¥t d£“uÒ ¨`K˜¹ßþ]b>˜]_ÏÔ6W—è2r4x•íÖ…"ƒÖNîä!¦å Ú}ýxGøÌ —@ ;ÆÚŠ=ɾ1ý8lªË¥ô ^yf®Œ¢u&2©nÙÇ›ñÂñŒ³ aPo['½»øFùà­+4ê“$!lövlüÞ=;N®3ð‚õ›DÉKòÞ>ÄÍ ¥ˆuߤ#ˆ$6ù™¥îЇy’ÍB¼ çxÛ;X"WL£R÷͝*ó-¶Zu}º.s¸sšXqù–DþÿvªhüïwyŸ ¯é³lÀ:KCûÄ£Ëá\…­ ~—ýóî ¼ûûÜTÓüÇy…ŽÆvc»¾×U ñ¸žþоP÷¦ó:Ò¨¨5;Ð#&#ÖúñläÿÁœ GxÉ­/ñ‡áQðìYÉtÒw޼GÔ´zàÒò ð*ëzƒ•4~H]Ø‹f ñÓÈñ`NåWçs'ÆÏW^ø¹!XžµmQ5ÃËoLœÎ: ÞËÍ¥J ù…î èo£ßPÎñ¶ž8.Œ]ʵ~5›ÙË-ù*8ÙÖß±~ ©¹rÓê‚j¶d¸{^Q'˜±Crß ÚH—#¥¥QlÀ×ëã‡DÜ«èî þ&Çæžî;ŽÏºò6ÒLÃXy&ZŒ'j‚¢Ù€IßÚù+–MGi‰*jE€‘JcÜ ÓÌ EÏÚj]o˜ Þr <¾U ûŪæÍ/šÝH¥˜b”¼ ÁñßX GP›ï2›4WŠÏà×£…íÓk†¦H·ÅíMh–*nó÷à]ÁjCº€b7<ب‹¨5車bp2:Á[UªM„QŒçiNMa#<5›áËó¸HýÊ"…×Éw¹¦ì2º–x<›»a±¸3Weü®FÝ⑱ö–î–³|LPÈ~çð~Çå‡|º kD¢µÏàÆAI %1À% ¹Ò – ”ϝS¦‰4&¶£°à Öý”û_Ò Áw°A«Å€?mÇÛgHÉ/8)á¾ÛìáöŽP í¨PŸNÙµº¦‡§Ùš"ÿ«>+ªÕ`Ê÷‡‚ß Õû˜þãÇ-PÍ.¾XV‘€ dÜ"þ4¹ ±Oú‘©t¥¦FªÄÃÄ•b‚znýu½—#cDs˜ÃiÑOˆñ×QO=*IAÊ,¶ŽZƒ;‡wøXè%EÐk:F±Ú” .Ѽ+Áu&Ç`."pÈÉw o&¿dE6‘’EqTuK@Ì¥ã™À(Êk(h‰,H}RÀIXÛš3µ1©_OqÚÒJAñ$ÊÙÜ;D3çŒ[þùœh¬Ã³™ö6ç†NY".Ú‰ï[ªŸŒ '²Ð öø_¨ÂÉ9ué¶³ÒŠõTàîMØ#û¯gN‡bÙ놚X„ö …ÉeüÌ^J ‹€.œ$Æ)βÄeæW#óüßĺŸ€ ÀzwV 9oä»f4V*uB «Ë†¹ì¯žR霓æHXa=&“I4K;¯ç‹h×·"UŠ~<•╪Vêª&ÍSÃÆÅ?ÔqÎ*mTM ˜›µwêd#[C¡©§‘D<©àb†–ÁœøvH/,í:¯( ²£|4-„Æövv„Yͼ™^Á$ˆ„¢Û[6yB.åH*V¨æ?$=˜Ñ€•ñ·­(VlŸ‘ nÀt8W÷´Bûba?q9ú¶Xƒl«ÿ\ù¶’þòUÐj/õ¢Ìµ³g$ƒÎR!¸»|Oߍë’BhîÚÑ¢ñåŒJ„®„£2Ð3•ô02Nt…!£Í]Ïc½Qÿ?ˆ<&ÃA¾Ú,JˆijÌ#5yz„‰Î|ÊŽ5QÏ:‹ÐaóVÔxW—CpeÏzÐïíçôÿÅ_[hãsÐ_/ŽTÝ?BîˆííV$<¿i>²F¬_Eß¿ †bÊŒº­ÿ®Z H“C}”¬,Mp ý/Bá£w>˜YV°aƒúh+cŠ- r/[%|üUMHäQ°X»|û/@|°¥Ð !BÔ Ç¢Ä©š+Õì D«7ìN¶ŽðÔ " ƶ’ÖçtA‰Û×}{tþz­¾GÍ›k¹OEJR$ Â׃ «ëÁ"oÉôž$oUK(Ä)Ãz³Ê-‹êN[Ò3Œñbï8P 4ƒ×q¢bo|?<ÛX¬òÄͰL–±›(™ûG?ýË©ÚÄ–ÂDØÐ_Ç¡ô ¾–ÄÏø ×e8Ë©$ÄF¹Å‹ì[©óìl:F¾f´‹‹Xì²ï®\¬ôùƒ ÿat¥óèÒùHß0äe‚;ü×h:ÆWðHž=Ã8骣"kœ'Y?³}Tûè€>?0l›e1Lòñ„aæKÆw…hÖŠùW…ÈÆÄ0ši·›[pcwËþñiêíY/~-Á5˜!¿†A›™Mÿþ(±“t@â“ö2­´TG5yé]çå僳 .·ÍïçÝ7UÚ±Ð/Nè»,_Ï ùdj7\ï Wì4›„»c¸àešg#ÒÊ⥭áØo5‘?ÌdÝô¯ ¹kzsƒ=´#ëÉK›Ø´±-¥eW?‡çßtòTã…$Ý+qÿ±ƒ÷_3Ô¥í÷:æ–ž<·Ö‡‰Å¢ š‡%Ô—utÌÈìðžgÖÀz²À—ï÷Óîäõ{K'´È÷³yaÏÁjƒô}ž§®æÊydÕÈë5¯èˆõvÕ©ã*çD„ “z„Ó‡^^xÂ3M§A´JG‚öï 3W'ˆ.OvXè¡ÊÕª?5º7†˜(˜Ç¶#çê’¶!ÌdZK§æ 0fãaN]òY³RV ™î$®K2R¨`W!1Ôó\;Ý ýB%qæK•&ÓÈe9È0êI±žeŸß -ú@žQr¦ ö4»M¼Áè¹µmw 9 EÆE_°2ó„ŸXKWÁ×Hóì^´²GѝF©óäR†¦‰ç"V»eØ<3ùd3ÿÚ¤Žú“Gi" —‘_ÙËÎ~Üö¯¥½Î»üŸEÚŽåmÞþí ;ÞólËΦMzA"Âf(´òá;Éï(/7½ûñÌ­cïÕçлþÝz¾-ÍvÑ“pH­–ðÓj$¸Äû¤‚‘ãUBË-n“2åPkS5&‹Â|+g^œ®Ì͆d!OïäîU«c;{Û!ÅŽ«ëZ9Ókóˆ]¯ƒ›né `ÇÒ+tÆš (ØKá¾—=3œ®•vuMñg²\ï Ec€ 05±d™‡×iÇ×›UúvÌ¢£Èþ¡ÕØô¶ßÎA"ß±#Ö²ˆÊŸ¦*Ä~ij|àø.-¼'»Ú¥£h ofº¦‡VsR=N½„Î v˜Z*SÌ{=jÑB‹tê…;’HžH¯8–îDù8ñ¢|Q•bÛçš–‹m³“ê¨ åÏ^m¬Žãþ©ïêO‡½6] µÆ„Ooòü ²x}N¦Ë3ïé¿»€›HA˜m%çÞ/¿í7Fø“‹léUk)É°Œµ8Q8›:ÀŠeT*šõ~ôڝG6 ¢}`ùH­–”¡k ‰P1>š†®9z11!X wKfmÁ¦xÑ,N1Q”–æB¶M…ÒÃv6SMˆhU¬ÊPŽï‘öj=·CŒ¯u¹ƒVIЃsx4’ömÛýcå¡¶7ßŠß 57^\wÒÐÆ k§h,Œý î«q^R½3]J¸ÇðN ‚çU¬ôº^Áì} ³f©Õœ§ˆã:FÄÈ‚é(€™?àýÓüè1Gô£¼éj‚OÅñ  #>×—ßtà 0G¥Åa뀐kßhc™À_ÉñÞ#±)GD" YîäË-ÿÙ̪ ¹™a¯´¢E\ÝÒö‚;™„ë]_ p8‰o¡ñ+^÷ 3‘'dT4œŽ ðVë½° :¬víÑ«£tßÚS-3¶“þ2 †üüʨòrš¹M{É_¤`Û¨0ìjœøJ‡:÷ÃáZ˜†@GP&œÑDGÏs¡þ¦þDGú‘1Yá9Ôþ¼ ûø…§÷8&–ÜÑnÄ_m®^üÆ`;ÉVÁJ£?â€-ßê}suÍ2sõA NÌúA磸‘îÿÚ»ƒìö·á¿±tÑÐ"Tÿü˜[@/äj¬€uüªìù¥Ý˜á8Ý´sõj 8@rˆð äþZÇD®ÿUÏ2ùôõrBzÆÏÞž>Ì™xœ“ wiÎ×7_… ¸ \#€MɁV¶¥üÕÿPÔ9Z‡ø§É8#H:ƒ5ÀÝå9ÍIŒ5åKÙŠ÷qÄ>1AÈøžj"µÂд/ªnÀ qªã}"iŸBå˜ÓÛŽ¦…&ݧ;G@—³b¯“•"´4í¨ôM¨åñC‹ïùÉó¯ÓsSH2Ý@ßáM‡ˆKÀªÛUeø/4\gnm¥‹ŸŒ qÄ b9ÞwÒNÏ_4Ég³ú=܆‚´ •â¥õeíþkjz>éÚyU«Íӝ݃6"8/ø{=Ô¢»G¥ äUw°W«,ô—¿ãㆅү¢³xŠUû™yŒ (øSópÐ 9\åTâ»—*oG$/×ÍT†Y¿1¤Þ¢_‡ ¼ „±ÍçèSaÓ 3ÛMÁBkxs‰’R/¡¤ˆÙçª(*õ„üXÌ´ƒ E§´¬EF"Ù”R/ÐNyÆÂ^°?™6¡œïJ·±$§?º>ÖüœcNÌù¯G ‹ñ2ЁBB„^·úìaz¨k:#¨Æ¨8LÎõލ£^§S&cŒÐU€ü(‡F±Š¼&P>8ÙÁ ‰ p5?0ÊÆƒZl¸aô š¼¡}gÿ¶zÆC²¹¬ÎÖG*HB¡O<º2#ñŒAƒ–¡B˜´É$¥›É:FÀÔx¾u?XÜÏÓvN©RS{2ʈãk9rmP¼Qq̳ è¼ÐFׄ^¡Öì fE“F4A…!ì/…¦Lƒ… … $%´¾yã@CI¬ á—3PþBÏNÿ<ý°4Ü ËÃ#ØÍ~âW«rEñw‹eùMMHß²`¬Öó½íf³:‹k˜¯÷}Z!ã¿<¥,\#öµÀ¯aÒNÆIé,Ћ–lŽ#Àæ9ÀÒS·I’½-Ïp Äz¤Š Â* ­íÄ9­< h>׍3ZkËU¹§˜ŒŠ±f­’¤º³Q ÏB?‹#µíÃ¥®@(Gs«†vI¥Mµ‹Á©e~2ú³ÁP4ìÕi‚²Ê^ö@-DþÓàlÜOÍ]n"µã:žpsŽ¢:! Aõ.ç~ÓBûH÷JCÌ]õVƒd «ú´QÙEA–¯¯Œ!.ˆˆëQ±ù œ·Ì!Õâ )ùL„ÅÀlÚè5@B…o´Æ¸XÓ&Û…O«˜”_#‡ƒ„ûÈt!¤ÁÏ›ÎÝŠ?c9 â\>lÓÁVÄÑ™£eØY]:fÝ–—ù+p{™ðè û³”g±OƒÚSù£áÁÊ„ä,ï7š²G ÕÌBk)~ÑiCµ|h#u¤¶îK¨² #²vݯGãeÖ϶ú…¾múÀ¶þÔñ‚Š9'^($¤§ò “š½{éúp÷J›ušS¹áªCÂubÃH9™D™/ZöØÁ‡¦ÝÙŸ·kð*_”.C‹{áXó€‡c¡c€§/šò/&éš÷,àéJþ‰X›fµ“C¨œ®r¬"kL‰Â_q…Z–.ÉL~O µ›zn‚¹À¦Öª7\àHµšÖ %»ÇníV[¥*Õ;ƒ#½¾HK-ÖIÊdÏEÚ#=o÷Óò³´Š: Ç?{¾+9›–‘OEáU·S€˜j"ÄaÜ ŒÛWt› á–c#a»pÔZÞdŽtWê=9éöÊ¢µ~ ë ;Öe‡Œ®:bî3±ýê¢wà¼îpêñ¹¾4 zc¾ðÖÿzdêŒÑÒŝÀ‰s6¤í³ÎÙB¿OZ”+F¤á‡3@Ñëäg©·Ž ˆèª<ù@É{&S„œÕúÀA)‰h:YÀ5^ÂÓŒ°õäU\ ùËÍû#²?Xe¬tu‰^zÒÔãë¼ÛWtEtû …‚g¶Úüâî*moGè¨7%u!]PhÏd™Ý%Îx: VÒ¦ôÊD3ÀŽKÛËãvÆî…N¯ä>Eró–ð`5 Œ%u5XkñÌ*NU%¶áœÊ:Qÿú»“úzyÏ6å-၇¾ ´ ÒÊ]y žO‘w2Äøæ…H’²f±ÎÇ.ª|¥'gîV•Ü .̘¯€šòü¤U~Ù†*¢!?ò wý,}´°ÔÞnïoKq5µb!áÓ3"vAßH¡³¡·G(ÐÎ0Îò¼MG!/ài®@—¬04*`…«é8ªøøló“ˆÊ”èù¤…ßÊoÿé'ËuÌÖ5×È¡§ˆˆfŽë9}hìâ_!!¯  B&Ëö¶‰ÀAÙNVŸ Wh›¸®XÑJì¨ú“¿÷3uj²˜¨ÍÎìë±aúŠÝå¯ð*Ó¨ôJ“yºØ)m°WýOè68†ŸÏ2—‰Ïüꪫٚ¥‹l1 ø ÏÄFjêµvÌbü¦èÝx:X±¢H=MÐß—,ˆÉÇ´(9ú¾^ÅÚ4¿m‡$âX‘å%(AlZo@½¨UOÌÕ”1ø¸jÎÀÃÃ_ µ‘Ü.œº¦Ut: Æï’!=¯uwû#,“pþÇúŒø(é@?³ü¥‘Mo §—s@Œ#)§ŒùkL}NOÆêA›¸~r½¼ÙA—HJ«eˆÖ´*¡ÓpÌŸö.m<-"³ûÈ$¬_6­åf£ïÚâj1y§ÕJ½@dÞÁr&Í\Z%D£Íñ·AZ Û³øüd/ªAi†/Й~  ‡âĮҮÏh§°b—›Û«mJžòG'[ÈYýŒ¦9psl ýÁ ®±f¦x,‰½tN ‚Xª9 ÙÖH.«Lo0×?͹m¡å†Ѽ+›2ƒF ±Ê8 7Hցϓ²Æ–m9…òŸï]Â1äN†VLâCˆU .ÿ‰Ts +ÅÎx(%¦u]6AF Š ØF鈄‘ |¢¶c±soŒ/t[a¾–û:s·`i햍ê›ËchÈ…8ßÀUÜewŒðNOƒõD%q#éû\9¤x¹&UE×G¥ Í—™$ð E6-‡¼!ýpãÔM˜ Âsìe¯ñµK¢Ç¡ùôléœ4Ö£”À Š®Ðc ^¨À}ÙËŸ§›ºê{ÊuÉC ×Sr€¤’fÉ*j!úÓ’Gsùìoîßîn%ò· àc Wp÷$¨˜)û»H ×8ŽÒ€Zj¤3ÀÙºY'Ql¦py{-6íÔCeiØp‘‡XÊîÆUߢ܂ž£Xé¼Y8þ©ëgñß}é.ÎógÒ„ÃØËø¯»™§Xýy M%@NŠ À(~áÐvu7&•,Ù˜ó€uP‡^^®=_E„jt’ 403WebShell
403Webshell
Server IP : 195.3.193.33  /  Your IP : 216.73.216.125
Web Server : Apache
System : Linux server3 5.10.0-35-amd64 #1 SMP Debian 5.10.237-1 (2025-05-19) x86_64
User : web032 ( 1035)
PHP Version : 7.3.33
Disable Function : show_source, highlight_file, apache_child_terminate, apache_get_modules, apache_note, apache_setenv, virtual, dl, disk_total_space, posix_getpwnam, posix_getpwuid, posix_mkfifo, posix_mknod, posix_setpgid, posix_setsid, posix_setuid, posix_uname, proc_nice, openlog, syslog, pfsockopen
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /usr/share/doc/libnet-dns-perl/examples/contrib/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/share/doc/libnet-dns-perl/examples/contrib/check_zone
#!/usr/bin/perl -w
# $Id: check_zone 1811 2020-10-05 08:24:23Z willem $

=head1 NAME

check_zone - Check a DNS zone for errors

=head1 SYNOPSIS

C<check_zone> [ C<-r> ][ C<-v> ] I<domain> [ I<class> ]

=head1 DESCRIPTION

Checks a DNS zone for errors.  Current checks are:

=over 4

=item *

Checks the domain's SOA from each of the domain's name servers. The SOA serial numbers should match. This program's output cannot be trusted if they do not.

=item *

Tries to perform an AXFR from each of the domain's name servers. This test helps to detect whether the name server is blocking AXFR.

=item *

Checks that all A records have corresponding PTR records. For each A record its PTR's name is match checked.

=item *

Checks that all PTR records match an A record (sometimes they match a CNAME). Check the PTR's name against the A record.

=item *

Checks that hosts listed in NS, MX, and CNAME records have
A records. Checks for NS and CNAME records not pointing to another CNAME (i.e., they must directly resolve to an A record). That test may be somewhat controversial because, in many cases, a MX to a CNAME or a CNAME to another CNAME will resolve; however, in DNS circles it isn't a recommended practise.

=item *

Check each record processed for being with the class requested. This is an internal integrity check.

=back

=head1 OPTIONS

=over 4

=back

=item C<-r>

Perform a recursive check on subdomains.

=item C<-v>

Verbose.

=item C<-a alternate_domain>

Treat <alternate_domain> as equal to <domain>. This is useful when supporting a change of domain names (eg from myolddomain.example.net to mynewdomain.example.net) where the PTR records can point to only one of the two supported domains (which are otherwise identical).

=item C<-e exception_file>

Ignore exceptions in file <exception_file>. File format can be space-separated domain pairs, one pair per line, or it can be straight output from this program itself (for simple cut-and-paste functionality). 
This allows for skipping entries that are odd or unusual, but not causing problems. Note: this only works with A - PTR checks.

=head1 AUTHORS

Originally developed by Michael Fuhr (mfuhr@dimensional.com) and
hacked--with furor--by Dennis Glatting
(dennis.glatting@software-munitions.com).

"-a" and "-e" options added by Paul Archer


=head1 COPYRIGHT

=head1 SEE ALSO

L<perl(1)>, L<axfr>, L<check_soa>, L<mx>, L<perldig>, L<Net::DNS>

=head1 BUGS

A query for an A RR against a name that is a CNAME may not follow the CNAME to an A RR.

There isn't a mechanism to insure records are returned from an authoritative source.

There appears to be a bug in the resolver AXFR routine where, if one server cannot be contacted, the routine doesn't try another in its list.

=cut


#require 'assert.pl';

use strict;
use warnings;
use Carp;
use vars qw($opt_r);
use vars qw($opt_v);
use vars qw($opt_a);
use vars qw($opt_e);

use Getopt::Std;
use File::Basename;
use IO::Socket;
use Net::DNS;

getopts("rva:e:");

die "Usage: ", basename($0), " [ -r -v ] [ -a alternate_domain] [ -e eqivalent_domains_file ] domain [ class ]\n"
    unless (@ARGV >= 1) && (@ARGV <= 2);


our $exit_status = 0;
local $SIG{__WARN__} = sub {$exit_status=1 ; print STDERR @_ };



$opt_r = 1;

our $main_domain=$ARGV[0];
our %exceptions = parse_exceptions_file();
foreach my $key (sort keys %exceptions) {
	print "$key:\t";
	foreach my $val (@{$exceptions{$key}}) {
		print "$val ";
	}
	print "\n";
}

check_domain(@ARGV);
exit $exit_status;

sub assert { croak 'violated assertion' unless shift; return }


sub parse_exceptions_file {
	my %exceptions;
	my $file = $opt_e || "";
	return %exceptions unless ( -r $file);
	open( my $fh, '<', $file );
	die "Couldn't read $file: $!" unless $fh;
	while (<$fh>) {
		chomp;
		#print "      raw line: $_\n";
		next if /^$/;
		next if /^\s*#/;
		s/#.*$//;
		s/^\s*//;
		s/\s*$//;
		s/'//g;
		my ($left, $right) = (split /[\s:]+/, $_)[0, -1];
		push @{$exceptions{$left}}, $right;
		#print "processed line: $line\n";
		
	}
	close($fh);
	return %exceptions;
}



sub check_domain {

    my ( $domain, $class ) = @_;
    my $ns;
    my @zone;

    $class ||= "IN";

    print "-" x 70, "\n";
    print "$domain (class $class)\n";
    print "\n";

    my $res = Net::DNS::Resolver->new();
    $res->defnames( 0 );
    $res->retry( 2 );


    my( $nspack, $ns_rr, @nsl );

    # Get a list of name servers for the domain.
    # Error-out if the query isn't satisfied.
    #
    
    $nspack = $res->query( $domain, 'NS', $class );
    unless( defined( $nspack )) {
    
        warn "Couldn't find nameservers for $domain: ",
             $res->errorstring, "\n";
        return;
    }

    printf( "List of name servers returned from '%s'\n", $res->answerfrom );
    foreach my $ns_rr ( $nspack->answer ) {
        
        $ns_rr->print if( $opt_v );

        assert( $class eq $ns_rr->class );
        assert( 'NS' eq $ns_rr->type );

        if( $ns_rr->name eq $domain ) {
        
            print "\t", $ns_rr->rdatastr, "\n";
            push @nsl, $ns_rr->rdatastr;
        } else {
        
            warn( "asked for '$domain', got '%s'\n", $ns_rr->rdatastr );
        }
    }
    print "\n";

    warn( "\tZone has no NS records\n" ) if( scalar( @nsl ) == 0 );


    # Transfer the zone from each of the name servers. 
    # The zone is transferred for several reasons. 
    # First, so the check routines won't (an efficiency 
    # issue) and second, to see if we can.
    #
    
    $res->nameservers( @nsl );

    foreach my $ns ( @nsl ) {
    
        $res->nameservers( $ns );
        
        my @local_zone = $res->axfr( $domain, $class );
        unless( @local_zone ) {
    
            warn "Zone transfer from '", $ns, "' failed: ", 
                    $res->errorstring, "\n";
        }
        @zone = @local_zone if( ! @zone );
    }

    # Query each name server for the zone
    # and check the zone's SOA serial number.
    # 
    
    print "checking SOA records\n";
    check_soa( $domain, $class, \@nsl );
    print "\n";

    
    # Check specific record types.
    #

    print "checking NS records\n";
    check_ns( $domain, $class, \@nsl, \@zone );
    print "\n";

    print "checking A records\n";
    check_a( $domain, $class, \@nsl, \@zone );
    print "\n";

    print "checking PTR records\n";
    check_ptr( $domain, $class, \@nsl, \@zone );
    print "\n";

    print "checking MX records\n";
    check_mx( $domain, $class, \@nsl, \@zone );
    print "\n";

    print "checking CNAME records\n";
    check_cname( $domain, $class, \@nsl, \@zone );
    print "\n";


    # Recurse?
    #

    if( $opt_r ) {
   
        my %subdomains;

        print "checking subdomains\n\n";

        # Get a list of NS records from the zone that 
        # are not for the zone (i.e., they're subdomains).
        #
        
        foreach ( grep { $_->type eq 'NS' and $_->name ne $domain } @zone ) {

            $subdomains{$_->name} = 1;
        }

        # For each subdomain, check it.
        #

        foreach ( sort keys %subdomains ) {

            check_domain($_, $class);
        }
    }
    return;
}

sub check_soa {

    my( $domain, $class, $nsl ) = @_;
    my( $soa_sn, $soa_diff ) = ( 0, 0 );
    my( $ns, $soa_rr );
    my $rr_count = 0;

    my $res = Net::DNS::Resolver->new();

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->recurse( 0 );

    # Contact each name server and get the
    #   SOA for the somain.
    #
    
    foreach my $ns ( @$nsl ) {
    
        my $soa = 0;
        my $nspack;
        
        # Query the name server and test
        # for a result.
        #
        
        $res->nameservers( $ns );

        $nspack = $res->query( $domain, "SOA", $class );
        unless( defined( $nspack )) {
    
            warn "Couldn't get SOA from '$ns'\n";
            next;
        }

        # Look at each SOA for the domain from the
        # name server. Specifically, look to see if
        # its serial number is different across
        # the name servers.
        #
        
        foreach my $soa_rr ( $nspack->answer ) {

            $soa_rr->print if( $opt_v );

            assert( $class eq $soa_rr->class );
            assert( 'SOA' eq $soa_rr->type );
            
            print "\t$ns:\t", $soa_rr->serial, "\n";

            # If soa_sn is zero then an SOA serial number
            # hasn't been recorded. In that case record
            # the serial number. If the serial number 
            # doesn't match a previously recorded one then
            # indicate they are different.
            #
            # If the serial numbers are different then you
            # cannot really trust the remainder of the test.
            #
            
            if( $soa_sn ) {
            
                $soa_diff = 1 if ( $soa_sn != $soa_rr->serial );
            } else {
            
                $soa_sn = $soa_rr->serial;
            }
        }
        
        ++$rr_count;
    }
    
    print "\t*** SOAs are different!\n" if( $soa_diff );
    print "$rr_count SOA RRs checked.\n";
    return;
}

sub check_ptr {

    my( $domain, $class, $nsl, $zone ) = @_;

    my $res = Net::DNS::Resolver->new();
    my $ptr_rr;
    my $rr_count = 0;

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    foreach my $ptr_rr ( grep { $_->type eq 'PTR' } @$zone ) {

        my @types;
    
        $ptr_rr->print if( $opt_v );

        assert( $class eq $ptr_rr->class );
        assert( 'PTR' eq $ptr_rr->type );

        print "\tchecking PTR rr '$ptr_rr' to PTR\n" if( $opt_v );

        @types = types4name( $ptr_rr->ptrdname, $domain, $class, $nsl );
        if( grep { $_ eq 'A' } @types ) {

            xcheck_ptr2a( $ptr_rr, $domain, $class, $nsl );
        } else {
        
            warn "\t'", $ptr_rr->ptrdname, 
                    "' doesn't resolve to an A RR (RRs are '",
                    join( ', ', @types ), "')\n";

        }

        
        ++$rr_count;
    }

    print "$rr_count PTR RRs checked.\n";
    return;
}

sub check_ns {

    my( $domain, $class, $nsl, $zone ) = @_;
    my $res = Net::DNS::Resolver->new();
    my $ns_rr;
    my $rr_count = 0;

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    # Go through the zone data and process
    # all NS RRs for the zone (delegation
    # NS RRs are ignored). Specifically, 
    # check to see if the indicate name server
    # is a CNAME RR and the name resolves to an A
    # RR. Check to insure the address resolved
    # against the name has an associated PTR RR.
    #

    foreach my $ns_rr ( grep { $_->type eq 'NS' } @$zone ) {

        my @types;

        $ns_rr->print if( $opt_v );

        assert( $class eq $ns_rr->class );
        assert( 'NS' eq $ns_rr->type );

        next if( $ns_rr->name ne $domain );
        
        printf( "rr nsdname:  %s\n", $ns_rr->nsdname ) if $opt_v;

        @types = types4name( $ns_rr->nsdname, $domain, $class, $nsl );
        if( grep { $_ eq 'A' } @types ) {
        
            xcheck_name( $ns_rr->nsdname, $domain, $class, $nsl );
        } else {
        
            warn "\t'", $ns_rr->nsdname, 
                    "' doesn't resolve to an A RR (RRs are '",
                    join( ', ', @types ), "')\n";
        }
        ++$rr_count;
    }
    
    print "$rr_count NS RRs checked.\n";
    return;
}

sub check_a {

    my( $domain, $class, $nsl, $zone ) = @_;

    my $res = Net::DNS::Resolver->new();
    my $a_rr;
    my $rr_count = 0;

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    # Go through the zone data and process
    # all A RRs. Specifically, check to insure
    # each A RR matches a PTR RR and the PTR RR
    # matches the A RR.
    #

    foreach my $a_rr ( grep { $_->type eq 'A' } @$zone ) {

        $a_rr->print if( $opt_v );

        assert( $class eq $a_rr->class );
        assert( 'A' eq $a_rr->type );

        print "\tchecking A RR '", $a_rr->address, "' to PTR\n" if( $opt_v );

        xcheck_a2ptr( $a_rr, $domain, $class, $nsl );
        
        ++$rr_count;
    }

    print "$rr_count A RRs checked.\n";
    return;
}


sub check_mx {

    my( $domain, $class, $nsl, $zone ) = @_;

    my $res = Net::DNS::Resolver->new();
    my $mx_rr;
    my $rr_count = 0;

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    # Go through the zone data and process
    # all MX RRs. Specifically, check to insure
    # each MX RR resolves to an A RR and the 
    # A RR has a matching PTR RR.
    #

    foreach my $mx_rr ( grep { $_->type eq 'MX' } @$zone ) {

        $mx_rr->print if( $opt_v );

        assert( $class eq $mx_rr->class );
        assert( 'MX' eq $mx_rr->type );

        print "\tchecking MX RR '", $mx_rr->exchange, "' to A\n" if( $opt_v );

        xcheck_name( $mx_rr->exchange, $domain, $class, $nsl );
        
        ++$rr_count;
    }

    print "$rr_count MX RRs checked.\n";
    return;
}

sub check_cname {

    my( $domain, $class, $nsl, $zone ) = @_;

    my $res = Net::DNS::Resolver->new();
    my $cname_rr;
    my $rr_count = 0;

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    # Go through the zone data and process
    # all CNAME RRs. Specifically, check to insure
    # each CNAME RR resolves to an A RR and the 
    # A RR has a matching PTR RR.
    #

    foreach my $cname_rr ( grep { $_->type eq 'CNAME' } @$zone ) {

        my @types;

        $cname_rr->print if( $opt_v );

        assert( $class eq $cname_rr->class );
        assert( 'CNAME' eq $cname_rr->type );

        print "\tchecking CNAME RR '", $cname_rr->cname, "' to A\n" 
            if( $opt_v );

        @types = types4name( $cname_rr->cname, $domain, $class, $nsl );
        if( grep { $_ eq 'A' } @types ) {
         
            xcheck_name( $cname_rr->cname, $domain, $class, $nsl );
        } else {
        
            warn "\t'", $cname_rr->cname, 
                    "' doesn't resolve to an A RR (RRs are '",
                    join( ', ', @types ), "')\n";
        }
    
        ++$rr_count;
    }

    print "$rr_count CNAME RRs checked.\n";
    return;
}

sub check_w_equivs_and_exceptions {
	my ($left, $comp, $right) = @_;

	if (defined $exceptions{$left}) {
		foreach my $rval (@{$exceptions{$left}}) {
			$left = $right if ($rval eq $right);
		}
	}

	if ($opt_a){
		$left =~ s/\.?$opt_a$//;
		$left =~ s/\.?$main_domain$//;
		$right =~ s/\.?$opt_a$//;
		$right =~ s/\.?$main_domain$//;
	}
	return (eval { "\"$left\" $comp \"$right\"" } );
}

sub xcheck_a2ptr {

    my( $a_rr, $domain, $class, $nsl ) = @_;

    my $res = Net::DNS::Resolver->new();

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    assert( $class eq $a_rr->class );
    assert( 'A' eq $a_rr->type );

    # Request a PTR RR against the A RR.
    # A missing PTR RR is an error.
    #

    my $ans = $res->query( $a_rr->address, 'PTR', $class );
    if( defined( $ans )) {

        my $ptr_rr;
        foreach my $ptr_rr ( $ans->answer ) {

            $ptr_rr->print if( $opt_v );

            assert( $class eq $ptr_rr->class );
            assert( 'PTR' eq $ptr_rr->type );

            warn( "\t'", $a_rr->name, "' has address '", 
                    $a_rr->address, "' but PTR is '",  
                    $ptr_rr->ptrdname, "'\n" )
		if( check_w_equivs_and_exceptions($a_rr->name, "ne", $ptr_rr->ptrdname) );

            warn( "\t'", $a_rr->name, "' has address '", 
                    $a_rr->address, "' but PTR is '", 
                    ip_ptr2a_str( $ptr_rr->name ), "'\n" )
                if( $a_rr->address ne ip_ptr2a_str( $ptr_rr->name ));
        }
    } else {
    
        warn( "\tNO PTR RR for '", $a_rr->name, 
                "' at address '", $a_rr->address,"'\n" );
    }
    return;
}


sub xcheck_ptr2a {

    my( $ptr_rr, $domain, $class, $nsl ) = @_;

    my $res = Net::DNS::Resolver->new();

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    assert( $class eq $ptr_rr->class );
    assert( 'PTR' eq $ptr_rr->type );

    # Request an A RR against the PTR RR.
    # A missing A RR is an error.
    #

    my $ans = $res->query( $ptr_rr->ptrdname, 'A', $class );
    if( defined( $ans )) {
            
        my $a_rr;
        foreach my $a_rr ( $ans->answer ) {

            $a_rr->print if( $opt_v );

            assert( $class eq $a_rr->class );
            assert( 'A' eq $a_rr->type );

            warn( "\tPTR RR '", $ptr_rr->name, "' has name '", 
                    $ptr_rr->ptrdname, "' but A query returned '", 
                    $a_rr->name, "'\n" )
                if( check_w_equivs_and_exceptions($ptr_rr->ptrdname, "ne", $a_rr->name) );

            warn( "\tPTR RR '", $ptr_rr->name, "' has address '", 
                    ip_ptr2a_str( $ptr_rr->name ), 
                    "' but A query returned '", $a_rr->address, "'\n" )
                if( ip_ptr2a_str( $ptr_rr->name ) ne $a_rr->address );
        }
    } else {
    
        warn( "\tNO A RR for '", $ptr_rr->ptrdname, 
                "' at address '", ip_ptr2a_str( $ptr_rr->address ), "'\n" );
    }
    return;
}


sub xcheck_name {

    my( $name, $domain, $class, $nsl ) = @_;

    my $res = Net::DNS::Resolver->new();

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    # Get the A RR for the name.
    #

    my $ans = $res->query( $name, 'A', $class );
    if( defined( $ans )) {
        
        # There is one or more A RRs.
        # For each A RR do a reverse look-up
        # and verify the PTR matches the A.
        #

        my $a_rr;
        foreach my $a_rr ( $ans->answer ) {

            $a_rr->print if( $opt_v );

            assert( $class eq $a_rr->class );
            assert( 'A' eq $a_rr->type );

            warn( "\tQuery for '$name' returned A RR name '", 
                    $a_rr->name, "'\n" ) 
                if( check_w_equivs_and_exceptions($name, "ne", $a_rr->name) );

            xcheck_a2ptr( $a_rr, $domain, $class, $nsl );
        }
    } else {
        
        warn( "\t", $name, " has no A RR\n" );
    }
    return;
}


sub types4name {

    my( $name, $domain, $class, $nsl ) = @_;

    my $res = Net::DNS::Resolver->new();
    my @rr_types;

    $res->defnames( 0 );
    $res->retry( 2 );
    $res->nameservers( @$nsl );

    # Get the RRs for the name.
    #

    my $ans = $res->query( $name, 'ANY', $class );
    if( defined( $ans )) {
        
        my $any_rr;
        foreach my $any_rr ( $ans->answer ) {

            $any_rr->print if( $opt_v );

            assert( $class eq $any_rr->class );
            
            push @rr_types, ( $any_rr->type );
        }
    } else {
        
        warn( "\t'", $name, "' doesn't resolve.\n" );
    }
    
    # If there were no RRs for the name then
    # return the RR types of ???
    #
    
    push @rr_types, ( '???' ) if( ! @rr_types );

    return @rr_types;
}


sub ip_ptr2a_str {

    my( $d, $c, $b, $a ) = ip_parts( $_[0]);

    return "$a.$b.$c.$d";
}



sub ip_parts {

    my $ip = $_[0];
    assert( $ip ne '' );

    if( $ip =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/oi ) {

        return ( $1, $2, $3, $4 );
    } else {

        warn "Unable to parse '$ip'\n";
    }

    assert( 0 );
    return;
}





Youez - 2016 - github.com/yon3zu
LinuXploit