IdDNSServer.pas 140 KB

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