IdDNSServer.pas 137 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. $Log$
  13. Rev 1.40 3/4/2005 12:35:32 PM JPMugaas
  14. Removed some compiler warnings.
  15. Rev 1.39 2/9/2005 4:35:06 AM JPMugaas
  16. Should compile.
  17. Rev 1.38 2/8/05 6:13:02 PM RLebeau
  18. Updated to use new AppendString() function in IdGlobal unit
  19. Updated TIdDNS_ProcessThread.CompleteQuery() to use CopyTId...() functions
  20. instead of ToBytes() and AppendBytes().
  21. Rev 1.37 2005/1/25 下午 12:25:26 DChang
  22. Modify UpdateTree method, make the NS record can be save in the lower level
  23. node.
  24. Rev 1.36 2005/1/5 下午 04:21:06 DChang Version: 1.36
  25. Fix parsing procedure while processing TXT record, in pass version, double
  26. quota will not be processed, but now, any charector between 2 double quotas
  27. will be treated as TXT message.
  28. Rev 1.35 2004/12/15 下午 12:05:26 DChang Version: 1.35
  29. 1. Move UpdateTree to public section.
  30. 2. add DoUDPRead of TIdDNSServer.
  31. 3. Fix TIdDNS_ProcessThread.CompleteQuery and
  32. InternalQuery to fit Indy 10 Core.
  33. Rev 1.34 12/2/2004 4:23:50 PM JPMugaas
  34. Adjusted for changes in Core.
  35. Rev 1.33 2004.10.27 9:17:46 AM czhower
  36. For TIdStrings
  37. Rev 1.32 10/26/2004 9:06:32 PM JPMugaas
  38. Updated references.
  39. Rev 1.31 2004.10.26 1:06:26 PM czhower
  40. Further fixes for aliaser
  41. Rev 1.30 2004.10.26 12:01:32 PM czhower
  42. Resolved alias conflict.
  43. Rev 1.29 9/15/2004 4:59:52 PM DSiders
  44. Added localization comments.
  45. Rev 1.28 22/07/2004 18:14:22 ANeillans
  46. Fixed compile error.
  47. Rev 1.27 7/21/04 2:38:04 PM RLebeau
  48. Removed redundant string copying in TIdDNS_ProcessThread constructor and
  49. procedure QueryDomain() method
  50. Removed local variable from TIdDNS_ProcessThread.SendData(), not needed
  51. Rev 1.26 2004/7/21 下午 06:37:48 DChang
  52. Fix compile error in TIdDNS_ProcessThread.SendData, and mark a case statment
  53. to comments in TIdDNS_ProcessThread.SaveToCache.
  54. Rev 1.25 2004/7/19 下午 09:55:52 DChang
  55. 1. Move all textmoderecords to IdDNSCommon.pas
  56. 2. Making DNS Server load the domain definition file while DNS Server
  57. component is active.
  58. 3. Add a new event : OnAfterCacheSaved
  59. 4. Add Full name condition to indicate if a domain is empty
  60. (ConvertDNtoString)
  61. 5. Make Query request processed with independent thread.
  62. 6. Rewrite TIdDNSServer into multiple thread mode, all queries will search
  63. and assemble the answer, and then share the TIdSocketHandle to send answer
  64. back.
  65. 7. Add version information in TIdDNSServer, so class CHAOS can be taken, but
  66. only for the label : "version.bind.".
  67. 8. Fix TIdRR_TXT.BinQueryRecord, to make sure it can be parsed in DNS client.
  68. 9. Modify the AXFR function, reduce the response data size and quantity.
  69. 10. Move all TIdTextModeResourceRecord and derived classes to IdDNSCommon.pas
  70. Rev 1.24 7/8/04 11:43:54 PM RLebeau
  71. Updated TIdDNS_TCPServer.DoConnect() to use new BytesToString() parameters
  72. Rev 1.23 7/7/04 1:45:16 PM RLebeau
  73. Compiler fixes
  74. Rev 1.22 6/29/04 1:43:30 PM RLebeau
  75. Bug fixes for various property setters
  76. Rev 1.21 2004.05.20 1:39:32 PM czhower
  77. Last of the IdStream updates
  78. Rev 1.20 2004.03.01 9:37:06 PM czhower
  79. Fixed name conflicts for .net
  80. Rev 1.19 2004.02.07 5:03:32 PM czhower
  81. .net fixes.
  82. Rev 1.18 2/7/2004 5:39:44 AM JPMugaas
  83. IdDNSServer should compile in both DotNET and WIn32.
  84. Rev 1.17 2004.02.03 5:45:58 PM czhower
  85. Name changes
  86. Rev 1.16 1/22/2004 8:26:40 AM JPMugaas
  87. Ansi* calls changed.
  88. Rev 1.15 1/21/2004 2:12:48 PM JPMugaas
  89. InitComponent
  90. Rev 1.14 12/7/2003 8:07:26 PM VVassiliev
  91. string -> TIdBytes
  92. Rev 1.13 2003.10.24 10:38:24 AM czhower
  93. UDP Server todos
  94. Rev 1.12 10/19/2003 12:16:30 PM DSiders
  95. Added localization comments.
  96. Rev 1.11 2003.10.12 3:50:40 PM czhower
  97. Compile todos
  98. Rev 1.10 2003/5/14 上午 01:17:36 DChang
  99. Fix a flag named denoted in the function which check if a domain correct.
  100. Update the logic of UpdateTree functions (make them unified).
  101. Update the TextRecord function of all TIdRR_ classes, it checks if the RRName
  102. the same as FullName, if RRName = FullName, it will not append the Fullname
  103. to RRName.
  104. Rev 1.9 2003/5/10 上午 01:09:42 DChang
  105. Patch the domainlist update when axfr action.
  106. Rev 1.8 2003/5/9 上午 10:03:36 DChang
  107. Modify the sequence of records. To make sure when we resolve MX record, the
  108. mail host A record can be additional record section.
  109. Rev 1.7 2003/5/8 下午 08:11:34 DChang
  110. Add TIdDNSMap, TIdDomainNameServerMapping to monitor primary DNS, and
  111. detecting if the primary DNS record changed, it will update automatically if
  112. necessary.
  113. Rev 1.6 2003/5/2 下午 03:39:38 DChang
  114. Fix all compile warnings and hints.
  115. Rev 1.5 4/29/2003 08:26:30 PM DenniesChang
  116. Fix TIdDNSServer Create, the older version miss to create the FBindings.
  117. fix AXFR procedure, fully support BIND 8 AXFR procedures.
  118. Rev 1.4 4/28/2003 02:30:58 PM JPMugaas
  119. reverted back to the old one as the new one checked will not compile, has
  120. problametic dependancies on Contrs and Dialogs (both not permitted).
  121. Rev 1.3 04/28/2003 01:15:10 AM DenniesChang
  122. Rev 1.2 4/28/2003 07:00:18 AM JPMugaas
  123. Should now compile.
  124. Rev 1.0 11/14/2002 02:18:42 PM JPMugaas
  125. // Ver: 2003-04-28-0115
  126. // Combine TCP, UDP Tunnel into single TIdDNSServer component.
  127. // Update TIdDNSServer from TIdUDPServer to TComponent.
  128. // Ver: 2003-04-26-1810
  129. // Add AXFR command.
  130. // Ver: 2002-10-30-1253
  131. // Add TIdRR_AAAA class, RFC 1884 (Ipv6 AAAA)
  132. // and add the coresponding fix in TIdDNSServer, but left
  133. // external search option for future.
  134. // Ver: 2002-07-10-1610
  135. // Add a new event : OnAfterSendBack to handle all
  136. // data logged after query result is sent back to
  137. // the client.
  138. // Ver: 2002-05-27-0910
  139. // Add a check function in SOA loading function.
  140. // Ver: 2002-04-25-1530
  141. // IdDNSServer. Ver: 2002-03-12-0900
  142. // To-do: RFC 2136 Zone transfer must be implemented.
  143. // Add FindHandedNodeByName to pass the TIdDNTreeNode Object back.
  144. // Append a blank char when ClearQuota, to avoid the possible of
  145. // losting a field.
  146. // Add IdDNTree.SaveToFile
  147. // Fix SOA RRName assignment.
  148. // Fix PTRName RRName assignment.
  149. // Fix TIdDNTreeNode RemoveChild
  150. // IdDNSServer. Ver: 2002-02-26-1420
  151. // Convert the DN Tree Node type, earlier verison just
  152. // store the A, PTR in the upper domain node, current
  153. // version save SOA and its subdomain in upper node.
  154. //
  155. // Moreover, move Cached_Tree, Handed_Tree to public
  156. // section, for using convinent.
  157. //
  158. // I forget return CName data, fixed.
  159. // Seperate the seaching of Cache and handled tree into 2
  160. // parts with a flag.
  161. //IdDNSServer. Ver: 2002-02-24-1715
  162. // Move TIdDNSServer protected property RootDNS_NET to public
  163. //IdDNSServer. Ver: 2002-02-23-1800
  164. Original Programmer: Dennies Chang <[email protected]>
  165. No Copyright. Code is given to the Indy Pit Crew.
  166. This DNS Server supports only IN record, but not Chaos system.
  167. Most of resource records in DNS server was stored with text mode,
  168. event the TREE structure, it's just for convininet.
  169. Why I did it with this way is tring to increase the speed for
  170. implementation, with Delphi/Kylix internal class and object,
  171. we can promise the compatible in Windows and Linux.
  172. Started: Jan. 20, 2002.
  173. First Finished: Feb. 23, 2002.
  174. RFC 1035 WKS record is not implemented.
  175. ToDO: Load Master File automaticlly when DNS Server Active.
  176. ToDO: patch WKS record data type.
  177. ToDO: prepare a Tree Editor for DNS Server Construction. (optional)
  178. }
  179. unit IdDNSServer;
  180. interface
  181. {$i IdCompilerDefines.inc}
  182. uses
  183. Classes,
  184. IdContainers,
  185. IdAssignedNumbers,
  186. IdSocketHandle,
  187. IdGlobal,
  188. IdGlobalProtocols,
  189. IdBaseComponent,
  190. IdComponent,
  191. IdContext,
  192. IdUDPBase,
  193. IdExceptionCore,
  194. IdDNSResolver,
  195. IdUDPServer,
  196. IdCustomTCPServer,
  197. IdStackConsts,
  198. IdThread,
  199. IdDNSCommon;
  200. type
  201. TIdDomainExpireCheckThread = class(TIdThread)
  202. protected
  203. FInterval: UInt32;
  204. FSender: TObject;
  205. FTimerEvent: TNotifyEvent;
  206. FBusy : Boolean;
  207. FDomain : string;
  208. FHost : string;
  209. //
  210. procedure Run; override;
  211. procedure TimerEvent;
  212. end;
  213. // forward declaration.
  214. TIdDNSMap = class;
  215. TIdDNS_UDPServer = class;
  216. // This class is to record the mapping of Domain and its primary DNS IP
  217. TIdDomainNameServerMapping = class(TObject)
  218. private
  219. FHost: string;
  220. FDomainName: string;
  221. FBusy : Boolean;
  222. FInterval: UInt32;
  223. FList: TIdDNSMap;
  224. procedure SetHost(const Value: string);
  225. procedure SetInterval(const Value: UInt32);
  226. protected
  227. CheckScheduler : TIdDomainExpireCheckThread;
  228. property Interval : UInt32 read FInterval write SetInterval;
  229. property List : TIdDNSMap read FList write FList;
  230. public
  231. constructor Create(AList : TIdDNSMap);
  232. destructor Destroy; override;
  233. //You can not make methods and properties published in this class.
  234. //If you want to make properties publishes, this has to derrive from TPersistant
  235. //and be used by TPersistant in a published property.
  236. // published
  237. procedure SyncAndUpdate(Sender : TObject);
  238. property Host : string read FHost write SetHost;
  239. property DomainName : string read FDomainName write FDomainName;
  240. end;
  241. TIdDNSMap = class(TIdObjectList{$IFDEF HAS_GENERICS_TObjectList}<TIdDomainNameServerMapping>{$ENDIF})
  242. private
  243. FServer: TIdDNS_UDPServer;
  244. {$IFNDEF HAS_GENERICS_TObjectList}
  245. function GetItem(Index: Integer): TIdDomainNameServerMapping;
  246. procedure SetItem(Index: Integer; const Value: TIdDomainNameServerMapping);
  247. {$ENDIF}
  248. procedure SetServer(const Value: TIdDNS_UDPServer);
  249. public
  250. constructor Create(Server: TIdDNS_UDPServer);
  251. {$IFNDEF USE_OBJECT_ARC}
  252. destructor Destroy; override;
  253. {$ENDIF}
  254. property Server : TIdDNS_UDPServer read FServer write SetServer;
  255. {$IFNDEF HAS_GENERICS_TObjectList}
  256. property Items[Index: Integer]: TIdDomainNameServerMapping read GetItem write SetItem; default;
  257. {$ENDIF}
  258. end;
  259. TIdMWayTreeNodeClass = class of TIdMWayTreeNode;
  260. // TODO: derive from TObjectList instead and remove SubTree member?
  261. TIdMWayTreeNode = class(TObject)
  262. private
  263. SubTree : TIdObjectList{$IFDEF HAS_GENERICS_TObjectList}<TIdMWayTreeNode>{$ENDIF};
  264. FFundmentalClass: TIdMWayTreeNodeClass;
  265. function GetTreeNode(Index: Integer): TIdMWayTreeNode;
  266. procedure SetFundmentalClass(const Value: TIdMWayTreeNodeClass);
  267. procedure SetTreeNode(Index: Integer; const Value: TIdMWayTreeNode);
  268. public
  269. constructor Create(NodeClass : TIdMWayTreeNodeClass); virtual;
  270. destructor Destroy; override;
  271. property FundmentalClass : TIdMWayTreeNodeClass read FFundmentalClass write SetFundmentalClass;
  272. property Children[Index : Integer] : TIdMWayTreeNode read GetTreeNode write SetTreeNode;
  273. function AddChild : TIdMWayTreeNode;
  274. function InsertChild(Index : Integer) : TIdMWayTreeNode;
  275. procedure RemoveChild(Index : Integer);
  276. end;
  277. TIdDNTreeNode = class(TIdMWayTreeNode)
  278. private
  279. FCLabel : String;
  280. FRRs: TIdTextModeRRs;
  281. FChildIndex: TStrings;
  282. FParentNode: TIdDNTreeNode;
  283. FAutoSortChild: Boolean;
  284. procedure SetCLabel(const Value: String);
  285. procedure SetRRs(const Value: TIdTextModeRRs);
  286. function GetNode(Index: integer): TIdDNTreeNode;
  287. procedure SetNode(Index: integer; const Value: TIdDNTreeNode);
  288. procedure SetChildIndex(const Value: TStrings);
  289. function GetFullName: string;
  290. function ConvertToDNString : string;
  291. function DumpAllBinaryData(var RecordCount:integer) : TIdBytes;
  292. public
  293. property ParentNode : TIdDNTreeNode read FParentNode write FParentNode;
  294. property CLabel : String read FCLabel write SetCLabel;
  295. property RRs : TIdTextModeRRs read FRRs write SetRRs;
  296. property Children[Index : Integer] : TIdDNTreeNode read GetNode write SetNode;
  297. property ChildIndex : TStrings read FChildIndex write SetChildIndex;
  298. property AutoSortChild : Boolean read FAutoSortChild write FAutoSortChild;
  299. property FullName : string read GetFullName;
  300. constructor Create(AParentNode : TIdDNTreeNode); reintroduce;
  301. destructor Destroy; override;
  302. function AddChild : TIdDNTreeNode;
  303. function InsertChild(Index : Integer) : TIdDNTreeNode;
  304. procedure RemoveChild(Index : Integer);
  305. procedure SortChildren;
  306. procedure Clear;
  307. procedure SaveToFile(Filename : String);
  308. function IndexByLabel(CLabel : String): Integer;
  309. function IndexByNode(ANode : TIdDNTreeNode) : Integer;
  310. end;
  311. TIdDNS_TCPServer = class(TIdCustomTCPServer)
  312. protected
  313. FAccessList: TStrings;
  314. FAccessControl: Boolean;
  315. //
  316. procedure DoConnect(AContext: TIdContext); override;
  317. procedure SetAccessList(const Value: TStrings);
  318. public
  319. constructor Create(AOwner: TComponent); override;
  320. destructor Destroy; override;
  321. published
  322. property AccessList : TStrings read FAccessList write SetAccessList;
  323. property AccessControl : boolean read FAccessControl write FAccessControl;
  324. end;
  325. TIdDNS_ProcessThread = class(TIdThread)
  326. protected
  327. FMyBinding: TIdSocketHandle;
  328. FMainBinding: TIdSocketHandle;
  329. FMyData: TStream;
  330. FData : TIdBytes;
  331. FServer: TIdDNS_UDPServer;
  332. procedure SetMyBinding(const Value: TIdSocketHandle);
  333. procedure SetMyData(const Value: TStream);
  334. procedure SetServer(const Value: TIdDNS_UDPServer);
  335. procedure ComposeErrorResult(var VFinal: TIdBytes; OriginalHeader: TDNSHeader;
  336. OriginalQuestion : TIdBytes; ErrorStatus: Integer);
  337. function CombineAnswer(Header : TDNSHeader; const EQuery, Answer : TIdBytes): TIdBytes;
  338. procedure InternalSearch(Header: TDNSHeader; QName: string; QType: UInt16;
  339. var Answer: TIdBytes; IfMainQuestion: Boolean; IsSearchCache: Boolean = False;
  340. IsAdditional: Boolean = False; IsWildCard : Boolean = False;
  341. WildCardOrgName: string = '');
  342. procedure ExternalSearch(ADNSResolver: TIdDNSResolver; Header: TDNSHeader;
  343. Question: TIdBytes; var Answer: TIdBytes);
  344. function CompleteQuery(DNSHeader: TDNSHeader; Question: string;
  345. OriginalQuestion: TIdBytes; var Answer : TIdBytes; QType, QClass : UInt16;
  346. DNSResolver : TIdDNSResolver) : string;
  347. procedure SaveToCache(ResourceRecord : TIdBytes; QueryName : string; OriginalQType : UInt16);
  348. function SearchTree(Root : TIdDNTreeNode; QName : String; QType : UInt16): TIdDNTreeNode;
  349. procedure Run; override;
  350. procedure QueryDomain;
  351. procedure SendData;
  352. public
  353. property MyBinding : TIdSocketHandle read FMyBinding write SetMyBinding;
  354. property MyData: TStream read FMyData write SetMyData;
  355. property Server : TIdDNS_UDPServer read FServer write SetServer;
  356. constructor Create(ACreateSuspended: Boolean = True; Data : TIdBytes = nil;
  357. MainBinding : TIdSocketHandle = nil; Binding : TIdSocketHandle = nil;
  358. Server : TIdDNS_UDPServer = nil); reintroduce; overload;
  359. destructor Destroy; override;
  360. end;
  361. TIdDNSBeforeQueryEvent = procedure(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader; var ADNSQuery: TIdBytes) of object;
  362. TIdDNSAfterQueryEvent = procedure(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader; var QueryResult: TIdBytes; var ResultCode: string; Query : TIdBytes) of object;
  363. TIdDNSAfterCacheSaved = procedure(CacheRoot : TIdDNTreeNode) of object;
  364. TIdDNS_UDPServer = class(TIdUDPServer)
  365. private
  366. FBusy: Boolean;
  367. protected
  368. FAutoUpdateZoneInfo: Boolean;
  369. FZoneMasterFiles: TStrings;
  370. FRootDNS_NET: TStrings;
  371. FCacheUnknowZone: Boolean;
  372. FCached_Tree: TIdDNTreeNode;
  373. FHanded_Tree: TIdDNTreeNode;
  374. FHanded_DomainList: TStrings;
  375. FAutoLoadMasterFile: Boolean;
  376. FOnAfterQuery: TIdDNSAfterQueryEvent;
  377. FOnBeforeQuery: TIdDNSBeforeQueryEvent;
  378. FCS: TIdCriticalSection;
  379. FOnAfterSendBack: TIdDNSAfterQueryEvent;
  380. FOnAfterCacheSaved: TIdDNSAfterCacheSaved;
  381. FGlobalCS: TIdCriticalSection;
  382. FDNSVersion: string;
  383. FofferDNSVersion: Boolean;
  384. procedure DoBeforeQuery(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader;
  385. var ADNSQuery : TIdBytes); dynamic;
  386. procedure DoAfterQuery(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader;
  387. var QueryResult : TIdBytes; var ResultCode : String; Query : TIdBytes); dynamic;
  388. procedure DoAfterSendBack(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader;
  389. var QueryResult : TIdBytes; var ResultCode : String; Query : TIdBytes); dynamic;
  390. procedure DoAfterCacheSaved(CacheRoot : TIdDNTreeNode); dynamic;
  391. procedure SetZoneMasterFiles(const Value: TStrings);
  392. procedure SetRootDNS_NET(const Value: TStrings);
  393. procedure SetHanded_DomainList(const Value: TStrings);
  394. procedure InternalSearch(Header: TDNSHeader; QName: string; QType: UInt16;
  395. var Answer: TIdBytes; IfMainQuestion: boolean; IsSearchCache: Boolean = False;
  396. IsAdditional: Boolean = False; IsWildCard : Boolean = False;
  397. WildCardOrgName: string = '');
  398. procedure ExternalSearch(ADNSResolver: TIdDNSResolver; Header: TDNSHeader;
  399. Question: TIdBytes; var Answer: TIdBytes);
  400. //modified in May 2004 by Dennies Chang.
  401. //procedure SaveToCache(ResourceRecord : string);
  402. procedure SaveToCache(ResourceRecord : TIdBytes; QueryName : string; OriginalQType : UInt16);
  403. //procedure UpdateTree(TreeRoot : TIdDNTreeNode; RR : TResultRecord); overload;
  404. //MoveTo Public section for RaidenDNSD.
  405. // Hide this property temporily, this property is prepared to maintain the
  406. // TTL expired record auto updated;
  407. property AutoUpdateZoneInfo : boolean read FAutoUpdateZoneInfo write FAutoUpdateZoneInfo;
  408. property CS: TIdCriticalSection read FCS;
  409. procedure DoUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); override;
  410. public
  411. constructor Create(AOwner: TComponent); override;
  412. destructor Destroy; override;
  413. function AXFR(Header : TDNSHeader; Question : string; var Answer : TIdBytes) : string;
  414. function LoadZoneFromMasterFile(MasterFileName : String) : boolean;
  415. function LoadZoneStrings(FileStrings: TStrings; Filename : String;
  416. TreeRoot : TIdDNTreeNode): Boolean;
  417. function SearchTree(Root : TIdDNTreeNode; QName : String; QType : UInt16): TIdDNTreeNode;
  418. procedure UpdateTree(TreeRoot : TIdDNTreeNode; RR : TIdTextModeResourceRecord); overload;
  419. function FindNodeFullName(Root : TIdDNTreeNode; QName : String; QType : UInt16) : string;
  420. function FindHandedNodeByName(QName : String; QType : UInt16) : TIdDNTreeNode;
  421. procedure UpdateTree(TreeRoot : TIdDNTreeNode; RR : TResultRecord); overload;
  422. property RootDNS_NET : TStrings read FRootDNS_NET write SetRootDNS_NET;
  423. property Cached_Tree : TIdDNTreeNode read FCached_Tree {write SetCached_Tree};
  424. property Handed_Tree : TIdDNTreeNode read FHanded_Tree {write SetHanded_Tree};
  425. property Busy : Boolean read FBusy;
  426. property GlobalCS : TIdCriticalSection read FGlobalCS;
  427. published
  428. property DefaultPort default IdPORT_DOMAIN;
  429. property AutoLoadMasterFile : Boolean read FAutoLoadMasterFile write FAutoLoadMasterFile Default False;
  430. //property AutoUpdateZoneInfo : boolean read FAutoUpdateZoneInfo write SetAutoUpdateZoneInfo;
  431. property ZoneMasterFiles : TStrings read FZoneMasterFiles write SetZoneMasterFiles;
  432. property CacheUnknowZone : Boolean read FCacheUnknowZone write FCacheUnknowZone default False;
  433. property Handed_DomainList : TStrings read FHanded_DomainList write SetHanded_DomainList;
  434. property DNSVersion : string read FDNSVersion write FDNSVersion;
  435. property offerDNSVersion : Boolean read FofferDNSVersion write FofferDNSVersion;
  436. property OnBeforeQuery : TIdDNSBeforeQueryEvent read FOnBeforeQuery write FOnBeforeQuery;
  437. property OnAfterQuery : TIdDNSAfterQueryEvent read FOnAfterQuery write FOnAfterQuery;
  438. property OnAfterSendBack : TIdDNSAfterQueryEvent read FOnAfterSendBack write FOnAfterSendBack;
  439. property OnAfterCacheSaved : TIdDNSAfterCacheSaved read FOnAfterCacheSaved write FOnAfterCacheSaved;
  440. end;
  441. TIdDNSServer = class(TIdComponent)
  442. protected
  443. FActive: Boolean;
  444. FTCPACLActive: Boolean;
  445. FServerType: TDNSServerTypes;
  446. FTCPTunnel: TIdDNS_TCPServer;
  447. FUDPTunnel: TIdDNS_UDPServer;
  448. FAccessList: TStrings;
  449. FBindings: TIdSocketHandles;
  450. procedure SetAccessList(const Value: TStrings);
  451. procedure SetActive(const Value: Boolean);
  452. procedure SetTCPACLActive(const Value: Boolean);
  453. procedure SetBindings(const Value: TIdSocketHandles);
  454. procedure TimeToUpdateNodeData(Sender : TObject);
  455. public
  456. BackupDNSMap : TIdDNSMap;
  457. constructor Create(AOwner: TComponent); override;
  458. destructor Destroy; override;
  459. procedure CheckIfExpire(Sender: TObject);
  460. published
  461. property Active : Boolean read FActive write SetActive;
  462. property AccessList : TStrings read FAccessList write SetAccessList;
  463. property Bindings: TIdSocketHandles read FBindings write SetBindings;
  464. property TCPACLActive : Boolean read FTCPACLActive write SetTCPACLActive;
  465. property ServerType: TDNSServerTypes read FServerType write FServerType;
  466. property TCPTunnel : TIdDNS_TCPServer read FTCPTunnel write FTCPTunnel;
  467. property UDPTunnel : TIdDNS_UDPServer read FUDPTunnel write FUDPTunnel;
  468. end;
  469. implementation
  470. uses
  471. {$IFDEF DCC_XE3_OR_ABOVE}
  472. {$IFNDEF NEXTGEN}
  473. System.Contnrs,
  474. {$ENDIF}
  475. System.SyncObjs,
  476. System.Types,
  477. {$ENDIF}
  478. IdException,
  479. {$IFDEF USE_VCL_POSIX}
  480. Posix.SysSelect,
  481. Posix.SysTime,
  482. {$ENDIF}
  483. IdIOHandler,
  484. IdStack,
  485. SysUtils;
  486. {Common Utilities}
  487. function CompareItems(Item1, Item2: {$IFDEF HAS_GENERICS_TObjectList}TIdMWayTreeNode{$ELSE}TObject{$ENDIF}): Integer;
  488. var
  489. LObj1, LObj2 : TIdDNTreeNode;
  490. begin
  491. LObj1 := Item1 as TIdDNTreeNode;
  492. LObj2 := Item2 as TIdDNTreeNode;
  493. Result := CompareStr(LObj1.CLabel, LObj2.CLabel);
  494. end;
  495. // TODO: move to IdGlobal.pas
  496. function PosBytes(const SubBytes, SBytes: TIdBytes): Integer;
  497. var
  498. LSubLen, LBytesLen, I: Integer;
  499. begin
  500. LSubLen := Length(SubBytes);
  501. LBytesLen := Length(SBytes);
  502. if (LSubLen > 0) and (LBytesLen >= LSubLen) then
  503. begin
  504. for Result := 0 to LBytesLen-LSubLen do
  505. begin
  506. if SBytes[Result] = SubBytes[0] then
  507. begin
  508. for I := 1 to LSubLen-1 do
  509. begin
  510. if SBytes[Result+I] <> SubBytes[I] then begin
  511. Break;
  512. end;
  513. end;
  514. if I = LSubLen then begin
  515. Exit;
  516. end;
  517. end;
  518. end;
  519. end;
  520. Result := -1;
  521. end;
  522. // TODO: move to IdGlobal.pas
  523. function FetchBytes(var AInput: TIdBytes; const ADelim: TIdBytes;
  524. const ADelete: Boolean = IdFetchDeleteDefault): TIdBytes;
  525. var
  526. LPos: integer;
  527. begin
  528. LPos := PosBytes(ADelim, AInput);
  529. if LPos = -1 then begin
  530. Result := AInput;
  531. if ADelete then begin
  532. SetLength(AInput, 0);
  533. end;
  534. end
  535. else begin
  536. Result := ToBytes(AInput, LPos);
  537. if ADelete then begin
  538. //slower Delete(AInput, 1, LPos + Length(ADelim) - 1);
  539. RemoveBytes(AInput, LPos + Length(ADelim));
  540. end;
  541. end;
  542. end;
  543. { TIdMWayTreeNode }
  544. function TIdMWayTreeNode.AddChild: TIdMWayTreeNode;
  545. begin
  546. Result := FundmentalClass.Create(FundmentalClass);
  547. try
  548. SubTree.Add(Result);
  549. except
  550. Result.Free;
  551. raise;
  552. end;
  553. end;
  554. constructor TIdMWayTreeNode.Create(NodeClass : TIdMWayTreeNodeClass);
  555. begin
  556. inherited Create;
  557. FundmentalClass := NodeClass;
  558. SubTree := TIdObjectList{$IFDEF HAS_GENERICS_TObjectList}<TIdMWayTreeNode>{$ENDIF}.Create;
  559. end;
  560. destructor TIdMWayTreeNode.Destroy;
  561. begin
  562. SubTree.Free;
  563. inherited Destroy;
  564. end;
  565. function TIdMWayTreeNode.GetTreeNode(Index: Integer): TIdMWayTreeNode;
  566. begin
  567. Result := {$IFDEF HAS_GENERICS_TObjectList}SubTree.Items[Index]{$ELSE}TIdMWayTreeNode(SubTree.Items[Index]){$ENDIF};
  568. end;
  569. function TIdMWayTreeNode.InsertChild(Index: Integer): TIdMWayTreeNode;
  570. begin
  571. Result := FundmentalClass.Create(FundmentalClass);
  572. try
  573. SubTree.Insert(Index, Result);
  574. except
  575. Result.Free;
  576. raise;
  577. end;
  578. end;
  579. procedure TIdMWayTreeNode.RemoveChild(Index: Integer);
  580. begin
  581. SubTree.Delete(Index);
  582. end;
  583. procedure TIdMWayTreeNode.SetFundmentalClass(const Value: TIdMWayTreeNodeClass);
  584. begin
  585. FFundmentalClass := Value;
  586. end;
  587. procedure TIdMWayTreeNode.SetTreeNode(Index: Integer; const Value: TIdMWayTreeNode);
  588. begin
  589. {$IFNDEF USE_OBJECT_ARC}
  590. SubTree.Items[Index].Free;
  591. {$ENDIF}
  592. SubTree.Items[Index] := Value;
  593. end;
  594. { TIdDNTreeNode }
  595. function TIdDNTreeNode.AddChild: TIdDNTreeNode;
  596. begin
  597. Result := TIdDNTreeNode.Create(Self);
  598. try
  599. SubTree.Add(Result);
  600. except
  601. Result.Free;
  602. raise;
  603. end;
  604. end;
  605. procedure TIdDNTreeNode.Clear;
  606. var
  607. I : Integer;
  608. begin
  609. for I := SubTree.Count - 1 downto 0 do begin
  610. RemoveChild(I);
  611. end;
  612. end;
  613. function TIdDNTreeNode.ConvertToDNString: string;
  614. var
  615. Count : Integer;
  616. begin
  617. Result := '$ORIGIN ' + FullName + EOL; {do not localize}
  618. for Count := 0 to RRs.Count-1 do begin
  619. Result := Result + RRs.Items[Count].TextRecord(FullName);
  620. end;
  621. for Count := 0 to FChildIndex.Count-1 do begin
  622. Result := Result + Children[Count].ConvertToDNString;
  623. end;
  624. end;
  625. constructor TIdDNTreeNode.Create(AParentNode : TIdDNTreeNode);
  626. begin
  627. inherited Create(TIdDNTreeNode);
  628. FRRs := TIdTextModeRRs.Create;
  629. FChildIndex := TStringList.Create;
  630. FParentNode := AParentNode;
  631. end;
  632. destructor TIdDNTreeNode.Destroy;
  633. begin
  634. FRRs.Free;
  635. FChildIndex.Free;
  636. inherited Destroy;
  637. end;
  638. function TIdDNTreeNode.DumpAllBinaryData(var RecordCount: Integer): TIdBytes;
  639. var
  640. Count, ChildCount : integer;
  641. MyString, ChildString : TIdBytes;
  642. begin
  643. SetLength(ChildString, 0);
  644. SetLength(MyString, 0);
  645. Inc(RecordCount, RRs.Count + 1);
  646. for Count := 0 to RRs.Count -1 do
  647. begin
  648. AppendBytes(MyString, RRs.Items[Count].BinQueryRecord(FullName));
  649. end;
  650. for Count := 0 to FChildIndex.Count -1 do
  651. begin
  652. // RLebeau: should ChildCount be set to 0 each time?
  653. AppendBytes(ChildString, Children[Count].DumpAllBinaryData(ChildCount));
  654. Inc(RecordCount, ChildCount);
  655. end;
  656. if RRs.Count > 0 then begin
  657. if RRs.Items[0] is TIdRR_SOA then begin
  658. AppendBytes(MyString, RRs.Items[0].BinQueryRecord(FullName));
  659. Inc(RecordCount);
  660. end;
  661. end;
  662. Result := MyString;
  663. AppendBytes(Result, ChildString);
  664. if RRs.Count > 0 then begin
  665. AppendBytes(Result, RRs.Items[0].BinQueryRecord(FullName));
  666. end;
  667. end;
  668. function TIdDNTreeNode.GetFullName: string;
  669. begin
  670. if ParentNode = nil then begin
  671. if CLabel = '.' then begin
  672. Result := '';
  673. end else begin
  674. Result := CLabel;
  675. end;
  676. end else begin
  677. Result := CLabel + '.' + ParentNode.FullName;
  678. end;
  679. end;
  680. function TIdDNTreeNode.GetNode(Index: Integer): TIdDNTreeNode;
  681. begin
  682. Result := TIdDNTreeNode(SubTree.Items[Index]);
  683. end;
  684. function TIdDNTreeNode.IndexByLabel(CLabel: String): Integer;
  685. begin
  686. Result := FChildIndex.IndexOf(CLabel);
  687. end;
  688. function TIdDNTreeNode.IndexByNode(ANode: TIdDNTreeNode): Integer;
  689. begin
  690. Result := SubTree.IndexOf(ANode);
  691. end;
  692. function TIdDNTreeNode.InsertChild(Index: Integer): TIdDNTreeNode;
  693. begin
  694. Result := TIdDNTreeNode.Create(Self);
  695. try
  696. SubTree.Insert(Index, Result);
  697. except
  698. Result.Free;
  699. raise;
  700. end;
  701. end;
  702. procedure TIdDNTreeNode.RemoveChild(Index: Integer);
  703. begin
  704. SubTree.Remove(SubTree.Items[Index]);
  705. FChildIndex.Delete(Index);
  706. end;
  707. procedure TIdDNTreeNode.SaveToFile(Filename: String);
  708. var
  709. DNSs : TStrings;
  710. begin
  711. DNSs := TStringList.Create;
  712. try
  713. DNSs.Add(ConvertToDNString);
  714. ToDo('SaveToFile() method of TIdDNTreeNode class is not implemented yet'); {do not localized}
  715. // DNSs.SaveToFile(Filename);
  716. finally
  717. DNSs.Free;
  718. end;
  719. end;
  720. procedure TIdDNTreeNode.SetChildIndex(const Value: TStrings);
  721. begin
  722. FChildIndex.Assign(Value);
  723. end;
  724. procedure TIdDNTreeNode.SetCLabel(const Value: String);
  725. begin
  726. FCLabel := Value;
  727. if ParentNode <> nil then begin
  728. ParentNode.ChildIndex.Insert(ParentNode.SubTree.IndexOf(Self), Value);
  729. end;
  730. if AutoSortChild then begin
  731. SortChildren;
  732. end;
  733. end;
  734. procedure TIdDNTreeNode.SetNode(Index: Integer; const Value: TIdDNTreeNode);
  735. begin
  736. SubTree.Items[Index] := Value;
  737. end;
  738. procedure TIdDNTreeNode.SetRRs(const Value: TIdTextModeRRs);
  739. begin
  740. FRRs.Assign(Value);
  741. end;
  742. procedure TIdDNTreeNode.SortChildren;
  743. begin
  744. SubTree.BubbleSort(CompareItems);
  745. TStringList(FChildIndex).Sort;
  746. end;
  747. { TIdDNSServer }
  748. constructor TIdDNS_UDPServer.Create(AOwner: TComponent);
  749. begin
  750. inherited Create(AOwner);
  751. FRootDNS_NET := TStringList.Create;
  752. FRootDNS_NET.Add('209.92.33.150'); // nic.net {do not localize}
  753. FRootDNS_NET.Add('209.92.33.130'); // nic.net {do not localize}
  754. FRootDNS_NET.Add('203.37.255.97'); // apnic.net {do not localize}
  755. FRootDNS_NET.Add('202.12.29.131'); // apnic.net {do not localize}
  756. FRootDNS_NET.Add('12.29.20.2'); // nanic.net {do not localize}
  757. FRootDNS_NET.Add('204.145.119.2'); // nanic.net {do not localize}
  758. FRootDNS_NET.Add('140.111.1.2'); // a.twnic.net.tw {do not localize}
  759. FCached_Tree := TIdDNTreeNode.Create(nil);
  760. FCached_Tree.AutoSortChild := True;
  761. FCached_Tree.CLabel := '.';
  762. FHanded_Tree := TIdDNTreeNode.Create(nil);
  763. FHanded_Tree.AutoSortChild := True;
  764. FHanded_Tree.CLabel := '.';
  765. FHanded_DomainList := TStringList.Create;
  766. FZoneMasterFiles := TStringList.Create;
  767. DefaultPort := IdPORT_DOMAIN;
  768. FCS := TIdCriticalSection.Create;
  769. FGlobalCS := TIdCriticalSection.Create;
  770. FBusy := False;
  771. end;
  772. destructor TIdDNS_UDPServer.Destroy;
  773. begin
  774. FCached_Tree.Free;
  775. FHanded_Tree.Free;
  776. FRootDNS_NET.Free;
  777. FHanded_DomainList.Free;
  778. FZoneMasterFiles.Free;
  779. FCS.Free;
  780. FGlobalCS.Free;
  781. inherited Destroy;
  782. end;
  783. procedure TIdDNS_UDPServer.DoAfterQuery(ABinding: TIdSocketHandle;
  784. ADNSHeader: TDNSHeader; var QueryResult: TIdBytes; var ResultCode : String;
  785. Query : TIdBytes);
  786. begin
  787. if Assigned(FOnAfterQuery) then begin
  788. FOnAfterQuery(ABinding, ADNSHeader, QueryResult, ResultCode, Query);
  789. end;
  790. end;
  791. procedure TIdDNS_UDPServer.DoBeforeQuery(ABinding: TIdSocketHandle;
  792. ADNSHeader: TDNSHeader; var ADNSQuery: TIdBytes);
  793. begin
  794. if Assigned(FOnBeforeQuery) then begin
  795. FOnBeforeQuery(ABinding, ADNSHeader, ADNSQuery);
  796. end;
  797. end;
  798. procedure TIdDNS_UDPServer.ExternalSearch(ADNSResolver : TIdDNSResolver;
  799. Header: TDNSHeader; Question: TIdBytes; var Answer: TIdBytes);
  800. var
  801. Server_Index : Integer;
  802. MyDNSResolver : TIdDNSResolver;
  803. begin
  804. if RootDNS_NET.Count = 0 then begin
  805. Exit;
  806. end;
  807. Server_Index := 0;
  808. if ADNSResolver = nil then begin
  809. MyDNSResolver := TIdDNSResolver.Create;
  810. MyDNSResolver.WaitingTime := 5000;
  811. end else begin
  812. MyDNSResolver := ADNSResolver;
  813. end;
  814. try
  815. repeat
  816. MyDNSResolver.Host := RootDNS_NET.Strings[Server_Index];
  817. try
  818. MyDNSResolver.InternalQuery := Question;
  819. MyDNSResolver.Resolve('');
  820. Answer := MyDNSResolver.PlainTextResult;
  821. except
  822. // Todo: Create DNS server interal resolver error.
  823. on EIdDnsResolverError do begin
  824. //Empty Event, for user to custom the event handle.
  825. end;
  826. on EIdSocketError do begin
  827. end;
  828. else
  829. begin
  830. end;
  831. end;
  832. Inc(Server_Index);
  833. until (Server_Index >= RootDNS_NET.Count) or (Answer <> nil);
  834. finally
  835. if ADNSResolver = nil then begin
  836. MyDNSResolver.Free;
  837. end;
  838. end;
  839. end;
  840. function TIdDNS_UDPServer.FindHandedNodeByName(QName: String; QType: UInt16): TIdDNTreeNode;
  841. begin
  842. Result := SearchTree(Handed_Tree, QName, QType);
  843. end;
  844. function TIdDNS_UDPServer.FindNodeFullName(Root: TIdDNTreeNode; QName: String; QType : UInt16): string;
  845. var
  846. MyNode : TIdDNTreeNode;
  847. begin
  848. MyNode := SearchTree(Root, QName, QType);
  849. if MyNode <> nil then begin
  850. Result := MyNode.FullName;
  851. end else begin
  852. Result := '';
  853. end;
  854. end;
  855. function TIdDNS_UDPServer.LoadZoneFromMasterFile(MasterFileName: String): Boolean;
  856. var
  857. FileStrings : TStrings;
  858. begin
  859. {MakeTagList;}
  860. Result := FileExists(MasterFileName);
  861. if Result then begin
  862. FileStrings := TStringList.Create;
  863. try
  864. Todo('LoadZoneFromMasterFile() method of TIdDNS_UDPServer class is not implemented yet'); {do not localize}
  865. // FileStrings.LoadFromFile(MasterFileName);
  866. Result := LoadZoneStrings(FileStrings, MasterFileName, Handed_Tree);
  867. finally
  868. FileStrings.Free;
  869. end;
  870. end;
  871. {FreeTagList;}
  872. end;
  873. function TIdDNS_UDPServer.LoadZoneStrings(FileStrings: TStrings; Filename : String;
  874. TreeRoot : TIdDNTreeNode): Boolean;
  875. var
  876. TagList : TStrings;
  877. function IsMSDNSFileName(theFileName : String; var DN: string) : Boolean;
  878. var
  879. namepart : TStrings;
  880. Fullname : string;
  881. Count : Integer;
  882. begin
  883. Fullname := theFilename;
  884. repeat
  885. if Pos('\', Fullname) > 0 then begin
  886. Fetch(Fullname, '\');
  887. end;
  888. until Pos('\', Fullname) = 0;
  889. namepart := TStringList.Create;
  890. try
  891. repeat
  892. namepart.Add(Fetch(Fullname, '.'));
  893. until Fullname = '';
  894. Result := namepart.Strings[namepart.Count-1] = 'dns'; {do not localize}
  895. if Result then begin
  896. Count := 0;
  897. DN := namepart.Strings[Count];
  898. repeat
  899. Inc(Count);
  900. if Count <= namepart.Count -2 then begin
  901. DN := DN + '.' + namepart.Strings[Count];
  902. end;
  903. until Count >= (namepart.Count-2);
  904. end;
  905. finally
  906. namepart.Free;
  907. end;
  908. end;
  909. procedure MakeTagList;
  910. begin
  911. TagList := TStringList.Create;
  912. try
  913. TagList.Add(cAAAA);
  914. TagList.Add(cA);
  915. TagList.Add(cNS);
  916. TagList.Add(cMD);
  917. TagList.Add(cMF);
  918. TagList.Add(cCName);
  919. TagList.Add(cSOA);
  920. TagList.Add(cMB);
  921. TagList.Add(cMG);
  922. TagList.Add(cMR);
  923. TagList.Add(cNULL);
  924. TagList.Add(cWKS);
  925. TagList.Add(cPTR);
  926. TagList.Add(cHINFO);
  927. TagList.Add(cMINFO);
  928. TagList.Add(cMX);
  929. TagList.Add(cTXT);
  930. // The Following Tags are used in master file, but not Resource Record.
  931. TagList.Add(cOrigin);
  932. TagList.Add(cInclude);
  933. //TagList.Add(cAt);
  934. except
  935. TagList.Free;
  936. raise;
  937. end;
  938. end;
  939. procedure FreeTagList;
  940. begin
  941. FreeAndNil(TagList);
  942. end;
  943. function ClearDoubleQutoa(Strs : TStrings): Boolean;
  944. var
  945. SSCount : Integer;
  946. Mark, Found : Boolean;
  947. begin
  948. SSCount := 0;
  949. Mark := False;
  950. while SSCount <= (Strs.Count-1) do begin
  951. Found := Pos('"', Strs.Strings[SSCount]) > 0;
  952. while Found do begin
  953. Mark := Mark xor Found;
  954. Strs.Strings[SSCount] := ReplaceSpecString(Strs.Strings[SSCount], '"', '', False);
  955. Found := Pos('"', Strs.Strings[SSCount]) > 0;
  956. end;
  957. if not Mark then begin
  958. Inc(SSCount);
  959. end else begin
  960. Strs.Strings[SSCount] := Strs.Strings[SSCount] + ' ' + Strs.Strings[SSCount + 1];
  961. Strs.Delete(SSCount + 1);
  962. end;
  963. end;
  964. Result := not Mark;
  965. end;
  966. function IsValidMasterFile : Boolean;
  967. var
  968. EachLinePart : TStrings;
  969. CurrentLineNum, TagField, Count : Integer;
  970. LineData, DataBody, {Comment,} FPart, LTag : string;
  971. Denoted, Stop, PassQuota : Boolean;
  972. begin
  973. EachLinePart := TStringList.Create;
  974. try
  975. CurrentLineNum := 0;
  976. Stop := False;
  977. // Check Denoted;
  978. Denoted := false;
  979. if FileStrings.Count > 0 then begin
  980. repeat
  981. LineData := Trim(FileStrings.Strings[CurrentLineNum]);
  982. DataBody := Fetch(LineData, ';');
  983. //Comment := LineData;
  984. PassQuota := Pos('(', DataBody) = 0;
  985. // Split each item into TStrings.
  986. repeat
  987. if not PassQuota then begin
  988. Inc(CurrentLineNum);
  989. LineData := Trim(FileStrings.Strings[CurrentLineNum]);
  990. DataBody := DataBody + ' ' + Fetch(LineData, ';');
  991. PassQuota := Pos(')', DataBody) > 0;
  992. end;
  993. until PassQuota or (CurrentLineNum > (FileStrings.Count-1));
  994. Stop := not PassQuota;
  995. if not Stop then begin
  996. EachLinePart.Clear;
  997. DataBody := ReplaceSpecString(DataBody, '(', '');
  998. DataBody := ReplaceSpecString(DataBody, ')', '');
  999. repeat
  1000. DataBody := Trim(DataBody);
  1001. FPart := Fetch(DataBody, #9);
  1002. repeat
  1003. FPart := Trim(FPart);
  1004. LTag := Fetch(FPart,' ');
  1005. if (LTag <> '') and (LTag <> '(') and (LTag <> ')') then begin
  1006. EachLinePart.Add(LTag);
  1007. end;
  1008. until FPart = '';
  1009. until DataBody = '';
  1010. if not Denoted then begin
  1011. if EachLinePart.Count > 1 then begin
  1012. Denoted := (EachLinePart.Strings[0] = cOrigin) or (EachLinePart.IndexOf(cSOA) <> -1);
  1013. end else begin
  1014. Denoted := False;
  1015. end;
  1016. end;
  1017. // Check Syntax;
  1018. if not ((EachLinePart.Count > 0) and (EachLinePart.Strings[0] = cOrigin)) then
  1019. begin
  1020. if not Denoted then begin
  1021. if EachLinePart.Count > 0 then begin
  1022. Stop := (EachLinePart.Count > 0) and (EachLinePart.IndexOf(cSOA) = -1);
  1023. end else begin
  1024. Stop := False;
  1025. end;
  1026. end else begin
  1027. //TagField := -1;
  1028. //FieldCount := 0;
  1029. // Search Tag Named 'IN';
  1030. TagField := EachLinePart.IndexOf('IN'); {do not localize}
  1031. if TagField = -1 then begin
  1032. Count := 0;
  1033. repeat
  1034. if EachLinePart.Count > 0 then begin
  1035. TagField := TagList.IndexOf(EachLinePart.Strings[Count]);
  1036. end;
  1037. Inc(Count);
  1038. until (Count >= EachLinePart.Count -1) or (TagField <> -1);
  1039. if TagField <> -1 then begin
  1040. TagField := Count;
  1041. end;
  1042. end else begin
  1043. if TagList.IndexOf(EachLinePart.Strings[TagField + 1]) = -1 then begin
  1044. TagField := -1;
  1045. end else begin
  1046. Inc(TagField);
  1047. end;
  1048. end;
  1049. if TagField > -1 then begin
  1050. case TagList.IndexOf(EachLinePart.Strings[TagField]) of
  1051. // Check ip
  1052. TypeCode_A : Stop := not IsValidIP(EachLinePart.Strings[TagField + 1]);
  1053. // Check ip v6
  1054. 0 : Stop := not IsValidIPv6(EachLinePart.Strings[TagField + 1]);
  1055. // Check Domain Name
  1056. TypeCode_CName, TypeCode_NS, TypeCode_MR,
  1057. TypeCode_MD, TypeCode_MB, TypeCode_MG,
  1058. TypeCode_MF: Stop := not IsHostName(EachLinePart.Strings[TagField + 1]);
  1059. // Can be anything
  1060. TypeCode_TXT, TypeCode_NULL: Stop := False;
  1061. // Must be FQDN.
  1062. TypeCode_PTR: Stop := not IsFQDN(EachLinePart.Strings[TagField + 1]);
  1063. // HINFO should has 2 fields : CPU and OS. but TStrings
  1064. // is 0 base, so that we have to minus one
  1065. TypeCode_HINFO:
  1066. begin
  1067. Stop := not (ClearDoubleQutoa(EachLinePart) and
  1068. ((EachLinePart.Count - TagField - 1) = 2));
  1069. end;
  1070. // Check RMailBX and EMailBX but TStrings
  1071. // is 0 base, so that we have to minus one
  1072. TypeCode_MINFO:
  1073. begin
  1074. Stop := ((EachLinePart.Count - TagField - 1) <> 2);
  1075. if not Stop then begin
  1076. Stop := not (IsHostName(EachLinePart.Strings[TagField + 1]) and
  1077. IsHostName(EachLinePart.Strings[TagField + 2]));
  1078. end;
  1079. end;
  1080. // Check Pref(Numeric) and Exchange. but TStrings
  1081. // is 0 base, so that we have to minus one
  1082. TypeCode_MX:
  1083. begin
  1084. Stop := ((EachLinePart.Count - TagField - 1) <> 2);
  1085. if not Stop then begin
  1086. Stop := not (IsNumeric(EachLinePart.Strings[TagField + 1]) and
  1087. IsHostName(EachLinePart.Strings[TagField + 2]));
  1088. end;
  1089. end;
  1090. // TStrings is 0 base, so that we have to minus one
  1091. TypeCode_SOA:
  1092. begin
  1093. Stop := ((EachLinePart.Count - TagField - 1) <> 7);
  1094. if not Stop then begin
  1095. Stop := not (IsHostName(EachLinePart.Strings[TagField + 1]) and
  1096. IsHostName(EachLinePart.Strings[TagField + 2]) and
  1097. IsNumeric(EachLinePart.Strings[TagField + 3]) and
  1098. IsNumeric(EachLinePart.Strings[TagField + 4]) and
  1099. IsNumeric(EachLinePart.Strings[TagField + 5]) and
  1100. IsNumeric(EachLinePart.Strings[TagField + 6]) and
  1101. IsNumeric(EachLinePart.Strings[TagField + 7])
  1102. );
  1103. end;
  1104. end;
  1105. TypeCode_WKS: Stop := ((EachLinePart.Count - TagField) = 1);
  1106. end;
  1107. end else begin
  1108. if EachLinePart.Count > 0 then
  1109. Stop := True;
  1110. end;
  1111. end;
  1112. end;
  1113. end;
  1114. Inc(CurrentLineNum);
  1115. until (CurrentLineNum > (FileStrings.Count-1)) or Stop;
  1116. end;
  1117. Result := not Stop;
  1118. finally
  1119. EachLinePart.Free;
  1120. end;
  1121. end;
  1122. function LoadMasterFile : Boolean;
  1123. var
  1124. Checks, EachLinePart, DenotedDomain : TStrings;
  1125. CurrentLineNum, TagField, Count, LastTTL : Integer;
  1126. LineData, DataBody, FPart, LTag, LText,
  1127. RName, LastDenotedDomain, LastTag, NewDomain, SingleHostName {CH: , PrevDNTag} : string;
  1128. Stop, PassQuota, Found {, canChangPrevDNTag } : Boolean;
  1129. LLRR_A : TIdRR_A;
  1130. LLRR_AAAA : TIdRR_AAAA;
  1131. LLRR_NS : TIdRR_NS;
  1132. LLRR_MB : TIdRR_MB;
  1133. LLRR_Name : TIdRR_CName;
  1134. LLRR_SOA : TIdRR_SOA;
  1135. LLRR_MG : TIdRR_MG;
  1136. LLRR_MR : TIdRR_MR;
  1137. LLRR_PTR : TIdRR_PTR;
  1138. LLRR_HINFO : TIdRR_HINFO;
  1139. LLRR_MINFO : TIdRR_MINFO;
  1140. LLRR_MX : TIdRR_MX;
  1141. LLRR_TXT : TIdRR_TXT;
  1142. begin
  1143. EachLinePart := TStringList.Create;
  1144. try
  1145. DenotedDomain := TStringList.Create;
  1146. try
  1147. CurrentLineNum := 0;
  1148. LastDenotedDomain := '';
  1149. LastTag := '';
  1150. NewDomain := '';
  1151. // PrevDNTag := '';
  1152. Stop := False;
  1153. //canChangPrevDNTag := True;
  1154. if IsMSDNSFileName(FileName, LastDenotedDomain) then begin
  1155. //canChangPrevDNTag := False;
  1156. Filename := Uppercase(Filename);
  1157. end else begin
  1158. LastDenotedDomain := '';
  1159. end;
  1160. if FileStrings.Count > 0 then begin
  1161. repeat
  1162. LineData := Trim(FileStrings.Strings[CurrentLineNum]);
  1163. DataBody := Fetch(LineData, ';');
  1164. // Comment := LineData;
  1165. PassQuota := Pos('(', DataBody) = 0;
  1166. // Split each item into TStrings.
  1167. repeat
  1168. if not PassQuota then begin
  1169. Inc(CurrentLineNum);
  1170. LineData := Trim(FileStrings.Strings[CurrentLineNum]);
  1171. DataBody := DataBody + ' ' + Fetch(LineData, ';');
  1172. PassQuota := Pos(')', DataBody) > 0;
  1173. end;
  1174. until PassQuota;
  1175. EachLinePart.Clear;
  1176. DataBody := ReplaceSpecString(DataBody, '(', '');
  1177. DataBody := ReplaceSpecString(DataBody, ')', '');
  1178. repeat
  1179. DataBody := Trim(DataBody);
  1180. FPart := Fetch(DataBody, #9);
  1181. repeat
  1182. FPart := Trim(FPart);
  1183. if Pos('"', FPart) = 1 then begin
  1184. Fetch(FPart, '"');
  1185. LText := Fetch(FPart, '"');
  1186. EachLinePart.Add(LText);
  1187. end;
  1188. LTag := Fetch(FPart, ' ');
  1189. if (TagList.IndexOf(LTag) = -1) and (LTag <> 'IN') then begin {do not localize}
  1190. LTag := LowerCase(LTag);
  1191. end;
  1192. if (LTag <> '') and (LTag <> '(') and (LTag <> ')') then begin
  1193. EachLinePart.Add(LTag);
  1194. end;
  1195. until FPart = '';
  1196. until DataBody = '';
  1197. if EachLinePart.Count > 0 then begin
  1198. if EachLinePart.Strings[0] = cOrigin then begin
  1199. // One Domain is found.
  1200. NewDomain := EachLinePart.Strings[1];
  1201. if TextEndsWith(NewDomain, '.') then begin
  1202. LastDenotedDomain := NewDomain;
  1203. NewDomain := '';
  1204. end else begin
  1205. LastDenotedDomain := NewDomain + '.' + LastDenotedDomain;
  1206. NewDomain := '';
  1207. end;
  1208. end else begin
  1209. // Search RR Type Tag;
  1210. Count := 0;
  1211. TagField := -1;
  1212. repeat
  1213. Found := TagList.IndexOf(EachLinePart.Strings[Count]) > -1;
  1214. if Found then begin
  1215. TagField := Count;
  1216. end;
  1217. Inc(Count);
  1218. until Found or (Count > (EachLinePart.Count-1));
  1219. // To initialize LastTTL;
  1220. LastTTL := 86400;
  1221. if TagField > -1 then begin
  1222. case TagField of
  1223. 1 :
  1224. if EachLinePart.Strings[0] <> 'IN' then begin {do not localize}
  1225. // canChangPrevDNTag := True;
  1226. LastTag := EachLinePart.Strings[0];
  1227. if EachLinePart.Strings[TagField] <> 'SOA' then begin {do not localize}
  1228. // PrevDNTag := '';
  1229. end else begin
  1230. LastTTL := IndyStrToInt(EachLinePart.Strings[TagField + 6]);
  1231. end;
  1232. // end else begin
  1233. // canChangPrevDNTag := False;
  1234. end;
  1235. 2 :
  1236. if EachLinePart.Strings[1] = 'IN' then begin {do not localize}
  1237. LastTag := EachLinePart.Strings[0];
  1238. // canChangPrevDNTag := True;
  1239. if EachLinePart.Strings[TagField] <> 'SOA' then begin {do not localize}
  1240. // PrevDNTag := '';
  1241. end else begin
  1242. LastTTL := IndyStrToInt(EachLinePart.Strings[TagField + 6]);
  1243. end;
  1244. end else begin
  1245. // canChangPrevDNTag := False;
  1246. end;
  1247. else
  1248. begin
  1249. // canChangPrevDNTag := False;
  1250. LastTTL := 86400;
  1251. end;
  1252. end;
  1253. //if (EachLinePart.Strings[0] = cAt) or (PrevDNTag = 'SOA') then
  1254. if EachLinePart.Strings[0] = cAt then begin
  1255. SingleHostName := LastDenotedDomain
  1256. end else begin
  1257. if LastTag = cAt then begin
  1258. LastTag := SingleHostName;
  1259. end;
  1260. if not TextEndsWith(LastTag, '.') then begin
  1261. SingleHostName := LastTag + '.' + LastDenotedDomain
  1262. end else begin
  1263. SingleHostName := LastTag;
  1264. end;
  1265. end;
  1266. case TagList.IndexOf(EachLinePart.Strings[TagField]) of
  1267. // Check ip
  1268. TypeCode_A :
  1269. begin
  1270. LLRR_A := TIdRR_A.Create;
  1271. LLRR_A.RRName := SingleHostName;
  1272. LLRR_A.Address := EachLinePart.Strings[TagField + 1];
  1273. LLRR_A.TTL := LastTTL;
  1274. UpdateTree(TreeRoot, LLRR_A);
  1275. // if canChangPrevDNTag then begin
  1276. // PrevDNTag := 'A';
  1277. // end;
  1278. end;
  1279. // Check IPv6 ip address 10/29,2002
  1280. 0 :
  1281. begin
  1282. LLRR_AAAA := TIdRR_AAAA.Create;
  1283. LLRR_AAAA.RRName := SingleHostName;
  1284. LLRR_AAAA.Address := ConvertToValidv6IP(EachLinePart.Strings[TagField + 1]);
  1285. LLRR_AAAA.TTL := LastTTL;
  1286. UpdateTree(TreeRoot, LLRR_AAAA);
  1287. // if canChangPrevDNTag then begin
  1288. // PrevDNTag := 'AAAA'; {do not localize}
  1289. // end;
  1290. end;
  1291. // Check Domain Name
  1292. TypeCode_CName:
  1293. begin
  1294. LLRR_Name := TIdRR_CName.Create;
  1295. LLRR_Name.RRName := SingleHostName;
  1296. if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
  1297. LLRR_Name.CName := EachLinePart.Strings[TagField + 1];
  1298. end else begin
  1299. LLRR_Name.CName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
  1300. end;
  1301. LLRR_Name.TTL := LastTTL;
  1302. UpdateTree(TreeRoot, LLRR_Name);
  1303. // if canChangPrevDNTag then begin
  1304. // PrevDNTag := 'CNAME'; {do not localize}
  1305. // end;
  1306. end;
  1307. TypeCode_NS :
  1308. begin
  1309. LLRR_NS := TIdRR_NS.Create;
  1310. LLRR_NS.RRName := SingleHostName;
  1311. if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
  1312. LLRR_NS.NSDName := EachLinePart.Strings[TagField + 1];
  1313. end else begin
  1314. LLRR_NS.NSDName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
  1315. end;
  1316. LLRR_NS.TTL := LastTTL;
  1317. UpdateTree(TreeRoot, LLRR_NS);
  1318. // if canChangPrevDNTag then begin
  1319. // PrevDNTag := 'NS'; {do not localize}
  1320. // end;
  1321. end;
  1322. TypeCode_MR :
  1323. begin
  1324. LLRR_MR := TIdRR_MR.Create;
  1325. LLRR_MR.RRName := SingleHostName;
  1326. if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
  1327. LLRR_MR.NewName := EachLinePart.Strings[TagField + 1];
  1328. end else begin
  1329. LLRR_MR.NewName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
  1330. end;
  1331. LLRR_MR.TTL := LastTTL;
  1332. UpdateTree(TreeRoot, LLRR_MR);
  1333. // if canChangPrevDNTag then begin
  1334. // PrevDNTag := 'MR'; {do not localize}
  1335. // end;
  1336. end;
  1337. TypeCode_MD, TypeCode_MB, TypeCode_MF :
  1338. begin
  1339. LLRR_MB := TIdRR_MB.Create;
  1340. LLRR_MB.RRName := SingleHostName;
  1341. if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
  1342. LLRR_MB.MADName := EachLinePart.Strings[TagField + 1];
  1343. end else begin
  1344. LLRR_MB.MADName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
  1345. end;
  1346. LLRR_MB.TTL := LastTTL;
  1347. UpdateTree(TreeRoot, LLRR_MB);
  1348. // if canChangPrevDNTag then begin
  1349. // PrevDNTag := 'MF'; {do not localize}
  1350. // end;
  1351. end;
  1352. TypeCode_MG :
  1353. begin
  1354. LLRR_MG := TIdRR_MG.Create;
  1355. LLRR_MG.RRName := SingleHostName;
  1356. if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
  1357. LLRR_MG.MGMName := EachLinePart.Strings[TagField + 1];
  1358. end else begin
  1359. LLRR_MG.MGMName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
  1360. end;
  1361. LLRR_MG.TTL := LastTTL;
  1362. UpdateTree(TreeRoot, LLRR_MG);
  1363. // if canChangPrevDNTag then begin
  1364. // PrevDNTag := 'MG'; {do not localize}
  1365. // end;
  1366. end;
  1367. // Can be anything
  1368. TypeCode_TXT, TypeCode_NULL:
  1369. begin
  1370. LLRR_TXT := TIdRR_TXT.Create;
  1371. LLRR_TXT.RRName := SingleHostName;
  1372. LLRR_TXT.TXT := EachLinePart.Strings[TagField + 1];
  1373. LLRR_TXT.TTL := LastTTL;
  1374. UpdateTree(TreeRoot, LLRR_TXT);
  1375. // if canChangPrevDNTag then begin
  1376. // PrevDNTag := 'TXT'; {do not localize}
  1377. // end;
  1378. end;
  1379. // Must be FQDN.
  1380. TypeCode_PTR:
  1381. begin
  1382. LLRR_PTR := TIdRR_PTR.Create;
  1383. LLRR_PTR.RRName := SingleHostName;
  1384. if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
  1385. LLRR_PTR.PTRDName := EachLinePart.Strings[TagField + 1];
  1386. end else begin
  1387. LLRR_PTR.PTRDName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
  1388. end;
  1389. LLRR_PTR.TTL := LastTTL;
  1390. UpdateTree(TreeRoot, LLRR_PTR);
  1391. // if canChangPrevDNTag then begin
  1392. // PrevDNTag := 'PTR'; {do not localize}
  1393. // end;
  1394. end;
  1395. // HINFO should has 2 fields : CPU and OS. but TStrings
  1396. // is 0 base, so that we have to minus one
  1397. TypeCode_HINFO:
  1398. begin
  1399. ClearDoubleQutoa(EachLinePart);
  1400. LLRR_HINFO := TIdRR_HINFO.Create;
  1401. LLRR_HINFO.RRName := SingleHostName;
  1402. LLRR_HINFO.CPU := EachLinePart.Strings[TagField + 1];
  1403. LLRR_HINFO.OS := EachLinePart.Strings[TagField + 2];
  1404. LLRR_HINFO.TTL := LastTTL;
  1405. UpdateTree(TreeRoot, LLRR_HINFO);
  1406. // if canChangPrevDNTag then begin
  1407. // PrevDNTag := 'HINFO'; {do not localize}
  1408. // end;
  1409. end;
  1410. // Check RMailBX and EMailBX but TStrings
  1411. // is 0 base, so that we have to minus one
  1412. TypeCode_MINFO:
  1413. begin
  1414. LLRR_MINFO := TIdRR_MINFO.Create;
  1415. LLRR_MINFO.RRName := SingleHostName;
  1416. if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
  1417. LLRR_MINFO.Responsible_Mail := EachLinePart.Strings[TagField + 1];
  1418. end else begin
  1419. LLRR_MINFO.Responsible_Mail := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
  1420. end;
  1421. if TextEndsWith(EachLinePart.Strings[TagField + 2], '.') then begin
  1422. LLRR_MINFO.ErrorHandle_Mail := EachLinePart.Strings[TagField + 2];
  1423. end else begin
  1424. LLRR_MINFO.ErrorHandle_Mail := EachLinePart.Strings[TagField + 2] + '.' + LastDenotedDomain;
  1425. end;
  1426. LLRR_MINFO.TTL := LastTTL;
  1427. UpdateTree(TreeRoot, LLRR_MINFO);
  1428. // if canChangPrevDNTag then begin
  1429. // PrevDNTag := 'MINFO'; {do not localize}
  1430. // end;
  1431. end;
  1432. // Check Pref(Numeric) and Exchange. but TStrings
  1433. // is 0 base, so that we have to minus one
  1434. TypeCode_MX:
  1435. begin
  1436. LLRR_MX := TIdRR_MX.Create;
  1437. LLRR_MX.RRName := SingleHostName;
  1438. LLRR_MX.Preference := EachLinePart.Strings[TagField + 1];
  1439. if TextEndsWith(EachLinePart.Strings[TagField + 2], '.') then begin
  1440. LLRR_MX.Exchange := EachLinePart.Strings[TagField + 2];
  1441. end else begin
  1442. LLRR_MX.Exchange := EachLinePart.Strings[TagField + 2] + '.' + LastDenotedDomain;
  1443. end;
  1444. LLRR_MX.TTL := LastTTL;
  1445. UpdateTree(TreeRoot, LLRR_MX);
  1446. // if canChangPrevDNTag then begin
  1447. // PrevDNTag := 'MX'; {do not localize}
  1448. // end;
  1449. end;
  1450. // TStrings is 0 base, so that we have to minus one
  1451. TypeCode_SOA:
  1452. begin
  1453. LLRR_SOA := TIdRR_SOA.Create;
  1454. if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
  1455. LLRR_SOA.MName := EachLinePart.Strings[TagField + 1];
  1456. end else begin
  1457. LLRR_SOA.MName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
  1458. end;
  1459. //LLRR_SOA.RRName:= LLRR_SOA.MName;
  1460. if (SingleHostName = '') and (LastDenotedDomain = '') then begin
  1461. LastDenotedDomain := String(LLRR_SOA.MName); // explicit convert to Unicode
  1462. Fetch(LastDenotedDomain, '.');
  1463. SingleHostName := LastDenotedDomain;
  1464. end;
  1465. LLRR_SOA.RRName := SingleHostName;
  1466. // Update the Handed List
  1467. {
  1468. if Handed_DomainList.IndexOf(LLRR_SOA.MName) = -1 then begin
  1469. Handed_DomainList.Add(LLRR_SOA.MName);
  1470. end;
  1471. }
  1472. if Handed_DomainList.IndexOf(LLRR_SOA.RRName) = -1 then begin
  1473. Handed_DomainList.Add(LLRR_SOA.RRName);
  1474. end;
  1475. {
  1476. if DenotedDomain.IndexOf(LLRR_SOA.MName) = -1 then begin
  1477. DenotedDomain.Add(LLRR_SOA.MName);
  1478. end;
  1479. LastDenotedDomain := LLRR_SOA.MName;
  1480. }
  1481. if DenotedDomain.IndexOf(LLRR_SOA.RRName) = -1 then begin
  1482. DenotedDomain.Add(LLRR_SOA.RRName);
  1483. end;
  1484. //LastDenotedDomain := LLRR_SOA.RRName;
  1485. if TextEndsWith(EachLinePart.Strings[TagField + 2], '.') then begin
  1486. LLRR_SOA.RName := EachLinePart.Strings[TagField + 2];
  1487. end else begin
  1488. LLRR_SOA.RName := EachLinePart.Strings[TagField + 2] + '.' + LastDenotedDomain;
  1489. end;
  1490. Checks := TStringList.Create;
  1491. try
  1492. RName := String(LLRR_SOA.RName); // explicit convert to Unicode
  1493. while RName <> '' do begin
  1494. Checks.Add(Fetch(RName, '.'));
  1495. end;
  1496. RName := '';
  1497. For Count := 0 to Checks.Count -1 do begin
  1498. if Checks.Strings[Count] <> '' then begin
  1499. RName := RName + Checks.Strings[Count] + '.';
  1500. end;
  1501. end;
  1502. LLRR_SOA.RName := RName;
  1503. finally
  1504. Checks.Free;
  1505. end;
  1506. LLRR_SOA.Serial := EachLinePart.Strings[TagField + 3];
  1507. LLRR_SOA.Refresh := EachLinePart.Strings[TagField + 4];
  1508. LLRR_SOA.Retry := EachLinePart.Strings[TagField + 5];
  1509. LLRR_SOA.Expire := EachLinePart.Strings[TagField + 6];
  1510. LLRR_SOA.Minimum := EachLinePart.Strings[TagField + 7];
  1511. LastTTL := IndyStrToInt(LLRR_SOA.Expire);
  1512. LLRR_SOA.TTL := LastTTL;
  1513. UpdateTree(TreeRoot, LLRR_SOA);
  1514. // if canChangPrevDNTag then begin
  1515. // PrevDNTag := 'SOA'; {do not localize}
  1516. // end;
  1517. end;
  1518. TypeCode_WKS:
  1519. begin
  1520. // if canChangPrevDNTag then begin
  1521. // PrevDNTag := 'WKS'; {do not localize}
  1522. // end;
  1523. end;
  1524. end;
  1525. end;
  1526. end; // if EachLinePart.Count == 0 => Only Comment
  1527. end;
  1528. Inc(CurrentLineNum);
  1529. until (CurrentLineNum > (FileStrings.Count -1));
  1530. end;
  1531. Result := not Stop;
  1532. finally
  1533. DenotedDomain.Free;
  1534. end;
  1535. finally
  1536. EachLinePart.Free;
  1537. end;
  1538. end;
  1539. begin
  1540. MakeTagList;
  1541. try
  1542. Result := IsValidMasterFile;
  1543. // IsValidMasterFile is used in local, so I design with not
  1544. // any parameter.
  1545. if Result then begin
  1546. Result := LoadMasterFile;
  1547. end;
  1548. finally
  1549. FreeTagList;
  1550. end;
  1551. end;
  1552. procedure TIdDNS_UDPServer.SaveToCache(ResourceRecord: TIdBytes; QueryName : string; OriginalQType : UInt16);
  1553. var
  1554. TempResolver : TIdDNSResolver;
  1555. Count : Integer;
  1556. begin
  1557. TempResolver := TIdDNSResolver.Create(nil);
  1558. try
  1559. // RLebeau: FillResultWithOutCheckId() is deprecated, but not using FillResult()
  1560. // here yet because it validates the DNSHeader.RCode, and I do not know if that
  1561. // is needed here. I don't want to break this logic...
  1562. TempResolver.FillResultWithOutCheckId(ResourceRecord);
  1563. if TempResolver.DNSHeader.ANCount > 0 then begin
  1564. for Count := 0 to TempResolver.QueryResult.Count - 1 do begin
  1565. UpdateTree(Cached_Tree, TempResolver.QueryResult.Items[Count]);
  1566. end;
  1567. end;
  1568. finally
  1569. TempResolver.Free;
  1570. end;
  1571. end;
  1572. function TIdDNS_UDPServer.SearchTree(Root: TIdDNTreeNode; QName: String; QType : UInt16): TIdDNTreeNode;
  1573. var
  1574. RRIndex : integer;
  1575. NodeCursor : TIdDNTreeNode;
  1576. NameLabels : TStrings;
  1577. OneNode, FullName : string;
  1578. Found : Boolean;
  1579. begin
  1580. Result := nil;
  1581. NameLabels := TStringList.Create;
  1582. try
  1583. FullName := QName;
  1584. NodeCursor := Root;
  1585. Found := False;
  1586. repeat
  1587. OneNode := Fetch(FullName, '.');
  1588. if OneNode <> '' then begin
  1589. NameLabels.Add(OneNode);
  1590. end;
  1591. until FullName = '';
  1592. repeat
  1593. if QType <> TypeCode_SOA then begin
  1594. RRIndex := NodeCursor.ChildIndex.IndexOf(NameLabels.Strings[NameLabels.Count - 1]);
  1595. if RRIndex <> -1 then begin
  1596. NameLabels.Delete(NameLabels.Count - 1);
  1597. NodeCursor := NodeCursor.Children[RRIndex];
  1598. if NameLabels.Count = 1 then begin
  1599. Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
  1600. end else begin
  1601. Found := NameLabels.Count = 0;
  1602. end;
  1603. end else begin
  1604. if NameLabels.Count = 1 then begin
  1605. Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
  1606. if not Found then begin
  1607. NameLabels.Clear;
  1608. end;
  1609. end else begin
  1610. NameLabels.Clear;
  1611. end;
  1612. end;
  1613. end else begin
  1614. RRIndex := NodeCursor.ChildIndex.IndexOf(NameLabels.Strings[NameLabels.Count - 1]);
  1615. if RRIndex <> -1 then begin
  1616. NameLabels.Delete(NameLabels.Count - 1);
  1617. NodeCursor := NodeCursor.Children[RRIndex];
  1618. if NameLabels.Count = 1 then begin
  1619. Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
  1620. end else begin
  1621. Found := NameLabels.Count = 0;
  1622. end;
  1623. end else begin
  1624. if NameLabels.Count = 1 then begin
  1625. Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
  1626. if not Found then begin
  1627. NameLabels.Clear;
  1628. end;
  1629. end else begin
  1630. NameLabels.Clear;
  1631. end;
  1632. end;
  1633. end;
  1634. until (NameLabels.Count = 0) or Found;
  1635. if Found then begin
  1636. Result := NodeCursor;
  1637. end;
  1638. finally
  1639. NameLabels.Free;
  1640. end;
  1641. end;
  1642. procedure TIdDNS_UDPServer.SetHanded_DomainList(const Value: TStrings);
  1643. begin
  1644. FHanded_DomainList.Assign(Value);
  1645. end;
  1646. procedure TIdDNS_UDPServer.SetRootDNS_NET(const Value: TStrings);
  1647. begin
  1648. FRootDNS_NET.Assign(Value);
  1649. end;
  1650. procedure TIdDNS_UDPServer.SetZoneMasterFiles(const Value: TStrings);
  1651. begin
  1652. FZoneMasterFiles.Assign(Value);
  1653. end;
  1654. procedure TIdDNS_UDPServer.UpdateTree(TreeRoot: TIdDNTreeNode; RR: TResultRecord);
  1655. var
  1656. NameNode : TStrings;
  1657. RRName, APart : String;
  1658. Count, NodeIndex : Integer;
  1659. NodeCursor : TIdDNTreeNode;
  1660. LRR_A : TIdRR_A;
  1661. LRR_AAAA : TIdRR_AAAA;
  1662. LRR_NS : TIdRR_NS;
  1663. LRR_MB : TIdRR_MB;
  1664. LRR_Name : TIdRR_CName;
  1665. LRR_SOA : TIdRR_SOA;
  1666. LRR_MG : TIdRR_MG;
  1667. LRR_MR : TIdRR_MR;
  1668. LRR_PTR : TIdRR_PTR;
  1669. LRR_HINFO : TIdRR_HINFO;
  1670. LRR_MINFO : TIdRR_MINFO;
  1671. LRR_MX : TIdRR_MX;
  1672. LRR_TXT : TIdRR_TXT;
  1673. begin
  1674. NameNode := TStringList.Create;
  1675. try
  1676. RRName := RR.Name;
  1677. repeat
  1678. APart := Fetch(RRName, '.');
  1679. if APart <> '' then begin
  1680. NameNode.Add(APart);
  1681. end;
  1682. until RRName = '';
  1683. NodeCursor := TreeRoot;
  1684. RRName := RR.Name;
  1685. if not TextEndsWith(RRName, '.') then begin
  1686. RRName := RRName + '.';
  1687. end;
  1688. if (RR.RecType <> qtSOA) and (Handed_DomainList.IndexOf(LowerCase(RRName)) = -1) and (RR.RecType <> qtNS) then begin
  1689. for Count := NameNode.Count-1 downto 1 do begin
  1690. NodeIndex := NodeCursor.ChildIndex.IndexOf(NameNode.Strings[Count]);
  1691. if NodeIndex = -1 then begin
  1692. NodeCursor := NodeCursor.AddChild;
  1693. NodeCursor.AutoSortChild := True;
  1694. NodeCursor.CLabel := NameNode.Strings[Count];
  1695. end else begin
  1696. NodeCursor := NodeCursor.Children[NodeIndex];
  1697. end;
  1698. end;
  1699. RRName := NameNode.Strings[0];
  1700. end else begin
  1701. for Count := NameNode.Count-1 downto 0 do begin
  1702. NodeIndex := NodeCursor.ChildIndex.IndexOf(NameNode.Strings[Count]);
  1703. RRName := NameNode.Strings[Count];
  1704. if NodeIndex = -1 then begin
  1705. NodeCursor := NodeCursor.AddChild;
  1706. //NodeCursor.CLabel := RRName;
  1707. NodeCursor.AutoSortChild := True;
  1708. NodeCursor.CLabel := RRName;
  1709. end else begin
  1710. NodeCursor := NodeCursor.Children[NodeIndex];
  1711. end;
  1712. end;
  1713. RRName := RR.Name;
  1714. end;
  1715. NodeCursor.RRs.ItemNames.Add(RRName);
  1716. case RR.RecType of
  1717. qtA :
  1718. begin
  1719. LRR_A := TIdRR_A.Create;
  1720. try
  1721. NodeCursor.RRs.Add(LRR_A);
  1722. except
  1723. LRR_A.Free;
  1724. raise;
  1725. end;
  1726. LRR_A.RRName := RRName;
  1727. LRR_A.Address := TARecord(RR).IPAddress;
  1728. LRR_A.TTL := TARecord(RR).TTL;
  1729. if LRR_A.ifAddFullName(NodeCursor.FullName) then begin
  1730. LRR_A.RRName := LRR_A.RRName + '.'+ NodeCursor.FullName;
  1731. end;
  1732. end;
  1733. qtAAAA :
  1734. begin
  1735. LRR_AAAA := TIdRR_AAAA.Create;
  1736. try
  1737. NodeCursor.RRs.Add(LRR_AAAA);
  1738. except
  1739. LRR_AAAA.Free;
  1740. raise;
  1741. end;
  1742. LRR_AAAA.RRName := RRName;
  1743. LRR_AAAA.Address := TAAAARecord(RR).Address;
  1744. LRR_AAAA.TTL := TAAAARecord(RR).TTL;
  1745. if LRR_AAAA.ifAddFullName(NodeCursor.FullName) then begin
  1746. LRR_AAAA.RRName := LRR_AAAA.RRName + '.'+ NodeCursor.FullName;
  1747. end;
  1748. end;
  1749. qtNS:
  1750. begin
  1751. LRR_NS := TIdRR_NS.Create;
  1752. try
  1753. NodeCursor.RRs.Add(LRR_NS);
  1754. except
  1755. LRR_NS.Free;
  1756. raise;
  1757. end;
  1758. LRR_NS.RRName := RRName;
  1759. LRR_NS.NSDName := TNSRecord(RR).HostName;
  1760. LRR_NS.TTL := TNSRecord(RR).TTL;
  1761. if LRR_NS.ifAddFullName(NodeCursor.FullName) then begin
  1762. LRR_NS.RRName := LRR_NS.RRName + '.'+ NodeCursor.FullName;
  1763. end;
  1764. end;
  1765. qtMD, qtMF, qtMB:
  1766. begin
  1767. LRR_MB := TIdRR_MB.Create;
  1768. try
  1769. NodeCursor.RRs.Add(LRR_MB);
  1770. except
  1771. LRR_MB.Free;
  1772. raise;
  1773. end;
  1774. LRR_MB.RRName := RRName;
  1775. LRR_MB.MADName := TNAMERecord(RR).HostName;
  1776. LRR_MB.TTL := TNAMERecord(RR).TTL;
  1777. if LRR_MB.ifAddFullName(NodeCursor.FullName) then begin
  1778. LRR_MB.RRName := LRR_MB.RRName + '.'+ NodeCursor.FullName;
  1779. end;
  1780. end;
  1781. qtName:
  1782. begin
  1783. LRR_Name := TIdRR_CName.Create;
  1784. try
  1785. NodeCursor.RRs.Add(LRR_Name);
  1786. except
  1787. LRR_Name.Free;
  1788. raise;
  1789. end;
  1790. LRR_Name.RRName := RRName;
  1791. LRR_Name.CName := TNAMERecord(RR).HostName;
  1792. LRR_Name.TTL:= TNAMERecord(RR).TTL;
  1793. if LRR_Name.ifAddFullName(NodeCursor.FullName) then begin
  1794. LRR_Name.RRName := LRR_Name.RRName + '.'+ NodeCursor.FullName;
  1795. end;
  1796. end;
  1797. qtSOA:
  1798. begin
  1799. LRR_SOA := TIdRR_SOA.Create;
  1800. try
  1801. NodeCursor.RRs.Add(LRR_SOA);
  1802. except
  1803. LRR_SOA.Free;
  1804. raise;
  1805. end;
  1806. LRR_SOA.RRName := RRName;
  1807. LRR_SOA.MName := TSOARecord(RR).Primary;
  1808. LRR_SOA.RName := TSOARecord(RR).ResponsiblePerson;
  1809. LRR_SOA.Serial := IntToStr(TSOARecord(RR).Serial);
  1810. LRR_SOA.Minimum := IntToStr(TSOARecord(RR).MinimumTTL);
  1811. LRR_SOA.Refresh := IntToStr(TSOARecord(RR).Refresh);
  1812. LRR_SOA.Retry := IntToStr(TSOARecord(RR).Retry);
  1813. LRR_SOA.Expire := IntToStr(TSOARecord(RR).Expire);
  1814. LRR_SOA.TTL:= TSOARecord(RR).TTL;
  1815. if LRR_SOA.ifAddFullName(NodeCursor.FullName) then begin
  1816. LRR_SOA.RRName := LRR_SOA.RRName + '.'+ NodeCursor.FullName;
  1817. end
  1818. else if not TextEndsWith(LRR_SOA.RRName, '.') then begin
  1819. LRR_SOA.RRName := LRR_SOA.RRName + '.';
  1820. end;
  1821. end;
  1822. qtMG :
  1823. begin
  1824. LRR_MG := TIdRR_MG.Create;
  1825. try
  1826. NodeCursor.RRs.Add(LRR_MG);
  1827. except
  1828. LRR_MG.Free;
  1829. raise;
  1830. end;
  1831. LRR_MG.RRName := RRName;
  1832. LRR_MG.MGMName := TNAMERecord(RR).HostName;
  1833. LRR_MG.TTL := TNAMERecord(RR).TTL;
  1834. if LRR_MG.ifAddFullName(NodeCursor.FullName) then begin
  1835. LRR_MG.RRName := LRR_MG.RRName + '.'+ NodeCursor.FullName;
  1836. end;
  1837. end;
  1838. qtMR :
  1839. begin
  1840. LRR_MR := TIdRR_MR.Create;
  1841. try
  1842. NodeCursor.RRs.Add(LRR_MR);
  1843. except
  1844. LRR_MR.Free;
  1845. raise;
  1846. end;
  1847. LRR_MR.RRName := RRName;
  1848. LRR_MR.NewName := TNAMERecord(RR).HostName;
  1849. LRR_MR.TTL := TNAMERecord(RR).TTL;
  1850. if LRR_MR.ifAddFullName(NodeCursor.FullName) then begin
  1851. LRR_MR.RRName := LRR_MR.RRName + '.'+ NodeCursor.FullName;
  1852. end;
  1853. end;
  1854. qtWKS:
  1855. begin
  1856. end;
  1857. qtPTR:
  1858. begin
  1859. LRR_PTR := TIdRR_PTR.Create;
  1860. try
  1861. NodeCursor.RRs.Add(LRR_PTR);
  1862. except
  1863. LRR_PTR.Free;
  1864. raise;
  1865. end;
  1866. LRR_PTR.RRName := RRName;
  1867. LRR_PTR.PTRDName := TPTRRecord(RR).HostName;
  1868. LRR_PTR.TTL := TPTRRecord(RR).TTL;
  1869. if LRR_PTR.ifAddFullName(NodeCursor.FullName) then begin
  1870. LRR_PTR.RRName := LRR_PTR.RRName + '.'+ NodeCursor.FullName;
  1871. end;
  1872. end;
  1873. qtHINFO:
  1874. begin
  1875. LRR_HINFO := TIdRR_HINFO.Create;
  1876. try
  1877. NodeCursor.RRs.Add(LRR_HINFO);
  1878. except
  1879. LRR_HINFO.Free;
  1880. raise;
  1881. end;
  1882. LRR_HINFO.RRName := RRName;
  1883. LRR_HINFO.CPU := THINFORecord(RR).CPU;
  1884. LRR_HINFO.OS := THINFORecord(RR).OS;
  1885. LRR_HINFO.TTL := THINFORecord(RR).TTL;
  1886. if LRR_HINFO.ifAddFullName(NodeCursor.FullName) then begin
  1887. LRR_HINFO.RRName := LRR_HINFO.RRName + '.'+ NodeCursor.FullName;
  1888. end;
  1889. end;
  1890. qtMINFO:
  1891. begin
  1892. LRR_MINFO := TIdRR_MINFO.Create;
  1893. try
  1894. NodeCursor.RRs.Add(LRR_MINFO);
  1895. except
  1896. LRR_MINFO.Free;
  1897. raise;
  1898. end;
  1899. LRR_MINFO.RRName := RRName;
  1900. LRR_MINFO.Responsible_Mail := TMINFORecord(RR).ResponsiblePersonMailbox;
  1901. LRR_MINFO.ErrorHandle_Mail := TMINFORecord(RR).ErrorMailbox;
  1902. LRR_MINFO.TTL := TMINFORecord(RR).TTL;
  1903. if LRR_MINFO.ifAddFullName(NodeCursor.FullName) then begin
  1904. LRR_MINFO.RRName := LRR_MINFO.RRName + '.' + NodeCursor.FullName;
  1905. end;
  1906. end;
  1907. qtMX:
  1908. begin
  1909. LRR_MX := TIdRR_MX.Create;
  1910. try
  1911. NodeCursor.RRs.Add(LRR_MX);
  1912. except
  1913. LRR_MX.Free;
  1914. raise;
  1915. end;
  1916. LRR_MX.RRName := RRName;
  1917. LRR_MX.Exchange := TMXRecord(RR).ExchangeServer;
  1918. LRR_MX.Preference := IntToStr(TMXRecord(RR).Preference);
  1919. LRR_MX.TTL := TMXRecord(RR).TTL;
  1920. if LRR_MX.ifAddFullName(NodeCursor.FullName) then begin
  1921. LRR_MX.RRName := LRR_MX.RRName + '.'+ NodeCursor.FullName;
  1922. end;
  1923. end;
  1924. qtTXT, qtNULL:
  1925. begin
  1926. LRR_TXT := TIdRR_TXT.Create;
  1927. try
  1928. NodeCursor.RRs.Add(LRR_TXT);
  1929. except
  1930. LRR_TXT.Free;
  1931. raise;
  1932. end;
  1933. LRR_TXT.RRName := RRName;
  1934. LRR_TXT.TXT := TTextRecord(RR).Text.Text;
  1935. LRR_TXT.TTL := TTextRecord(RR).TTL;
  1936. if LRR_TXT.ifAddFullName(NodeCursor.FullName) then begin
  1937. LRR_TXT.RRName := LRR_TXT.RRName + '.'+ NodeCursor.FullName;
  1938. end;
  1939. end;
  1940. end;
  1941. finally
  1942. NameNode.Free;
  1943. end;
  1944. end;
  1945. procedure TIdDNS_UDPServer.UpdateTree(TreeRoot: TIdDNTreeNode; RR: TIdTextModeResourceRecord);
  1946. var
  1947. NameNode : TStrings;
  1948. RRName, APart : String;
  1949. Count, NodeIndex, RRIndex : Integer;
  1950. NodeCursor : TIdDNTreeNode;
  1951. LRR_AAAA : TIdRR_AAAA;
  1952. LRR_A : TIdRR_A;
  1953. LRR_NS : TIdRR_NS;
  1954. LRR_MB : TIdRR_MB;
  1955. LRR_Name : TIdRR_CName;
  1956. LRR_SOA : TIdRR_SOA;
  1957. LRR_MG : TIdRR_MG;
  1958. LRR_MR : TIdRR_MR;
  1959. LRR_PTR : TIdRR_PTR;
  1960. LRR_HINFO : TIdRR_HINFO;
  1961. LRR_MINFO : TIdRR_MINFO;
  1962. LRR_MX : TIdRR_MX;
  1963. LRR_TXT : TIdRR_TXT;
  1964. LRR_Error : TIdRR_Error;
  1965. begin
  1966. NameNode := TStringList.Create;
  1967. try
  1968. RRName := RR.RRName;
  1969. repeat
  1970. APart := Fetch(RRName, '.');
  1971. if APart <> '' then begin
  1972. NameNode.Add(APart);
  1973. end;
  1974. until RRName = '';
  1975. NodeCursor := TreeRoot;
  1976. RRName := RR.RRName;
  1977. if not TextEndsWith(RRName, '.') then begin
  1978. RR.RRName := RR.RRName + '.';
  1979. end;
  1980. // VC: in2002-02-24-1715, it just denoted TIdRR_A and TIdRR_PTR,
  1981. // but that make search a domain name RR becoming complex,
  1982. // therefor I replace it with all RRs but not TIdRR_SOA
  1983. // SOA should own independent node.
  1984. if (not (RR is TIdRR_SOA)) and (Handed_DomainList.IndexOf(LowerCase(RR.RRName)) = -1) then begin
  1985. for Count := NameNode.Count - 1 downto 1 do begin
  1986. NodeIndex := NodeCursor.ChildIndex.IndexOf(NameNode.Strings[Count]);
  1987. if NodeIndex = -1 then begin
  1988. NodeCursor := NodeCursor.AddChild;
  1989. NodeCursor.AutoSortChild := True;
  1990. NodeCursor.CLabel := NameNode.Strings[Count];
  1991. end else begin
  1992. NodeCursor := NodeCursor.Children[NodeIndex];
  1993. end;
  1994. end;
  1995. RRName := NameNode.Strings[0];
  1996. end else begin
  1997. for Count := NameNode.Count -1 downto 0 do begin
  1998. NodeIndex := NodeCursor.ChildIndex.IndexOf(NameNode.Strings[Count]);
  1999. RRName := NameNode.Strings[Count];
  2000. if NodeIndex = -1 then begin
  2001. NodeCursor := NodeCursor.AddChild;
  2002. NodeCursor.AutoSortChild := True;
  2003. NodeCursor.CLabel := RRName;
  2004. end else begin
  2005. NodeCursor := NodeCursor.Children[NodeIndex];
  2006. end;
  2007. end;
  2008. RRName := RR.RRName;
  2009. end;
  2010. RRIndex := NodeCursor.RRs.ItemNames.IndexOf(RRName);
  2011. if RRIndex = -1 then begin
  2012. NodeCursor.RRs.ItemNames.Add(RRName);
  2013. end else begin
  2014. repeat
  2015. Inc(RRIndex);
  2016. if RRIndex > NodeCursor.RRs.ItemNames.Count -1 then begin
  2017. RRIndex := -1;
  2018. Break;
  2019. end;
  2020. if NodeCursor.RRs.ItemNames.Strings[RRIndex] <> RRName then begin
  2021. Break;
  2022. end;
  2023. until RRIndex > (NodeCursor.RRs.ItemNames.Count-1);
  2024. if RRIndex = -1 then begin
  2025. NodeCursor.RRs.ItemNames.Add(RRName);
  2026. end else begin
  2027. NodeCursor.RRs.ItemNames.Insert(RRIndex, RRName);
  2028. end;
  2029. end;
  2030. case RR.TypeCode of
  2031. TypeCode_Error :
  2032. begin
  2033. LRR_Error := TIdRR_Error(RR);
  2034. if RRIndex = -1 then begin
  2035. NodeCursor.RRs.Add(LRR_Error);
  2036. end else begin
  2037. NodeCursor.RRs.Insert(RRIndex, LRR_Error);
  2038. end;
  2039. end;
  2040. TypeCode_A :
  2041. begin
  2042. LRR_A := TIdRR_A(RR);
  2043. if RRIndex = -1 then begin
  2044. NodeCursor.RRs.Add(LRR_A);
  2045. end else begin
  2046. NodeCursor.RRs.Insert(RRIndex, LRR_A);
  2047. end;
  2048. end;
  2049. TypeCode_AAAA :
  2050. begin
  2051. LRR_AAAA := TIdRR_AAAA(RR);
  2052. if RRIndex = -1 then begin
  2053. NodeCursor.RRs.Add(LRR_AAAA);
  2054. end else begin
  2055. NodeCursor.RRs.Insert(RRIndex, LRR_AAAA);
  2056. end;
  2057. end;
  2058. TypeCode_NS:
  2059. begin
  2060. LRR_NS := TIdRR_NS(RR);
  2061. if RRIndex = -1 then begin
  2062. NodeCursor.RRs.Add(LRR_NS);
  2063. end else begin
  2064. NodeCursor.RRs.Insert(RRIndex, LRR_NS);
  2065. end;
  2066. end;
  2067. TypeCode_MF:
  2068. begin
  2069. LRR_MB := TIdRR_MB(RR);
  2070. if RRIndex = -1 then begin
  2071. NodeCursor.RRs.Add(LRR_MB);
  2072. end else begin
  2073. NodeCursor.RRs.Insert(RRIndex, LRR_MB);
  2074. end;
  2075. end;
  2076. TypeCode_CName:
  2077. begin
  2078. LRR_Name := TIdRR_CName(RR);
  2079. if RRIndex = -1 then begin
  2080. NodeCursor.RRs.Add(LRR_Name);
  2081. end else begin
  2082. NodeCursor.RRs.Insert(RRIndex, LRR_Name);
  2083. end;
  2084. end;
  2085. TypeCode_SOA:
  2086. begin
  2087. LRR_SOA := TIdRR_SOA(RR);
  2088. if RRIndex = -1 then begin
  2089. NodeCursor.RRs.Add(LRR_SOA);
  2090. end else begin
  2091. NodeCursor.RRs.Insert(RRIndex, LRR_SOA);
  2092. end;
  2093. end;
  2094. TypeCode_MG :
  2095. begin
  2096. LRR_MG := TIdRR_MG(RR);
  2097. if RRIndex = -1 then begin
  2098. NodeCursor.RRs.Add(LRR_MG);
  2099. end else begin
  2100. NodeCursor.RRs.Insert(RRIndex, LRR_MG);
  2101. end;
  2102. end;
  2103. TypeCode_MR :
  2104. begin
  2105. LRR_MR := TIdRR_MR(RR);
  2106. if RRIndex = -1 then begin
  2107. NodeCursor.RRs.Add(LRR_MR);
  2108. end else begin
  2109. NodeCursor.RRs.Insert(RRIndex, LRR_MR);
  2110. end;
  2111. end;
  2112. TypeCode_WKS:
  2113. begin
  2114. end;
  2115. TypeCode_PTR:
  2116. begin
  2117. LRR_PTR := TIdRR_PTR(RR);
  2118. if RRIndex = -1 then begin
  2119. NodeCursor.RRs.Add(LRR_PTR);
  2120. end else begin
  2121. NodeCursor.RRs.Insert(RRIndex, LRR_PTR);
  2122. end;
  2123. end;
  2124. TypeCode_HINFO:
  2125. begin
  2126. LRR_HINFO := TIdRR_HINFO(RR);
  2127. if RRIndex = -1 then begin
  2128. NodeCursor.RRs.Add(LRR_HINFO);
  2129. end else begin
  2130. NodeCursor.RRs.Insert(RRIndex, LRR_HINFO);
  2131. end;
  2132. end;
  2133. TypeCode_MINFO:
  2134. begin
  2135. LRR_MINFO := TIdRR_MINFO(RR);
  2136. if RRIndex = -1 then begin
  2137. NodeCursor.RRs.Add(LRR_MINFO);
  2138. end else begin
  2139. NodeCursor.RRs.Insert(RRIndex, LRR_MINFO);
  2140. end;
  2141. end;
  2142. TypeCode_MX:
  2143. begin
  2144. LRR_MX := TIdRR_MX(RR);
  2145. if RRIndex = -1 then begin
  2146. NodeCursor.RRs.Add(LRR_MX);
  2147. end else begin
  2148. NodeCursor.RRs.Insert(RRIndex, LRR_MX);
  2149. end;
  2150. end;
  2151. TypeCode_TXT, TypeCode_NULL:
  2152. begin
  2153. LRR_TXT := TIdRR_TXT(RR);
  2154. if RRIndex = -1 then begin
  2155. NodeCursor.RRs.Add(LRR_TXT);
  2156. end else begin
  2157. NodeCursor.RRs.Insert(RRIndex, LRR_TXT);
  2158. end;
  2159. end;
  2160. end;
  2161. finally
  2162. NameNode.Free;
  2163. end;
  2164. end;
  2165. procedure TIdDNS_UDPServer.DoAfterSendBack(ABinding: TIdSocketHandle;
  2166. ADNSHeader: TDNSHeader; var QueryResult: TIdBytes; var ResultCode: String;
  2167. Query : TIdBytes);
  2168. begin
  2169. if Assigned(FOnAfterSendBack) then begin
  2170. FOnAfterSendBack(ABinding, ADNSHeader, QueryResult, ResultCode, Query);
  2171. end;
  2172. end;
  2173. function TIdDNS_UDPServer.AXFR(Header : TDNSHeader; Question: string; var Answer: TIdBytes): string;
  2174. var
  2175. TargetNode : TIdDNTreeNode;
  2176. IsMyDomains : Boolean;
  2177. RRcount : Integer;
  2178. Temp: TIdBytes;
  2179. begin
  2180. Question := LowerCase(Question);
  2181. IsMyDomains := Handed_DomainList.IndexOf(Question) > -1;
  2182. if not IsMyDomains then begin
  2183. Fetch(Question, '.');
  2184. IsMyDomains := Handed_DomainList.IndexOf(Question) > -1;
  2185. end;
  2186. // Is my domain, go for searching the node.
  2187. TargetNode := nil;
  2188. SetLength(Answer, 0);
  2189. Header.ANCount := 0;
  2190. if IsMyDomains then begin
  2191. TargetNode := SearchTree(Handed_Tree, Question, TypeCode_SOA);
  2192. end;
  2193. if IsMyDomains and (TargetNode <> nil) then begin
  2194. // combine the AXFR Data(So many)
  2195. RRCount := 0;
  2196. Answer := TargetNode.DumpAllBinaryData(RRCount);
  2197. Header.ANCount := RRCount;
  2198. Header.QR := iQr_Answer;
  2199. Header.AA := iAA_Authoritative;
  2200. Header.RCode := iRCodeNoError;
  2201. Header.QDCount := 0;
  2202. Header.ARCount := 0;
  2203. Header.TC := 0;
  2204. Temp := Header.GenerateBinaryHeader;
  2205. AppendBytes(Temp, Answer);
  2206. Answer := Temp;
  2207. Result := cRCodeQueryOK;
  2208. end else begin
  2209. Header.QR := iQr_Answer;
  2210. Header.AA := iAA_Authoritative;
  2211. Header.RCode := iRCodeNameError;
  2212. Header.QDCount := 0;
  2213. Header.ARCount := 0;
  2214. Header.TC := 0;
  2215. Answer := Header.GenerateBinaryHeader;
  2216. Result := cRCodeQueryNotFound;
  2217. end;
  2218. end;
  2219. procedure TIdDNS_UDPServer.InternalSearch(Header: TDNSHeader; QName: string;
  2220. QType : UInt16; var Answer: TIdBytes; IfMainQuestion : Boolean;
  2221. IsSearchCache : Boolean = False; IsAdditional : Boolean = False;
  2222. IsWildCard : Boolean = False; WildCardOrgName : string = '');
  2223. var
  2224. MoreAddrSearch : TStrings;
  2225. TargetNode : TIdDNTreeNode;
  2226. Server_Index, RRIndex, Count : Integer;
  2227. LocalAnswer, TempBytes, TempAnswer: TIdBytes;
  2228. temp_QName, temp: string;
  2229. AResult: TIdBytes;
  2230. Stop, Extra, IsMyDomains, ifAdditional : Boolean;
  2231. LDNSResolver : TIdDNSResolver;
  2232. procedure CheckMoreAddrSearch(const AStr: String);
  2233. begin
  2234. if (not IsValidIP(AStr)) and IsHostName(AStr) then begin
  2235. MoreAddrSearch.Add(AStr);
  2236. end;
  2237. end;
  2238. begin
  2239. SetLength(Answer, 0);
  2240. SetLength(Aresult, 0);
  2241. // Search the Handed Tree first.
  2242. MoreAddrSearch := TStringList.Create;
  2243. try
  2244. Extra := False;
  2245. //Pushed := False;
  2246. if not IsSearchCache then begin
  2247. TargetNode := SearchTree(Handed_Tree, QName, QType);
  2248. if TargetNode <> nil then begin //Assemble the Answer.
  2249. RRIndex := TargetNode.RRs.ItemNames.IndexOf(LowerCase(QName));
  2250. if RRIndex = -1 then begin
  2251. { below are added again by Dennies Chang in 2004/7/15
  2252. { According RFC 1035, a full domain name must be tailed by a '.',
  2253. { but in normal behavior, user will not input '.' in last
  2254. { position of the full name. So we have to compare both of the
  2255. { cases. }
  2256. if TextEndsWith(QName, '.') then begin
  2257. SetLength(QName, Length(QName)-1);
  2258. end;
  2259. RRIndex := TargetNode.RRs.ItemNames.IndexOf(LowerCase(QName));
  2260. { above are added again by Dennies Chang in 2004/7/15}
  2261. if RRIndex = -1 then begin
  2262. QName := Fetch(QName, '.');
  2263. RRIndex := TargetNode.RRs.ItemNames.IndexOf(LowerCase(QName));
  2264. end;
  2265. { marked by Dennies Chang in 2004/7/15
  2266. QName:= Fetch(QName, '.');
  2267. RRIndex := TargetNode.RRs.ItemNames.IndexOf(IndyLowerCase(QName));
  2268. }
  2269. end;
  2270. repeat
  2271. temp_QName := QName;
  2272. SetLength(LocalAnswer, 0);
  2273. if RRIndex <> -1 then begin
  2274. case QType of
  2275. TypeCode_A:
  2276. begin
  2277. if TargetNode.RRs.Items[RRIndex] is TIdRR_A then begin
  2278. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2279. end;
  2280. end;
  2281. TypeCode_AAAA:
  2282. begin
  2283. if TargetNode.RRs.Items[RRIndex] is TIdRR_AAAA then begin
  2284. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2285. end;
  2286. end;
  2287. TypeCode_NS:
  2288. begin
  2289. if TargetNode.RRs.Items[RRIndex] is TIdRR_NS then begin
  2290. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_NS).NSDName);
  2291. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2292. end;
  2293. end;
  2294. TypeCode_MD:
  2295. begin
  2296. if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
  2297. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
  2298. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2299. end;
  2300. end;
  2301. TypeCode_MF:
  2302. begin
  2303. if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
  2304. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
  2305. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2306. end;
  2307. end;
  2308. TypeCode_CName:
  2309. begin
  2310. if TargetNode.RRs.Items[RRIndex] is TIdRR_CName then begin
  2311. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_CName).CName);
  2312. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2313. end;
  2314. end;
  2315. TypeCode_SOA:
  2316. begin
  2317. if TargetNode.RRs.Items[RRIndex] is TIdRR_SOA then begin
  2318. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_SOA).MName);
  2319. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_SOA).RName);
  2320. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2321. end;
  2322. end;
  2323. TypeCode_MB:
  2324. begin
  2325. if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
  2326. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
  2327. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2328. end;
  2329. end;
  2330. TypeCode_MG:
  2331. begin
  2332. if TargetNode.RRs.Items[RRIndex] is TIdRR_MG then begin
  2333. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MG).MGMName);
  2334. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2335. end;
  2336. end;
  2337. TypeCode_MR:
  2338. begin
  2339. if TargetNode.RRs.Items[RRIndex] is TIdRR_MR then begin
  2340. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MR).NewName);
  2341. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2342. end;
  2343. end;
  2344. TypeCode_NULL:
  2345. begin
  2346. {
  2347. if TargetNode.RRs.Items[RRIndex] is TIdRR_NULL then begin
  2348. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2349. end;
  2350. }
  2351. end;
  2352. TypeCode_WKS:
  2353. begin
  2354. if TargetNode.RRs.Items[RRIndex] is TIdRR_WKS then begin
  2355. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2356. end;
  2357. end;
  2358. TypeCode_PTR:
  2359. begin
  2360. if TargetNode.RRs.Items[RRIndex] is TIdRR_PTR then begin
  2361. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2362. end;
  2363. end;
  2364. TypeCode_HINFO:
  2365. begin
  2366. if TargetNode.RRs.Items[RRIndex] is TIdRR_HINFO then begin
  2367. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2368. end;
  2369. end;
  2370. TypeCode_MINFO:
  2371. begin
  2372. if TargetNode.RRs.Items[RRIndex] is TIdRR_MINFO then begin
  2373. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2374. end;
  2375. end;
  2376. TypeCode_MX:
  2377. begin
  2378. if TargetNode.RRs.Items[RRIndex] is TIdRR_MX then begin
  2379. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MX).Exchange);
  2380. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2381. end;
  2382. end;
  2383. TypeCode_TXT:
  2384. begin
  2385. if TargetNode.RRs.Items[RRIndex] is TIdRR_TXT then begin
  2386. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2387. end;
  2388. end;
  2389. TypeCode_STAR:
  2390. begin
  2391. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2392. end;
  2393. end;
  2394. if IsWildCard and (LocalAnswer <> nil) then begin
  2395. {
  2396. temp := DomainNameToDNSStr(QName+'.'+TargetNode.FullName);
  2397. Fetch(LocalAnswer, temp);
  2398. }
  2399. TempBytes := DomainNameToDNSStr(TargetNode.FullName);
  2400. FetchBytes(LocalAnswer, TempBytes);
  2401. TempBytes := DomainNameToDNSStr(WildCardOrgName);
  2402. AppendBytes(TempBytes, LocalAnswer);
  2403. LocalAnswer := TempBytes;
  2404. //LocalAnswer := DomainNameToDNSStr(WildCardOrgName) + LocalAnswer;
  2405. end;
  2406. if LocalAnswer <> nil then begin
  2407. AppendBytes(Answer, LocalAnswer);
  2408. if ((not Extra) and (not IsAdditional)) or (QType = TypeCode_AAAA) then begin
  2409. if (TargetNode.RRs.Items[RRIndex] is TIdRR_NS) then begin
  2410. if IfMainQuestion then begin
  2411. Header.ANCount := Header.ANCount + 1;
  2412. end else begin
  2413. Header.NSCount := Header.NSCount + 1;
  2414. end;
  2415. end
  2416. else if IfMainQuestion then begin
  2417. Header.ANCount := Header.ANCount + 1;
  2418. end else begin
  2419. Header.ARCount := Header.ARCount + 1;
  2420. end;
  2421. end
  2422. else if IsAdditional then begin
  2423. Header.ARCount := Header.ARCount + 1;
  2424. end
  2425. else begin
  2426. Header.ANCount := Header.ANCount + 1;
  2427. end;
  2428. Header.Qr := iQr_Answer;
  2429. Header.AA := iAA_Authoritative;
  2430. Header.RCode := iRCodeNoError;
  2431. end;
  2432. if RRIndex < (TargetNode.RRs.ItemNames.Count-1) then begin
  2433. Stop := False;
  2434. Inc(RRIndex);
  2435. end else begin
  2436. Stop := True;
  2437. end;
  2438. end else begin
  2439. Stop := True;
  2440. end;
  2441. if QName = temp_QName then begin
  2442. temp_QName := '';
  2443. end;
  2444. until (RRIndex = -1) or
  2445. (not ((not TextIsSame(TargetNode.RRs.ItemNames.Strings[RRIndex], QName)) xor
  2446. (not TextIsSame(TargetNode.RRs.ItemNames.Strings[RRIndex], Fetch(temp_QName, '.')))))
  2447. or Stop;
  2448. // Finish the Loop, but n record is found, we need to search if
  2449. // there is a widechar record in its subdomain.
  2450. // Main, Cache, Additional, Wildcard
  2451. if Answer <> nil then begin
  2452. InternalSearch(Header, '*.' + QName, QType, LocalAnswer, IfMAinQuestion, False, False, True, QName);
  2453. if LocalAnswer <> nil then begin
  2454. AppendBytes(Answer, LocalAnswer);
  2455. end;
  2456. end;
  2457. end else begin // Node can't be found.
  2458. MoreAddrSearch.Clear;
  2459. end;
  2460. if MoreAddrSearch.Count > 0 then begin
  2461. for Count := 0 to MoreAddrSearch.Count -1 do begin
  2462. Server_Index := 0;
  2463. if Handed_DomainList.Count > 0 then begin
  2464. repeat
  2465. IsMyDomains := IndyPos(
  2466. LowerCase(Handed_DomainList.Strings[Server_Index]),
  2467. LowerCase(MoreAddrSearch.Strings[Count])) > 0;
  2468. Inc(Server_Index);
  2469. until IsMyDomains or (Server_Index > (Handed_DomainList.Count-1));
  2470. end else begin
  2471. IsMyDomains := False;
  2472. end;
  2473. if IsMyDomains then begin
  2474. //ifAdditional := (QType <> TypeCode_A) or (QType <> TypeCode_AAAA);
  2475. // modified by Dennies Chang in 2004/7/15.
  2476. ifAdditional := (QType <> TypeCode_CName);
  2477. //Search A record first.
  2478. // Main, Cache, Additional, Wildcard
  2479. InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_A, LocalAnswer, True, False, ifAdditional, False);
  2480. { modified by Dennies Chang in 2004/7/15.
  2481. InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_A,
  2482. LocalAnswer, True, ifAdditional, True);
  2483. }
  2484. if LocalAnswer = nil then begin
  2485. temp := MoreAddrSearch.Strings[Count];
  2486. Fetch(temp, '.');
  2487. temp := '*.' + temp;
  2488. InternalSearch(Header, temp, TypeCode_A, LocalAnswer, True, False, ifAdditional, True, MoreAddrSearch.Strings[Count]);
  2489. { marked by Dennies Chang in 2004/7/15.
  2490. InternalSearch(Header, temp, TypeCode_A, LocalAnswer, True, ifAdditional, True, True, MoreAddrSearch.Strings[Count]);
  2491. }
  2492. end;
  2493. TempAnswer := LocalAnswer;
  2494. // Search for AAAA also.
  2495. InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_AAAA, LocalAnswer, True, False, ifAdditional, True);
  2496. { marked by Dennies Chang in 2004/7/15.
  2497. InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_AAAA, LocalAnswer, True, ifAdditional, True);
  2498. }
  2499. if LocalAnswer = nil then begin
  2500. temp := MoreAddrSearch.Strings[Count];
  2501. Fetch(temp, '.');
  2502. temp := '*.' + temp;
  2503. InternalSearch(Header, temp, TypeCode_AAAA, LocalAnswer, True, False, ifAdditional, True, MoreAddrSearch.Strings[Count]);
  2504. { marked by Dennies Chang in 2004/7/15.
  2505. InternalSearch(Header, temp, TypeCode_AAAA, LocalAnswer, True, ifAdditional, True, True, MoreAddrSearch.Strings[Count]);
  2506. }
  2507. end;
  2508. AppendBytes(TempAnswer, LocalAnswer);
  2509. LocalAnswer := TempAnswer;
  2510. end else begin
  2511. // Need add AAAA Search in future.
  2512. //QType := TypeCode_A;
  2513. LDNSResolver := TIdDNSResolver.Create;
  2514. try
  2515. Server_Index := 0;
  2516. repeat
  2517. LDNSResolver.Host := RootDNS_NET.Strings[Server_Index];
  2518. LDNSResolver.QueryType := [qtA];
  2519. LDNSResolver.Resolve(MoreAddrSearch.Strings[Count]);
  2520. AResult := LDNSResolver.PlainTextResult;
  2521. Header.ARCount := Header.ARCount + LDNSResolver.QueryResult.Count;
  2522. until (Server_Index >= (RootDNS_NET.Count-1)) or (AResult <> nil);
  2523. AppendBytes(LocalAnswer, AResult, 12);
  2524. finally
  2525. LDNSResolver.Free;
  2526. end;
  2527. end;
  2528. if LocalAnswer <> nil then begin
  2529. AppendBytes(Answer, LocalAnswer);
  2530. end;
  2531. //Answer := LocalAnswer;
  2532. end;
  2533. end;
  2534. end else begin
  2535. //Search the Cache Tree;
  2536. { marked by Dennies Chang in 2004/7/15.
  2537. { it's mark for querying cache only.
  2538. { if Answer = nil then begin }
  2539. TargetNode := SearchTree(Cached_Tree, QName, QType);
  2540. if TargetNode <> nil then begin
  2541. //Assemble the Answer.
  2542. { modified by Dennies Chang in 2004/7/15}
  2543. if (QType in [TypeCode_A, TypeCode_PTR, TypeCode_AAAA, TypeCode_Error, TypeCode_CName]) then begin
  2544. QName := Fetch(QName, '.');
  2545. end;
  2546. RRIndex := TargetNode.RRs.ItemNames.IndexOf(QName);
  2547. repeat
  2548. temp_QName := QName;
  2549. SetLength(LocalAnswer, 0);
  2550. if RRIndex <> -1 then begin
  2551. // TimeOut, update the record.
  2552. if CompareDate(Now, StrToDateTime(TargetNode.RRs.Items[RRIndex].TimeOut)) = 1 then begin
  2553. SetLength(LocalAnswer, 0);
  2554. end else begin
  2555. case QType of
  2556. TypeCode_Error:
  2557. begin
  2558. AppendString(Answer, 'Error'); {do not localize}
  2559. end;
  2560. TypeCode_A:
  2561. begin
  2562. if TargetNode.RRs.Items[RRIndex] is TIdRR_A then begin
  2563. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2564. end;
  2565. end;
  2566. TypeCode_AAAA:
  2567. begin
  2568. if TargetNode.RRs.Items[RRIndex] is TIdRR_AAAA then begin
  2569. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2570. end;
  2571. end;
  2572. TypeCode_NS:
  2573. begin
  2574. if TargetNode.RRs.Items[RRIndex] is TIdRR_NS then begin
  2575. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_NS).NSDName);
  2576. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2577. end;
  2578. end;
  2579. TypeCode_MD:
  2580. begin
  2581. if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
  2582. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
  2583. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2584. end;
  2585. end;
  2586. TypeCode_MF:
  2587. begin
  2588. if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
  2589. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
  2590. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2591. end;
  2592. end;
  2593. TypeCode_CName:
  2594. begin
  2595. if TargetNode.RRs.Items[RRIndex] is TIdRR_CName then begin
  2596. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_CName).CName);
  2597. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2598. end;
  2599. end;
  2600. TypeCode_SOA:
  2601. begin
  2602. if TargetNode.RRs.Items[RRIndex] is TIdRR_SOA then begin
  2603. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_SOA).MName);
  2604. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_SOA).RName);
  2605. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2606. end;
  2607. end;
  2608. TypeCode_MB:
  2609. begin
  2610. if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
  2611. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
  2612. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2613. end;
  2614. end;
  2615. TypeCode_MG:
  2616. begin
  2617. if TargetNode.RRs.Items[RRIndex] is TIdRR_MG then begin
  2618. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MG).MGMName);
  2619. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2620. end;
  2621. end;
  2622. TypeCode_MR:
  2623. begin
  2624. if TargetNode.RRs.Items[RRIndex] is TIdRR_MR then begin
  2625. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MR).NewName);
  2626. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2627. end;
  2628. end;
  2629. TypeCode_NULL:
  2630. begin
  2631. {
  2632. if TargetNode.RRs.Items[RRIndex] is TIdRR_NULL then begin
  2633. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2634. end;
  2635. }
  2636. end;
  2637. TypeCode_WKS:
  2638. begin
  2639. if TargetNode.RRs.Items[RRIndex] is TIdRR_WKS then begin
  2640. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2641. end;
  2642. end;
  2643. TypeCode_PTR:
  2644. begin
  2645. if TargetNode.RRs.Items[RRIndex] is TIdRR_PTR then begin
  2646. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2647. end;
  2648. end;
  2649. TypeCode_HINFO:
  2650. begin
  2651. if TargetNode.RRs.Items[RRIndex] is TIdRR_HINFO then begin
  2652. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2653. end;
  2654. end;
  2655. TypeCode_MINFO:
  2656. begin
  2657. if TargetNode.RRs.Items[RRIndex] is TIdRR_MINFO then begin
  2658. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2659. end;
  2660. end;
  2661. TypeCode_MX:
  2662. begin
  2663. if TargetNode.RRs.Items[RRIndex] is TIdRR_MX then begin
  2664. CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MX).Exchange);
  2665. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2666. end;
  2667. end;
  2668. TypeCode_TXT:
  2669. begin
  2670. if TargetNode.RRs.Items[RRIndex] is TIdRR_TXT then begin
  2671. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2672. end;
  2673. end;
  2674. TypeCode_STAR:
  2675. begin
  2676. LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
  2677. end;
  2678. end;
  2679. end;
  2680. if BytesToString(LocalAnswer) = 'Error' then begin {do not localize}
  2681. Stop := True;
  2682. end else begin
  2683. if LocalAnswer <> nil then begin
  2684. AppendBytes(Answer, LocalAnswer);
  2685. if TargetNode.RRs.Items[RRIndex] is TIdRR_NS then begin
  2686. if IfMainQuestion then begin
  2687. Header.ANCount := Header.ANCount + 1;
  2688. end else begin
  2689. Header.NSCount := Header.NSCount + 1;
  2690. end;
  2691. end
  2692. else if IfMainQuestion then begin
  2693. Header.ANCount := Header.ANCount + 1;
  2694. end
  2695. else begin
  2696. Header.ARCount := Header.ARCount + 1;
  2697. end;
  2698. Header.Qr := iQr_Answer;
  2699. Header.AA := iAA_NotAuthoritative;
  2700. Header.RCode := iRCodeNoError;
  2701. end;
  2702. if RRIndex < (TargetNode.RRs.ItemNames.Count-1) then begin
  2703. Stop := False;
  2704. Inc(RRIndex);
  2705. end else begin
  2706. Stop := True;
  2707. end;
  2708. end;
  2709. end else begin
  2710. Stop := True;
  2711. end;
  2712. until (RRIndex = -1) or
  2713. (not ((not TextIsSame(TargetNode.RRs.ItemNames.Strings[RRIndex], QName)) xor
  2714. (not TextIsSame(TargetNode.RRs.ItemNames.Strings[RRIndex], Fetch(temp_QName, '.')))))
  2715. or Stop;
  2716. end;
  2717. // Search MoreAddrSearch it's added in 2004/7/15, but the need is
  2718. // found in 2004 Feb.
  2719. if MoreAddrSearch.Count > 0 then begin
  2720. for Count := 0 to MoreAddrSearch.Count -1 do begin
  2721. Server_Index := 0;
  2722. if Handed_DomainList.Count > 0 then begin
  2723. repeat
  2724. IsMyDomains := IndyPos(
  2725. LowerCase(Handed_DomainList.Strings[Server_Index]),
  2726. LowerCase(MoreAddrSearch.Strings[Count])) > 0;
  2727. Inc(Server_Index);
  2728. until IsMyDomains or (Server_Index > (Handed_DomainList.Count-1));
  2729. end else begin
  2730. IsMyDomains := False;
  2731. end;
  2732. if IsMyDomains then begin
  2733. ifAdditional := (QType <> TypeCode_A) or (QType <> TypeCode_AAAA);
  2734. //Search A record first.
  2735. // Main, Cache, Additional, Wildcard
  2736. InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_A, LocalAnswer, True, False, ifAdditional, False);
  2737. if LocalAnswer = nil then begin
  2738. temp := MoreAddrSearch.Strings[Count];
  2739. Fetch(temp, '.');
  2740. temp := '*.' + temp;
  2741. InternalSearch(Header, temp, TypeCode_A, LocalAnswer, True, False, ifAdditional, True, MoreAddrSearch.Strings[Count]);
  2742. end;
  2743. TempAnswer := LocalAnswer;
  2744. // Search for AAAA also.
  2745. InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_AAAA, LocalAnswer, True, False, ifAdditional, True);
  2746. if LocalAnswer = nil then begin
  2747. temp := MoreAddrSearch.Strings[Count];
  2748. Fetch(temp, '.');
  2749. temp := '*.' + temp;
  2750. InternalSearch(Header, temp, TypeCode_AAAA, LocalAnswer, True, False, ifAdditional, True, MoreAddrSearch.Strings[Count]);
  2751. end;
  2752. AppendBytes(TempAnswer, LocalAnswer);
  2753. LocalAnswer := TempAnswer;
  2754. end else begin
  2755. // 找Cache
  2756. TempAnswer := LocalAnswer;
  2757. ifAdditional := (QType <> TypeCode_A) or (QType <> TypeCode_AAAA);
  2758. //Search A record first.
  2759. // Main, Cache, Additional, Wildcard
  2760. InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_A, LocalAnswer, True, True, ifAdditional, False);
  2761. if LocalAnswer = nil then begin
  2762. temp := MoreAddrSearch.Strings[Count];
  2763. Fetch(temp, '.');
  2764. temp := '*.' + temp;
  2765. InternalSearch(Header, temp, TypeCode_A, LocalAnswer, True, True, ifAdditional, True, MoreAddrSearch.Strings[Count]);
  2766. end;
  2767. AppendBytes(TempAnswer, LocalAnswer);
  2768. LocalAnswer := TempAnswer;
  2769. // Search for AAAA also.
  2770. InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_AAAA, LocalAnswer, True, True, ifAdditional, True);
  2771. if LocalAnswer <> nil then begin
  2772. AppendBytes(TempAnswer, LocalAnswer);
  2773. LocalAnswer := TempAnswer;
  2774. end;
  2775. Answer := LocalAnswer;
  2776. end;
  2777. end;
  2778. end;
  2779. end;
  2780. finally
  2781. MoreAddrSearch.Free;
  2782. end;
  2783. end;
  2784. { TIdDNSServer }
  2785. constructor TIdDNSServer.Create(AOwner: TComponent);
  2786. begin
  2787. inherited Create(AOwner);
  2788. FAccessList := TStringList.Create;
  2789. FUDPTunnel := TIdDNS_UDPServer.Create(Self);
  2790. FTCPTunnel := TIdDNS_TCPServer.Create(Self);
  2791. FBindings := TIdSocketHandles.Create(Self);
  2792. FTCPTunnel.DefaultPort := IdPORT_DOMAIN;
  2793. FUDPTunnel.DefaultPort := IdPORT_DOMAIN;
  2794. ServerType := stPrimary;
  2795. BackupDNSMap := TIdDNSMap.Create(FUDPTunnel);
  2796. end;
  2797. destructor TIdDNSServer.Destroy;
  2798. begin
  2799. FAccessList.Free;
  2800. FUDPTunnel.Free;
  2801. FTCPTunnel.Free;
  2802. FBindings.Free;
  2803. BackupDNSMap.Free;
  2804. inherited Destroy;
  2805. end;
  2806. procedure TIdDNSServer.CheckIfExpire(Sender: TObject);
  2807. begin
  2808. end;
  2809. procedure TIdDNSServer.SetAccessList(const Value: TStrings);
  2810. begin
  2811. FAccessList.Assign(Value);
  2812. FTCPTunnel.AccessList.Assign(Value);
  2813. end;
  2814. procedure TIdDNSServer.SetActive(const Value: Boolean);
  2815. var
  2816. Count : Integer;
  2817. DNSMap : TIdDomainNameServerMapping;
  2818. begin
  2819. FActive := Value;
  2820. FUDPTunnel.Active := Value;
  2821. if ServerType = stSecondary then begin
  2822. TCPTunnel.Active := False;
  2823. // TODO: should this loop only be run if Value=True?
  2824. for Count := 0 to BackupDNSMap.Count-1 do begin
  2825. DNSMap := BackupDNSMap.Items[Count];
  2826. DNSMap.CheckScheduler.Start;
  2827. end;
  2828. end else begin
  2829. TCPTunnel.Active := Value;
  2830. end;
  2831. end;
  2832. procedure TIdDNSServer.SetBindings(const Value: TIdSocketHandles);
  2833. begin
  2834. FBindings.Assign(Value);
  2835. FUDPTunnel.Bindings.Assign(Value);
  2836. FTCPTunnel.Bindings.Assign(Value);
  2837. end;
  2838. procedure TIdDNSServer.SetTCPACLActive(const Value: Boolean);
  2839. begin
  2840. FTCPACLActive := Value;
  2841. TCPTunnel.AccessControl := Value;
  2842. if Value then begin
  2843. FTCPTunnel.FAccessList.Assign(FAccessList);
  2844. end else begin
  2845. FTCPTunnel.FAccessList.Clear;
  2846. end;
  2847. end;
  2848. procedure TIdDNSServer.TimeToUpdateNodeData(Sender: TObject);
  2849. var
  2850. Resolver : TIdDNSResolver;
  2851. Count : Integer;
  2852. begin
  2853. Resolver := TIdDNSResolver.Create(Self);
  2854. try
  2855. Resolver.Host := UDPTunnel.RootDNS_NET.Strings[0];
  2856. Resolver.QueryType := [qtAXFR];
  2857. Resolver.Resolve((Sender as TIdDNTreeNode).FullName);
  2858. for Count := 0 to Resolver.QueryResult.Count-1 do begin
  2859. UDPTunnel.UpdateTree(UDPTunnel.Handed_Tree, Resolver.QueryResult.Items[Count]);
  2860. end;
  2861. finally
  2862. Resolver.Free;
  2863. end;
  2864. end;
  2865. { TIdDNS_TCPServer }
  2866. constructor TIdDNS_TCPServer.Create(AOwner: TComponent);
  2867. begin
  2868. inherited Create(AOwner);
  2869. FAccessList := TStringList.Create;
  2870. end;
  2871. destructor TIdDNS_TCPServer.Destroy;
  2872. begin
  2873. FAccessList.Free;
  2874. inherited Destroy;
  2875. end;
  2876. procedure TIdDNS_TCPServer.DoConnect(AContext: TIdContext);
  2877. var
  2878. Answer, Data, Question: TIdBytes;
  2879. QName, QLabel, QResult, PeerIP : string;
  2880. LData, QPos, LLength : Integer;
  2881. TestHeader : TDNSHeader;
  2882. procedure GenerateAXFRData;
  2883. begin
  2884. TestHeader := TDNSHeader.Create;
  2885. try
  2886. TestHeader.ParseQuery(Data);
  2887. if TestHeader.QDCount > 0 then begin
  2888. // parse the question.
  2889. QPos := 13;
  2890. QLabel := '';
  2891. QName := '';
  2892. repeat
  2893. LLength := Byte(Data[QPos]);
  2894. Inc(QPos);
  2895. QLabel := BytesToString(Data, QPos, LLength);
  2896. Inc(QPos, LLength);
  2897. QName := QName + QLabel + '.';
  2898. until (QPos >= LData) or (Data[QPos] = 0);
  2899. Question := Copy(Data, 13, Length(Data)-12);
  2900. QResult := TIdDNSServer(Owner).UDPTunnel.AXFR(TestHeader, QName, Answer);
  2901. end;
  2902. finally
  2903. TestHeader.Free;
  2904. end;
  2905. end;
  2906. procedure GenerateAXFRRefuseData;
  2907. begin
  2908. TestHeader := TDNSHeader.Create;
  2909. try
  2910. TestHeader.ParseQuery(Data);
  2911. TestHeader.Qr := iQr_Answer;
  2912. TestHeader.RCode := iRCodeRefused;
  2913. Answer := TestHeader.GenerateBinaryHeader;
  2914. finally
  2915. TestHeader.Free;
  2916. end;
  2917. end;
  2918. begin
  2919. inherited DoConnect(AContext);
  2920. LData := AContext.Connection.IOHandler.ReadInt16;
  2921. SetLength(Data, 0);
  2922. // RLebeau - why not use ReadBuffer() here?
  2923. // Dennies - Sure, in older version, my concern is for real time generate system
  2924. // might not generate the data with correct data size we expect.
  2925. AContext.Connection.IOHandler.ReadBytes(Data, LData);
  2926. {for Count := 1 to LData do begin
  2927. AppendByte(Data, AThread.Connection.IOHandler.ReadByte);
  2928. end;
  2929. }
  2930. // PeerIP is ip address.
  2931. PeerIP := AContext.Binding.PeerIP;
  2932. if AccessControl and (AccessList.IndexOf(PeerIP) = -1) then begin
  2933. GenerateAXFRRefuseData;
  2934. end else begin
  2935. GenerateAXFRData;
  2936. end;
  2937. if Length(Answer) > 32767 then begin
  2938. SetLength(Answer, 32767);
  2939. end;
  2940. AContext.Connection.IOHandler.Write(Int16(Length(Answer)));
  2941. AContext.Connection.IOHandler.Write(Answer);
  2942. end;
  2943. procedure TIdDNS_TCPServer.SetAccessList(const Value: TStrings);
  2944. begin
  2945. FAccessList.Assign(Value);
  2946. end;
  2947. { TIdDomainExpireCheckThread }
  2948. procedure TIdDomainExpireCheckThread.Run;
  2949. var
  2950. LInterval, LStep: Integer;
  2951. begin
  2952. LInterval := FInterval;
  2953. while LInterval > 0 do begin
  2954. LStep := IndyMin(LInterval, 500);
  2955. IndySleep(LStep);
  2956. Dec(LInterval, LStep);
  2957. if Terminated then begin
  2958. Exit;
  2959. end;
  2960. if Assigned(FTimerEvent) then begin
  2961. Synchronize(TimerEvent);
  2962. end;
  2963. end;
  2964. end;
  2965. procedure TIdDomainExpireCheckThread.TimerEvent;
  2966. begin
  2967. if Assigned(FTimerEvent) then begin
  2968. FTimerEvent(FSender);
  2969. end;
  2970. end;
  2971. { TIdDomainNameServerMapping }
  2972. constructor TIdDomainNameServerMapping.Create(AList : TIdDNSMap);
  2973. begin
  2974. inherited Create;
  2975. CheckScheduler := TIdDomainExpireCheckThread.Create;
  2976. CheckScheduler.FInterval := 100000;
  2977. CheckScheduler.FSender := Self;
  2978. CheckScheduler.FDomain := DomainName;
  2979. CheckScheduler.FHost := Host;
  2980. CheckScheduler.FTimerEvent := SyncAndUpdate;
  2981. FList := List;
  2982. FBusy := False;
  2983. end;
  2984. destructor TIdDomainNameServerMapping.Destroy;
  2985. begin
  2986. if Assigned(CheckScheduler) then
  2987. begin
  2988. //Self.CheckScheduler.TerminateAndWaitFor;
  2989. CheckScheduler.Terminate;
  2990. CheckScheduler.Free;
  2991. end;
  2992. inherited Destroy;
  2993. end;
  2994. procedure TIdDomainNameServerMapping.SetHost(const Value: string);
  2995. begin
  2996. if (not IsValidIP(Value)) and (not IsValidIPv6(Value)) then begin
  2997. raise EIdDNSServerSettingException.Create(RSDNSServerSettingError_MappingHostError);
  2998. end;
  2999. FHost := Value;
  3000. end;
  3001. procedure TIdDomainNameServerMapping.SetInterval(const Value: UInt32);
  3002. begin
  3003. FInterval := Value;
  3004. CheckScheduler.FInterval := Value;
  3005. end;
  3006. procedure TIdDomainNameServerMapping.SyncAndUpdate(Sender: TObject);
  3007. //Todo - Dennies Chang should append axfr and update Tree.
  3008. var
  3009. Resolver : TIdDNSResolver;
  3010. RR : TResultRecord;
  3011. TNode : TIdDNTreeNode;
  3012. Server : TIdDNS_UDPServer;
  3013. NeedUpdated, NotThis : Boolean;
  3014. Count, TIndex : Integer;
  3015. RRName : string;
  3016. begin
  3017. if FBusy then begin
  3018. Exit;
  3019. end;
  3020. FBusy := True;
  3021. try
  3022. Resolver := TIdDNSResolver.Create(nil);
  3023. try
  3024. Resolver.Host := Host;
  3025. Resolver.QueryType := [qtAXFR];
  3026. Resolver.Resolve(DomainName);
  3027. if Resolver.QueryResult.Count = 0 then begin
  3028. raise EIdDNSServerSyncException.Create(RSDNSServerAXFRError_QuerySequenceError);
  3029. end;
  3030. RR := Resolver.QueryResult.Items[0];
  3031. if RR.RecType <> qtSOA then begin
  3032. raise EIdDNSServerSyncException.Create(RSDNSServerAXFRError_QuerySequenceError);
  3033. end;
  3034. Server := List.Server;
  3035. Interval := TSOARecord(RR).Expire * 1000;
  3036. {
  3037. //Update MyDomain
  3038. if not TextEndsWith(RR.Name, '.') then begin
  3039. RRName := RR.Name + '.';
  3040. end;
  3041. }
  3042. if Server.Handed_DomainList.IndexOf(RR.Name) = -1 then begin
  3043. Server.Handed_DomainList.Add(RR.Name);
  3044. end;
  3045. TNode := Server.SearchTree(Server.Handed_Tree, RR.Name, TypeCode_SOA);
  3046. if TNode = nil then begin
  3047. NeedUpdated := True;
  3048. end else begin
  3049. RRName := RRName;
  3050. RRName := Fetch(RRName, '.');
  3051. TIndex := TNode.RRs.ItemNames.IndexOf(RR.Name);
  3052. NotThis := True;
  3053. while (TIndex > -1) and (TIndex <= (TNode.RRs.Count-1)) and
  3054. (TNode.RRs.Items[TIndex].RRName = RR.Name) and NotThis do
  3055. begin
  3056. NotThis := not (TNode.RRs.Items[TIndex] is TIdRR_SOA);
  3057. Inc(TIndex);
  3058. end;
  3059. if not NotThis then begin
  3060. Dec(TIndex);
  3061. NeedUpdated := (TNode.RRs.Items[TIndex] as TIdRR_SOA).Serial = IntToStr(TSOARecord(RR).Serial);
  3062. end else begin
  3063. NeedUpdated := True;
  3064. end;
  3065. end;
  3066. if NeedUpdated then begin
  3067. if TNode <> nil then begin
  3068. Server.Handed_Tree.RemoveChild(Server.Handed_Tree.IndexByNode(TNode));
  3069. end;
  3070. for Count := 0 to Resolver.QueryResult.Count-1 do begin
  3071. RR := Resolver.QueryResult.Items[Count];
  3072. Server.UpdateTree(Server.Handed_Tree, RR);
  3073. end;
  3074. end;
  3075. finally
  3076. Resolver.Free;
  3077. end;
  3078. finally
  3079. FBusy := False;
  3080. end;
  3081. end;
  3082. { TIdDNSMap }
  3083. constructor TIdDNSMap.Create(Server: TIdDNS_UDPServer);
  3084. begin
  3085. inherited Create;
  3086. FServer := Server;
  3087. end;
  3088. {$IFNDEF USE_OBJECT_ARC}
  3089. destructor TIdDNSMap.Destroy;
  3090. var
  3091. I : Integer;
  3092. DNSMP : TIdDomainNameServerMapping;
  3093. begin
  3094. if Count > 0 then begin
  3095. for I := Count-1 downto 0 do begin
  3096. DNSMP := Items[I];
  3097. Delete(I);
  3098. DNSMP.Free;
  3099. end;
  3100. end;
  3101. inherited Destroy;
  3102. end;
  3103. {$ENDIF}
  3104. {$IFNDEF HAS_GENERICS_TObjectList}
  3105. function TIdDNSMap.GetItem(Index: Integer): TIdDomainNameServerMapping;
  3106. begin
  3107. Result := TIdDomainNameServerMapping(inherited GetItem(Index));
  3108. end;
  3109. procedure TIdDNSMap.SetItem(Index: Integer; const Value: TIdDomainNameServerMapping);
  3110. begin
  3111. inherited SetItem(Index, Value);
  3112. end;
  3113. {$ENDIF}
  3114. procedure TIdDNSMap.SetServer(const Value: TIdDNS_UDPServer);
  3115. begin
  3116. FServer := Value;
  3117. end;
  3118. { TIdDNS_ProcessThread }
  3119. constructor TIdDNS_ProcessThread.Create(ACreateSuspended: Boolean;
  3120. Data: TIdBytes; MainBinding, Binding: TIdSocketHandle;
  3121. Server: TIdDNS_UDPServer);
  3122. begin
  3123. inherited Create(ACreateSuspended);
  3124. FMyData := nil;
  3125. FData := Data;
  3126. FMyBinding := Binding;
  3127. FMainBinding := MainBinding;
  3128. FServer := Server;
  3129. FreeOnTerminate := True;
  3130. end;
  3131. procedure TIdDNS_ProcessThread.ComposeErrorResult(var VFinal: TIdBytes;
  3132. OriginalHeader: TDNSHeader; OriginalQuestion : TIdBytes;
  3133. ErrorStatus: Integer);
  3134. begin
  3135. case ErrorStatus of
  3136. iRCodeQueryNotImplement :
  3137. begin
  3138. OriginalHeader.Qr := iQr_Answer;
  3139. OriginalHeader.RCode := iRCodeNotImplemented;
  3140. VFinal := OriginalHeader.GenerateBinaryHeader;
  3141. AppendBytes(VFinal, OriginalQuestion, 12);
  3142. end;
  3143. iRCodeQueryNotFound :
  3144. begin
  3145. OriginalHeader.Qr := iQr_Answer;
  3146. OriginalHeader.RCode := iRCodeNameError;
  3147. OriginalHeader.ANCount := 0;
  3148. VFinal := OriginalHeader.GenerateBinaryHeader;
  3149. //VFinal := VFinal;
  3150. end;
  3151. end;
  3152. end;
  3153. destructor TIdDNS_ProcessThread.Destroy;
  3154. begin
  3155. FServer := nil;
  3156. FMainBinding := nil;
  3157. if Assigned(FMyBinding) then begin
  3158. FMyBinding.CloseSocket;
  3159. FMyBinding.Free;
  3160. end;
  3161. FMyData.Free;
  3162. inherited Destroy;
  3163. end;
  3164. procedure TIdDNS_ProcessThread.QueryDomain;
  3165. var
  3166. QName, QLabel, RString : string;
  3167. Temp, ExternalQuery, Answer, FinalResult : TIdBytes;
  3168. DNSHeader_Processing : TDNSHeader;
  3169. QType, QClass : UInt16;
  3170. QPos, QLength, LLength : Integer;
  3171. ABinding: TIdSocketHandle;
  3172. begin
  3173. ExternalQuery := FData;
  3174. ABinding := MyBinding;
  3175. Temp := Copy(FData, 0, Length(FData));
  3176. SetLength(FinalResult, 0);
  3177. QType := TypeCode_A;
  3178. if Length(FData) >= 12 then begin
  3179. DNSHeader_Processing := TDNSHeader.Create;
  3180. try
  3181. // RLebeau: this does not make sense to me. ParseQuery() always returns
  3182. // 0 when the data length is >= 12 unless an exception is raised, which
  3183. // should only happen if the GStack object is invalid...
  3184. //
  3185. if DNSHeader_Processing.ParseQuery(ExternalQuery) <> 0 then begin
  3186. FServer.DoAfterQuery(ABinding, DNSHeader_Processing, Temp, RString, ExternalQuery);
  3187. AppendBytes(FinalResult, Temp);
  3188. end else begin
  3189. if DNSHeader_Processing.QDCount > 0 then begin
  3190. QPos := 12; //13; Modified in Dec. 13, 2004 by Dennies
  3191. QLength := Length(ExternalQuery);
  3192. if QLength > 12 then begin
  3193. QName := '';
  3194. repeat
  3195. SetLength(Answer, 0);
  3196. LLength := ExternalQuery[QPos];
  3197. Inc(QPos);
  3198. QLabel := BytesToString(ExternalQuery, QPos, LLength);
  3199. Inc(QPos, LLength);
  3200. QName := QName + QLabel + '.';
  3201. until (QPos >= QLength) or (ExternalQuery[QPos] = 0);
  3202. Inc(QPos);
  3203. QType := GStack.NetworkToHost(TwoByteToUInt16(ExternalQuery[QPos], ExternalQuery[QPos + 1]));
  3204. Inc(QPos, 2);
  3205. QClass := GStack.NetworkToHost(TwoByteToUInt16(ExternalQuery[QPos], ExternalQuery[QPos + 1]));
  3206. FServer.DoBeforeQuery(ABinding, DNSHeader_Processing, Temp);
  3207. RString := CompleteQuery(DNSHeader_Processing, QName, ExternalQuery, Answer, QType, QClass, nil);
  3208. if RString = cRCodeQueryNotImplement then begin
  3209. ComposeErrorResult(FinalResult, DNSHeader_Processing, ExternalQuery, iRCodeQueryNotImplement);
  3210. end
  3211. else if (RString = cRCodeQueryReturned) then begin
  3212. FinalResult := Answer;
  3213. end
  3214. else if (RString = cRCodeQueryNotFound) or (RString = cRCodeQueryCacheFindError) then begin
  3215. ComposeErrorResult(FinalResult, DNSHeader_Processing, ExternalQuery, iRCodeQueryNotFound);
  3216. end
  3217. else begin
  3218. FinalResult := CombineAnswer(DNSHeader_Processing, ExternalQuery, Answer);
  3219. end;
  3220. FServer.DoAfterQuery(ABinding, DNSHeader_Processing, FinalResult, RString, Temp);
  3221. //AppendString(FinalResult, Temp);
  3222. end;
  3223. end;
  3224. end;
  3225. finally
  3226. try
  3227. FData := FinalResult;
  3228. FServer.DoAfterSendBack(ABinding, DNSHeader_Processing, FinalResult, RString, ExternalQuery);
  3229. if (FServer.CacheUnknowZone) and
  3230. (RString <> cRCodeQueryCacheFindError) and
  3231. (RString <> cRCodeQueryCacheOK) and
  3232. (RString <> cRCodeQueryOK) and
  3233. (RString <> cRCodeQueryNotImplement) then
  3234. begin
  3235. FServer.SaveToCache(FinalResult, QName, QType);
  3236. FServer.DoAfterCacheSaved(Self.FServer.FCached_Tree);
  3237. end;
  3238. finally
  3239. DNSHeader_Processing.Free;
  3240. end;
  3241. end;
  3242. end;
  3243. end;
  3244. procedure TIdDNS_ProcessThread.Run;
  3245. begin
  3246. try
  3247. QueryDomain;
  3248. SendData;
  3249. finally
  3250. Stop;
  3251. Terminate;
  3252. end;
  3253. end;
  3254. procedure TIdDNS_ProcessThread.SetMyBinding(const Value: TIdSocketHandle);
  3255. begin
  3256. FMyBinding := Value;
  3257. end;
  3258. procedure TIdDNS_ProcessThread.SetMyData(const Value: TStream);
  3259. begin
  3260. FMyData := Value;
  3261. end;
  3262. procedure TIdDNS_ProcessThread.SetServer(const Value: TIdDNS_UDPServer);
  3263. begin
  3264. FServer := Value;
  3265. end;
  3266. function TIdDNS_ProcessThread.CombineAnswer(Header: TDNSHeader; const EQuery, Answer: TIdBytes): TIdBytes;
  3267. begin
  3268. Result := Header.GenerateBinaryHeader;
  3269. AppendBytes(Result, EQuery, 12);
  3270. AppendBytes(Result, Answer);
  3271. end;
  3272. procedure TIdDNS_ProcessThread.ExternalSearch(ADNSResolver: TIdDNSResolver; Header: TDNSHeader;
  3273. Question: TIdBytes; var Answer: TIdBytes);
  3274. var
  3275. Server_Index : Integer;
  3276. MyDNSResolver : TIdDNSResolver;
  3277. begin
  3278. Server_Index := 0;
  3279. if ADNSResolver = nil then begin
  3280. MyDNSResolver := TIdDNSResolver.Create;
  3281. MyDNSResolver.WaitingTime := 2000;
  3282. end else
  3283. begin
  3284. MyDNSResolver := ADNSResolver;
  3285. end;
  3286. try
  3287. repeat
  3288. MyDNSResolver.Host := FServer.RootDNS_NET.Strings[Server_Index];
  3289. try
  3290. MyDNSResolver.InternalQuery := Question;
  3291. MyDNSResolver.Resolve('');
  3292. Answer := MyDNSResolver.PlainTextResult;
  3293. except
  3294. // Todo: Create DNS server interal resolver error.
  3295. on EIdDnsResolverError do
  3296. begin
  3297. //Empty Event, for user to custom the event handle.
  3298. end;
  3299. on EIdSocketError do
  3300. begin
  3301. end;
  3302. else
  3303. begin
  3304. end;
  3305. end;
  3306. Inc(Server_Index);
  3307. until (Server_Index >= FServer.RootDNS_NET.Count) or (Answer <> nil);
  3308. finally
  3309. if ADNSResolver = nil then begin
  3310. MyDNSResolver.Free;
  3311. end;
  3312. end;
  3313. end;
  3314. procedure TIdDNS_ProcessThread.InternalSearch(Header: TDNSHeader; QName: string; QType: UInt16;
  3315. var Answer: TIdBytes; IfMainQuestion: boolean; IsSearchCache: Boolean = False;
  3316. IsAdditional: boolean = false; IsWildCard : boolean = false;
  3317. WildCardOrgName: string = '');
  3318. begin
  3319. end;
  3320. procedure TIdDNS_ProcessThread.SaveToCache(ResourceRecord: TIdBytes; QueryName: string; OriginalQType: UInt16);
  3321. var
  3322. TempResolver : TIdDNSResolver;
  3323. Count : Integer;
  3324. TNode : TIdDNTreeNode;
  3325. RR_Err : TIdRR_Error;
  3326. begin
  3327. TempResolver := TIdDNSResolver.Create(nil);
  3328. try
  3329. // RLebeau: FillResultWithOutCheckId() is deprecated, but not using FillResult()
  3330. // here yet because it validates the DNSHeader.RCode, and I do not know if that
  3331. // is needed here. I don't want to break this logic...
  3332. TempResolver.FillResultWithOutCheckId(ResourceRecord);
  3333. if TempResolver.DNSHeader.ANCount > 0 then begin
  3334. for Count := 0 to TempResolver.QueryResult.Count-1 do begin
  3335. FServer.UpdateTree(FServer.Cached_Tree, TempResolver.QueryResult.Items[Count]);
  3336. end; // for loop
  3337. end else begin
  3338. TNode := Self.SearchTree(FServer.Cached_Tree, QueryName, TypeCode_Error);
  3339. if TNode = nil then begin
  3340. RR_Err := TIdRR_Error.Create;
  3341. RR_Err.RRName := QueryName;
  3342. RR_Err.TTL := 600;
  3343. FServer.UpdateTree(FServer.Cached_Tree, RR_Err);
  3344. end;
  3345. end;
  3346. finally
  3347. TempResolver.Free;
  3348. end;
  3349. end;
  3350. function TIdDNS_ProcessThread.SearchTree(Root: TIdDNTreeNode; QName: String; QType: UInt16): TIdDNTreeNode;
  3351. var
  3352. RRIndex : integer;
  3353. NodeCursor : TIdDNTreeNode;
  3354. NameLabels : TStrings;
  3355. OneNode, FullName : string;
  3356. Found : Boolean;
  3357. begin
  3358. Result := nil;
  3359. NameLabels := TStringList.Create;
  3360. try
  3361. FullName := QName;
  3362. NodeCursor := Root;
  3363. Found := False;
  3364. repeat
  3365. OneNode := Fetch(FullName, '.');
  3366. if OneNode <> '' then begin
  3367. NameLabels.Add(OneNode);
  3368. end;
  3369. until FullName = '';
  3370. repeat
  3371. IndySleep(0);
  3372. if QType <> TypeCode_SOA then begin
  3373. RRIndex := NodeCursor.ChildIndex.IndexOf(NameLabels.Strings[NameLabels.Count - 1]);
  3374. if RRIndex <> -1 then begin
  3375. NameLabels.Delete(NameLabels.Count - 1);
  3376. NodeCursor := NodeCursor.Children[RRIndex];
  3377. if NameLabels.Count = 1 then begin
  3378. Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
  3379. end else begin
  3380. Found := NameLabels.Count = 0;
  3381. end;
  3382. end
  3383. else if NameLabels.Count = 1 then begin
  3384. Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
  3385. if not Found then begin
  3386. NameLabels.Clear;
  3387. end;
  3388. end
  3389. else begin
  3390. NameLabels.Clear;
  3391. end;
  3392. end else begin
  3393. RRIndex := NodeCursor.ChildIndex.IndexOf(NameLabels.Strings[NameLabels.Count - 1]);
  3394. if RRIndex <> -1 then begin
  3395. NameLabels.Delete(NameLabels.Count - 1);
  3396. NodeCursor := NodeCursor.Children[RRIndex];
  3397. if NameLabels.Count = 1 then begin
  3398. Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
  3399. end else begin
  3400. Found := NameLabels.Count = 0;
  3401. end;
  3402. end
  3403. else if NameLabels.Count = 1 then begin
  3404. Found := (NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1);
  3405. if not Found then begin
  3406. NameLabels.Clear;
  3407. end;
  3408. end
  3409. else begin
  3410. NameLabels.Clear;
  3411. end;
  3412. end;
  3413. until (NameLabels.Count = 0) or Found;
  3414. if Found then begin
  3415. Result := NodeCursor;
  3416. end;
  3417. finally
  3418. NameLabels.Free;
  3419. end;
  3420. end;
  3421. function TIdDNS_ProcessThread.CompleteQuery(DNSHeader: TDNSHeader;
  3422. Question: string; OriginalQuestion: TIdBytes; var Answer : TIdBytes;
  3423. QType, QClass : UInt16; DNSResolver : TIdDNSResolver) : string;
  3424. var
  3425. IsMyDomains : boolean;
  3426. LAnswer, TempAnswer, RRData: TIdBytes;
  3427. WildQuestion, TempDomain : string;
  3428. LIdx: Integer;
  3429. begin
  3430. // QClass = 1 => IN, we support only "IN" class now.
  3431. // QClass = 2 => CS,
  3432. // QClass = 3 => CH, we suppor "CHAOS" class now, but only "version.bind." info.
  3433. // from 2004/6/28
  3434. // QClass = 4 => HS.
  3435. RRData := nil;
  3436. TempAnswer := nil;
  3437. TempDomain := LowerCase(Question);
  3438. case QClass of
  3439. Class_IN :
  3440. begin
  3441. IsMyDomains := FServer.Handed_DomainList.IndexOf(TempDomain) > -1;
  3442. if not IsMyDomains then begin
  3443. Fetch(TempDomain, '.');
  3444. IsMyDomains := FServer.Handed_DomainList.IndexOf(TempDomain) > -1;
  3445. end;
  3446. if IsMyDomains then begin
  3447. FServer.InternalSearch(DNSHeader, Question, QType, LAnswer, True, False, False);
  3448. Answer := LAnswer;
  3449. if (QType in [TypeCode_A, TypeCode_AAAA]) and (Answer = nil) then begin
  3450. FServer.InternalSearch(DNSHeader, Question, TypeCode_CNAME, LAnswer, True, False, True);
  3451. if LAnswer <> nil then begin
  3452. AppendBytes(Answer, LAnswer);
  3453. end;
  3454. end;
  3455. WildQuestion := Question;
  3456. Fetch(WildQuestion, '.');
  3457. WildQuestion := '*.' + WildQuestion;
  3458. FServer.InternalSearch(DNSHeader, WildQuestion, QType, LAnswer, True, False, False, True, Question);
  3459. {
  3460. FServer.InternalSearch(DNSHeader, Question, QType, LAnswer, True, True, False);
  3461. }
  3462. if LAnswer <> nil then begin
  3463. AppendBytes(Answer, LAnswer);
  3464. end;
  3465. if Answer <> nil then begin
  3466. Result := cRCodeQueryOK;
  3467. end else begin
  3468. Result := cRCodeQueryNotFound;
  3469. end;
  3470. end else begin
  3471. FServer.InternalSearch(DNSHeader, Question, QType, Answer, True, True, False);
  3472. if (QType in [TypeCode_A, TypeCode_AAAA]) and (Answer = nil) then begin
  3473. FServer.InternalSearch(DNSHeader, Question, TypeCode_CNAME, LAnswer, True, True, False);
  3474. if LAnswer <> nil then begin
  3475. AppendBytes(Answer, LAnswer);
  3476. end;
  3477. end;
  3478. if Answer <> nil then begin
  3479. Result := cRCodeQueryCacheOK;
  3480. end else begin
  3481. //QType := TypeCode_Error;
  3482. FServer.InternalSearch(DNSHeader, Question, QType, Answer, True, True, False);
  3483. if BytesToString(Answer) = 'Error' then begin {do not localize}
  3484. Result := cRCodeQueryCacheFindError;
  3485. end else begin
  3486. FServer.ExternalSearch(DNSResolver, DNSHeader, OriginalQuestion, Answer);
  3487. if Answer <> nil then begin
  3488. Result := cRCodeQueryReturned;
  3489. end else begin
  3490. Result := cRCodeQueryNotImplement;
  3491. end;
  3492. end;
  3493. end;
  3494. end;
  3495. end;
  3496. Class_CHAOS :
  3497. begin
  3498. if TempDomain = 'version.bind.' then begin {do not localize}
  3499. if FServer.offerDNSVersion then begin
  3500. TempAnswer := DomainNameToDNSStr('version.bind.'); {do not localize}
  3501. RRData := NormalStrToDNSStr(FServer.DNSVersion);
  3502. SetLength(LAnswer, Length(TempAnswer) + (SizeOf(UInt16)*3) + SizeOf(UInt32) + Length(RRData));
  3503. CopyTIdBytes(TempAnswer, 0, LAnswer, 0, Length(TempAnswer));
  3504. LIdx := Length(TempAnswer);
  3505. CopyTIdUInt16(GStack.HostToNetwork(UInt16(TypeCode_TXT)), LAnswer, LIdx);
  3506. Inc(LIdx, SizeOf(UInt16));
  3507. CopyTIdUInt16(GStack.HostToNetwork(UInt16(Class_CHAOS)), LAnswer, LIdx);
  3508. Inc(LIdx, SizeOf(UInt16));
  3509. CopyTIdUInt32(GStack.HostToNetwork(UInt32(86400)), LAnswer, LIdx); {do not localize}
  3510. Inc(LIdx, SizeOf(UInt32));
  3511. CopyTIdUInt16(GStack.HostToNetwork(UInt16(Length(RRData))), LAnswer, LIdx);
  3512. Inc(LIdx, SizeOf(UInt16));
  3513. CopyTIdBytes(RRData, 0, LAnswer, LIdx, Length(RRData));
  3514. Answer := LAnswer;
  3515. DNSHeader.ANCount := 1;
  3516. DNSHeader.AA := 1;
  3517. Result := cRCodeQueryOK;
  3518. end else begin
  3519. Result := cRCodeQueryNotImplement;
  3520. end;
  3521. end else begin
  3522. Result := cRCodeQueryNotImplement;
  3523. end;
  3524. end;
  3525. else
  3526. begin
  3527. Result := cRCodeQueryNotImplement;
  3528. end;
  3529. end;
  3530. end;
  3531. procedure TIdDNS_ProcessThread.SendData;
  3532. begin
  3533. FServer.GlobalCS.Enter;
  3534. try
  3535. FMainBinding.SendTo(FMyBinding.PeerIP, FMyBinding.PeerPort, FData, FMyBinding.IPVersion);
  3536. finally
  3537. FServer.GlobalCS.Leave;
  3538. end;
  3539. end;
  3540. procedure TIdDNS_UDPServer.DoAfterCacheSaved(CacheRoot: TIdDNTreeNode);
  3541. begin
  3542. if Assigned(FOnAfterCacheSaved) then begin
  3543. FOnAfterCacheSaved(CacheRoot);
  3544. end;
  3545. end;
  3546. procedure TIdDNS_UDPServer.DoUDPRead(AThread: TIdUDPListenerThread;
  3547. const AData: TIdBytes; ABinding: TIdSocketHandle);
  3548. var
  3549. PThread : TIdDNS_ProcessThread;
  3550. BBinding : TIdSocketHandle;
  3551. Binded : Boolean;
  3552. begin
  3553. inherited DoUDPRead(AThread, AData, ABinding);
  3554. Binded := False;
  3555. BBinding := TIdSocketHandle.Create(nil);
  3556. try
  3557. BBinding.SetPeer(ABinding.PeerIP, ABinding.PeerPort, ABinding.IPVersion);
  3558. BBinding.IP := ABinding.IP;
  3559. repeat
  3560. try
  3561. BBinding.Port := 53;
  3562. BBinding.AllocateSocket(Id_SOCK_DGRAM);
  3563. Binded := True;
  3564. except
  3565. end;
  3566. until Binded;
  3567. PThread := TIdDNS_ProcessThread.Create(True, AData, ABinding, BBinding, Self);
  3568. except
  3569. BBinding.Free;
  3570. raise;
  3571. end;
  3572. PThread.Start;
  3573. end;
  3574. end.