| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073 |
- {
- $Project$
- $Workfile$
- $Revision$
- $DateUTC$
- $Id$
- This file is part of the Indy (Internet Direct) project, and is offered
- under the dual-licensing agreement described on the Indy website.
- (http://www.indyproject.org/)
- Copyright:
- (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
- $Log$
- Rev 1.40 3/4/2005 12:35:32 PM JPMugaas
- Removed some compiler warnings.
- Rev 1.39 2/9/2005 4:35:06 AM JPMugaas
- Should compile.
- Rev 1.38 2/8/05 6:13:02 PM RLebeau
- Updated to use new AppendString() function in IdGlobal unit
- Updated TIdDNS_ProcessThread.CompleteQuery() to use CopyTId...() functions
- instead of ToBytes() and AppendBytes().
- Rev 1.37 2005/1/25 下午 12:25:26 DChang
- Modify UpdateTree method, make the NS record can be save in the lower level
- node.
- Rev 1.36 2005/1/5 下午 04:21:06 DChang Version: 1.36
- Fix parsing procedure while processing TXT record, in pass version, double
- quota will not be processed, but now, any charector between 2 double quotas
- will be treated as TXT message.
- Rev 1.35 2004/12/15 下午 12:05:26 DChang Version: 1.35
- 1. Move UpdateTree to public section.
- 2. add DoUDPRead of TIdDNSServer.
- 3. Fix TIdDNS_ProcessThread.CompleteQuery and
- InternalQuery to fit Indy 10 Core.
- Rev 1.34 12/2/2004 4:23:50 PM JPMugaas
- Adjusted for changes in Core.
- Rev 1.33 2004.10.27 9:17:46 AM czhower
- For TIdStrings
- Rev 1.32 10/26/2004 9:06:32 PM JPMugaas
- Updated references.
- Rev 1.31 2004.10.26 1:06:26 PM czhower
- Further fixes for aliaser
- Rev 1.30 2004.10.26 12:01:32 PM czhower
- Resolved alias conflict.
- Rev 1.29 9/15/2004 4:59:52 PM DSiders
- Added localization comments.
- Rev 1.28 22/07/2004 18:14:22 ANeillans
- Fixed compile error.
- Rev 1.27 7/21/04 2:38:04 PM RLebeau
- Removed redundant string copying in TIdDNS_ProcessThread constructor and
- procedure QueryDomain() method
- Removed local variable from TIdDNS_ProcessThread.SendData(), not needed
- Rev 1.26 2004/7/21 下午 06:37:48 DChang
- Fix compile error in TIdDNS_ProcessThread.SendData, and mark a case statment
- to comments in TIdDNS_ProcessThread.SaveToCache.
- Rev 1.25 2004/7/19 下午 09:55:52 DChang
- 1. Move all textmoderecords to IdDNSCommon.pas
- 2. Making DNS Server load the domain definition file while DNS Server
- component is active.
- 3. Add a new event : OnAfterCacheSaved
- 4. Add Full name condition to indicate if a domain is empty
- (ConvertDNtoString)
- 5. Make Query request processed with independent thread.
- 6. Rewrite TIdDNSServer into multiple thread mode, all queries will search
- and assemble the answer, and then share the TIdSocketHandle to send answer
- back.
- 7. Add version information in TIdDNSServer, so class CHAOS can be taken, but
- only for the label : "version.bind.".
- 8. Fix TIdRR_TXT.BinQueryRecord, to make sure it can be parsed in DNS client.
- 9. Modify the AXFR function, reduce the response data size and quantity.
- 10. Move all TIdTextModeResourceRecord and derived classes to IdDNSCommon.pas
- Rev 1.24 7/8/04 11:43:54 PM RLebeau
- Updated TIdDNS_TCPServer.DoConnect() to use new BytesToString() parameters
- Rev 1.23 7/7/04 1:45:16 PM RLebeau
- Compiler fixes
- Rev 1.22 6/29/04 1:43:30 PM RLebeau
- Bug fixes for various property setters
- Rev 1.21 2004.05.20 1:39:32 PM czhower
- Last of the IdStream updates
- Rev 1.20 2004.03.01 9:37:06 PM czhower
- Fixed name conflicts for .net
- Rev 1.19 2004.02.07 5:03:32 PM czhower
- .net fixes.
- Rev 1.18 2/7/2004 5:39:44 AM JPMugaas
- IdDNSServer should compile in both DotNET and WIn32.
- Rev 1.17 2004.02.03 5:45:58 PM czhower
- Name changes
- Rev 1.16 1/22/2004 8:26:40 AM JPMugaas
- Ansi* calls changed.
- Rev 1.15 1/21/2004 2:12:48 PM JPMugaas
- InitComponent
- Rev 1.14 12/7/2003 8:07:26 PM VVassiliev
- string -> TIdBytes
- Rev 1.13 2003.10.24 10:38:24 AM czhower
- UDP Server todos
- Rev 1.12 10/19/2003 12:16:30 PM DSiders
- Added localization comments.
- Rev 1.11 2003.10.12 3:50:40 PM czhower
- Compile todos
- Rev 1.10 2003/5/14 上午 01:17:36 DChang
- Fix a flag named denoted in the function which check if a domain correct.
- Update the logic of UpdateTree functions (make them unified).
- Update the TextRecord function of all TIdRR_ classes, it checks if the RRName
- the same as FullName, if RRName = FullName, it will not append the Fullname
- to RRName.
- Rev 1.9 2003/5/10 上午 01:09:42 DChang
- Patch the domainlist update when axfr action.
- Rev 1.8 2003/5/9 上午 10:03:36 DChang
- Modify the sequence of records. To make sure when we resolve MX record, the
- mail host A record can be additional record section.
- Rev 1.7 2003/5/8 下午 08:11:34 DChang
- Add TIdDNSMap, TIdDomainNameServerMapping to monitor primary DNS, and
- detecting if the primary DNS record changed, it will update automatically if
- necessary.
- Rev 1.6 2003/5/2 下午 03:39:38 DChang
- Fix all compile warnings and hints.
- Rev 1.5 4/29/2003 08:26:30 PM DenniesChang
- Fix TIdDNSServer Create, the older version miss to create the FBindings.
- fix AXFR procedure, fully support BIND 8 AXFR procedures.
- Rev 1.4 4/28/2003 02:30:58 PM JPMugaas
- reverted back to the old one as the new one checked will not compile, has
- problametic dependancies on Contrs and Dialogs (both not permitted).
- Rev 1.3 04/28/2003 01:15:10 AM DenniesChang
- Rev 1.2 4/28/2003 07:00:18 AM JPMugaas
- Should now compile.
- Rev 1.0 11/14/2002 02:18:42 PM JPMugaas
- // Ver: 2003-04-28-0115
- // Combine TCP, UDP Tunnel into single TIdDNSServer component.
- // Update TIdDNSServer from TIdUDPServer to TComponent.
- // Ver: 2003-04-26-1810
- // Add AXFR command.
- // Ver: 2002-10-30-1253
- // Add TIdRR_AAAA class, RFC 1884 (Ipv6 AAAA)
- // and add the coresponding fix in TIdDNSServer, but left
- // external search option for future.
- // Ver: 2002-07-10-1610
- // Add a new event : OnAfterSendBack to handle all
- // data logged after query result is sent back to
- // the client.
- // Ver: 2002-05-27-0910
- // Add a check function in SOA loading function.
- // Ver: 2002-04-25-1530
- // IdDNSServer. Ver: 2002-03-12-0900
- // To-do: RFC 2136 Zone transfer must be implemented.
- // Add FindHandedNodeByName to pass the TIdDNTreeNode Object back.
- // Append a blank char when ClearQuota, to avoid the possible of
- // losting a field.
- // Add IdDNTree.SaveToFile
- // Fix SOA RRName assignment.
- // Fix PTRName RRName assignment.
- // Fix TIdDNTreeNode RemoveChild
- // IdDNSServer. Ver: 2002-02-26-1420
- // Convert the DN Tree Node type, earlier verison just
- // store the A, PTR in the upper domain node, current
- // version save SOA and its subdomain in upper node.
- //
- // Moreover, move Cached_Tree, Handed_Tree to public
- // section, for using convinent.
- //
- // I forget return CName data, fixed.
- // Seperate the seaching of Cache and handled tree into 2
- // parts with a flag.
- //IdDNSServer. Ver: 2002-02-24-1715
- // Move TIdDNSServer protected property RootDNS_NET to public
- //IdDNSServer. Ver: 2002-02-23-1800
- Original Programmer: Dennies Chang <[email protected]>
- No Copyright. Code is given to the Indy Pit Crew.
- This DNS Server supports only IN record, but not Chaos system.
- Most of resource records in DNS server was stored with text mode,
- event the TREE structure, it's just for convininet.
- Why I did it with this way is tring to increase the speed for
- implementation, with Delphi/Kylix internal class and object,
- we can promise the compatible in Windows and Linux.
- Started: Jan. 20, 2002.
- First Finished: Feb. 23, 2002.
- RFC 1035 WKS record is not implemented.
- ToDO: Load Master File automaticlly when DNS Server Active.
- ToDO: patch WKS record data type.
- ToDO: prepare a Tree Editor for DNS Server Construction. (optional)
- }
- unit IdDNSServer;
- interface
- {$i IdCompilerDefines.inc}
- uses
- Classes,
- IdContainers,
- IdAssignedNumbers,
- IdSocketHandle,
- IdGlobal,
- IdGlobalProtocols,
- IdBaseComponent,
- IdComponent,
- IdContext,
- IdUDPBase,
- IdExceptionCore,
- IdDNSResolver,
- IdUDPServer,
- IdCustomTCPServer,
- IdStackConsts,
- IdThread,
- IdDNSCommon;
- type
- TIdDomainExpireCheckThread = class(TIdThread)
- protected
- FInterval: UInt32;
- FSender: TObject;
- FTimerEvent: TNotifyEvent;
- FBusy : Boolean;
- FDomain : string;
- FHost : string;
- //
- procedure Run; override;
- procedure TimerEvent;
- end;
- // forward declaration.
- TIdDNSMap = class;
- TIdDNS_UDPServer = class;
- // This class is to record the mapping of Domain and its primary DNS IP
- TIdDomainNameServerMapping = class(TObject)
- private
- FHost: string;
- FDomainName: string;
- FBusy : Boolean;
- FInterval: UInt32;
- FList: TIdDNSMap;
- procedure SetHost(const Value: string);
- procedure SetInterval(const Value: UInt32);
- protected
- CheckScheduler : TIdDomainExpireCheckThread;
- property Interval : UInt32 read FInterval write SetInterval;
- property List : TIdDNSMap read FList write FList;
- public
- constructor Create(AList : TIdDNSMap);
- destructor Destroy; override;
- //You can not make methods and properties published in this class.
- //If you want to make properties publishes, this has to derrive from TPersistant
- //and be used by TPersistant in a published property.
- // published
- procedure SyncAndUpdate(Sender : TObject);
- property Host : string read FHost write SetHost;
- property DomainName : string read FDomainName write FDomainName;
- end;
- TIdDNSMap = class(TIdObjectList{$IFDEF HAS_GENERICS_TObjectList}<TIdDomainNameServerMapping>{$ENDIF})
- private
- FServer: TIdDNS_UDPServer;
- {$IFNDEF HAS_GENERICS_TObjectList}
- function GetItem(Index: Integer): TIdDomainNameServerMapping;
- procedure SetItem(Index: Integer; const Value: TIdDomainNameServerMapping);
- {$ENDIF}
- procedure SetServer(const Value: TIdDNS_UDPServer);
- public
- constructor Create(Server: TIdDNS_UDPServer);
- {$IFNDEF USE_OBJECT_ARC}
- destructor Destroy; override;
- {$ENDIF}
- property Server : TIdDNS_UDPServer read FServer write SetServer;
- {$IFNDEF HAS_GENERICS_TObjectList}
- property Items[Index: Integer]: TIdDomainNameServerMapping read GetItem write SetItem; default;
- {$ENDIF}
- end;
- TIdMWayTreeNodeClass = class of TIdMWayTreeNode;
- // TODO: derive from TObjectList instead and remove SubTree member?
- TIdMWayTreeNode = class(TObject)
- private
- SubTree : TIdObjectList{$IFDEF HAS_GENERICS_TObjectList}<TIdMWayTreeNode>{$ENDIF};
- FFundmentalClass: TIdMWayTreeNodeClass;
- function GetTreeNode(Index: Integer): TIdMWayTreeNode;
- procedure SetFundmentalClass(const Value: TIdMWayTreeNodeClass);
- procedure SetTreeNode(Index: Integer; const Value: TIdMWayTreeNode);
- public
- constructor Create(NodeClass : TIdMWayTreeNodeClass); virtual;
- destructor Destroy; override;
- property FundmentalClass : TIdMWayTreeNodeClass read FFundmentalClass write SetFundmentalClass;
- property Children[Index : Integer] : TIdMWayTreeNode read GetTreeNode write SetTreeNode;
- function AddChild : TIdMWayTreeNode;
- function InsertChild(Index : Integer) : TIdMWayTreeNode;
- procedure RemoveChild(Index : Integer);
- end;
- TIdDNTreeNode = class(TIdMWayTreeNode)
- private
- FCLabel : String;
- FRRs: TIdTextModeRRs;
- FChildIndex: TStrings;
- FParentNode: TIdDNTreeNode;
- FAutoSortChild: Boolean;
- procedure SetCLabel(const Value: String);
- procedure SetRRs(const Value: TIdTextModeRRs);
- function GetNode(Index: integer): TIdDNTreeNode;
- procedure SetNode(Index: integer; const Value: TIdDNTreeNode);
- procedure SetChildIndex(const Value: TStrings);
- function GetFullName: string;
- function ConvertToDNString : string;
- function DumpAllBinaryData(var RecordCount:integer) : TIdBytes;
- public
- property ParentNode : TIdDNTreeNode read FParentNode write FParentNode;
- property CLabel : String read FCLabel write SetCLabel;
- property RRs : TIdTextModeRRs read FRRs write SetRRs;
- property Children[Index : Integer] : TIdDNTreeNode read GetNode write SetNode;
- property ChildIndex : TStrings read FChildIndex write SetChildIndex;
- property AutoSortChild : Boolean read FAutoSortChild write FAutoSortChild;
- property FullName : string read GetFullName;
- constructor Create(AParentNode : TIdDNTreeNode); reintroduce;
- destructor Destroy; override;
- function AddChild : TIdDNTreeNode;
- function InsertChild(Index : Integer) : TIdDNTreeNode;
- procedure RemoveChild(Index : Integer);
- procedure SortChildren;
- procedure Clear;
- procedure SaveToFile(Filename : String);
- function IndexByLabel(CLabel : String): Integer;
- function IndexByNode(ANode : TIdDNTreeNode) : Integer;
- end;
- TIdDNS_TCPServer = class(TIdCustomTCPServer)
- protected
- FAccessList: TStrings;
- FAccessControl: Boolean;
- //
- procedure DoConnect(AContext: TIdContext); override;
- procedure SetAccessList(const Value: TStrings);
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- published
- property AccessList : TStrings read FAccessList write SetAccessList;
- property AccessControl : boolean read FAccessControl write FAccessControl;
- end;
- TIdDNS_ProcessThread = class(TIdThread)
- protected
- FMyBinding: TIdSocketHandle;
- FMainBinding: TIdSocketHandle;
- FMyData: TStream;
- FData : TIdBytes;
- FServer: TIdDNS_UDPServer;
- procedure SetMyBinding(const Value: TIdSocketHandle);
- procedure SetMyData(const Value: TStream);
- procedure SetServer(const Value: TIdDNS_UDPServer);
- procedure ComposeErrorResult(var VFinal: TIdBytes; OriginalHeader: TDNSHeader;
- OriginalQuestion : TIdBytes; ErrorStatus: Integer);
- function CombineAnswer(Header : TDNSHeader; const EQuery, Answer : TIdBytes): TIdBytes;
- procedure InternalSearch(Header: TDNSHeader; QName: string; QType: UInt16;
- var Answer: TIdBytes; IfMainQuestion: Boolean; IsSearchCache: Boolean = False;
- IsAdditional: Boolean = False; IsWildCard : Boolean = False;
- WildCardOrgName: string = '');
- procedure ExternalSearch(ADNSResolver: TIdDNSResolver; Header: TDNSHeader;
- Question: TIdBytes; var Answer: TIdBytes);
- function CompleteQuery(DNSHeader: TDNSHeader; Question: string;
- OriginalQuestion: TIdBytes; var Answer : TIdBytes; QType, QClass : UInt16;
- DNSResolver : TIdDNSResolver) : string;
- procedure SaveToCache(ResourceRecord : TIdBytes; QueryName : string; OriginalQType : UInt16);
- function SearchTree(Root : TIdDNTreeNode; QName : String; QType : UInt16): TIdDNTreeNode;
- procedure Run; override;
- procedure QueryDomain;
- procedure SendData;
- public
- property MyBinding : TIdSocketHandle read FMyBinding write SetMyBinding;
- property MyData: TStream read FMyData write SetMyData;
- property Server : TIdDNS_UDPServer read FServer write SetServer;
- constructor Create(ACreateSuspended: Boolean = True; Data : TIdBytes = nil;
- MainBinding : TIdSocketHandle = nil; Binding : TIdSocketHandle = nil;
- Server : TIdDNS_UDPServer = nil); reintroduce; overload;
- destructor Destroy; override;
- end;
- TIdDNSBeforeQueryEvent = procedure(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader; var ADNSQuery: TIdBytes) of object;
- TIdDNSAfterQueryEvent = procedure(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader; var QueryResult: TIdBytes; var ResultCode: string; Query : TIdBytes) of object;
- TIdDNSAfterCacheSaved = procedure(CacheRoot : TIdDNTreeNode) of object;
- TIdDNS_UDPServer = class(TIdUDPServer)
- private
- FBusy: Boolean;
- protected
- FAutoUpdateZoneInfo: Boolean;
- FZoneMasterFiles: TStrings;
- FRootDNS_NET: TStrings;
- FCacheUnknowZone: Boolean;
- FCached_Tree: TIdDNTreeNode;
- FHanded_Tree: TIdDNTreeNode;
- FHanded_DomainList: TStrings;
- FAutoLoadMasterFile: Boolean;
- FOnAfterQuery: TIdDNSAfterQueryEvent;
- FOnBeforeQuery: TIdDNSBeforeQueryEvent;
- FCS: TIdCriticalSection;
- FOnAfterSendBack: TIdDNSAfterQueryEvent;
- FOnAfterCacheSaved: TIdDNSAfterCacheSaved;
- FGlobalCS: TIdCriticalSection;
- FDNSVersion: string;
- FofferDNSVersion: Boolean;
- procedure DoBeforeQuery(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader;
- var ADNSQuery : TIdBytes); dynamic;
- procedure DoAfterQuery(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader;
- var QueryResult : TIdBytes; var ResultCode : String; Query : TIdBytes); dynamic;
- procedure DoAfterSendBack(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader;
- var QueryResult : TIdBytes; var ResultCode : String; Query : TIdBytes); dynamic;
- procedure DoAfterCacheSaved(CacheRoot : TIdDNTreeNode); dynamic;
- procedure SetZoneMasterFiles(const Value: TStrings);
- procedure SetRootDNS_NET(const Value: TStrings);
- procedure SetHanded_DomainList(const Value: TStrings);
- procedure InternalSearch(Header: TDNSHeader; QName: string; QType: UInt16;
- var Answer: TIdBytes; IfMainQuestion: boolean; IsSearchCache: Boolean = False;
- IsAdditional: Boolean = False; IsWildCard : Boolean = False;
- WildCardOrgName: string = '');
- procedure ExternalSearch(ADNSResolver: TIdDNSResolver; Header: TDNSHeader;
- Question: TIdBytes; var Answer: TIdBytes);
- //modified in May 2004 by Dennies Chang.
- //procedure SaveToCache(ResourceRecord : string);
- procedure SaveToCache(ResourceRecord : TIdBytes; QueryName : string; OriginalQType : UInt16);
- //procedure UpdateTree(TreeRoot : TIdDNTreeNode; RR : TResultRecord); overload;
- //MoveTo Public section for RaidenDNSD.
- // Hide this property temporily, this property is prepared to maintain the
- // TTL expired record auto updated;
- property AutoUpdateZoneInfo : boolean read FAutoUpdateZoneInfo write FAutoUpdateZoneInfo;
- property CS: TIdCriticalSection read FCS;
- procedure DoUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function AXFR(Header : TDNSHeader; Question : string; var Answer : TIdBytes) : string;
- function LoadZoneFromMasterFile(MasterFileName : String) : boolean;
- function LoadZoneStrings(FileStrings: TStrings; Filename : String;
- TreeRoot : TIdDNTreeNode): Boolean;
- function SearchTree(Root : TIdDNTreeNode; QName : String; QType : UInt16): TIdDNTreeNode;
- procedure UpdateTree(TreeRoot : TIdDNTreeNode; RR : TIdTextModeResourceRecord); overload;
- function FindNodeFullName(Root : TIdDNTreeNode; QName : String; QType : UInt16) : string;
- function FindHandedNodeByName(QName : String; QType : UInt16) : TIdDNTreeNode;
- procedure UpdateTree(TreeRoot : TIdDNTreeNode; RR : TResultRecord); overload;
- property RootDNS_NET : TStrings read FRootDNS_NET write SetRootDNS_NET;
- property Cached_Tree : TIdDNTreeNode read FCached_Tree {write SetCached_Tree};
- property Handed_Tree : TIdDNTreeNode read FHanded_Tree {write SetHanded_Tree};
- property Busy : Boolean read FBusy;
- property GlobalCS : TIdCriticalSection read FGlobalCS;
- published
- property DefaultPort default IdPORT_DOMAIN;
- property AutoLoadMasterFile : Boolean read FAutoLoadMasterFile write FAutoLoadMasterFile Default False;
- //property AutoUpdateZoneInfo : boolean read FAutoUpdateZoneInfo write SetAutoUpdateZoneInfo;
- property ZoneMasterFiles : TStrings read FZoneMasterFiles write SetZoneMasterFiles;
- property CacheUnknowZone : Boolean read FCacheUnknowZone write FCacheUnknowZone default False;
- property Handed_DomainList : TStrings read FHanded_DomainList write SetHanded_DomainList;
- property DNSVersion : string read FDNSVersion write FDNSVersion;
- property offerDNSVersion : Boolean read FofferDNSVersion write FofferDNSVersion;
- property OnBeforeQuery : TIdDNSBeforeQueryEvent read FOnBeforeQuery write FOnBeforeQuery;
- property OnAfterQuery : TIdDNSAfterQueryEvent read FOnAfterQuery write FOnAfterQuery;
- property OnAfterSendBack : TIdDNSAfterQueryEvent read FOnAfterSendBack write FOnAfterSendBack;
- property OnAfterCacheSaved : TIdDNSAfterCacheSaved read FOnAfterCacheSaved write FOnAfterCacheSaved;
- end;
- TIdDNSServer = class(TIdComponent)
- protected
- FActive: Boolean;
- FTCPACLActive: Boolean;
- FServerType: TDNSServerTypes;
- FTCPTunnel: TIdDNS_TCPServer;
- FUDPTunnel: TIdDNS_UDPServer;
- FAccessList: TStrings;
- FBindings: TIdSocketHandles;
- procedure SetAccessList(const Value: TStrings);
- procedure SetActive(const Value: Boolean);
- procedure SetTCPACLActive(const Value: Boolean);
- procedure SetBindings(const Value: TIdSocketHandles);
- procedure TimeToUpdateNodeData(Sender : TObject);
- public
- BackupDNSMap : TIdDNSMap;
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure CheckIfExpire(Sender: TObject);
- published
- property Active : Boolean read FActive write SetActive;
- property AccessList : TStrings read FAccessList write SetAccessList;
- property Bindings: TIdSocketHandles read FBindings write SetBindings;
- property TCPACLActive : Boolean read FTCPACLActive write SetTCPACLActive;
- property ServerType: TDNSServerTypes read FServerType write FServerType;
- property TCPTunnel : TIdDNS_TCPServer read FTCPTunnel write FTCPTunnel;
- property UDPTunnel : TIdDNS_UDPServer read FUDPTunnel write FUDPTunnel;
- end;
- implementation
- uses
- {$IFDEF DCC_XE3_OR_ABOVE}
- {$IFNDEF NEXTGEN}
- System.Contnrs,
- {$ENDIF}
- System.SyncObjs,
- System.Types,
- {$ENDIF}
- IdException,
- {$IFDEF USE_VCL_POSIX}
- Posix.SysSelect,
- Posix.SysTime,
- {$ENDIF}
- IdIOHandler,
- IdStack,
- SysUtils;
- {Common Utilities}
- function CompareItems(Item1, Item2: {$IFDEF HAS_GENERICS_TObjectList}TIdMWayTreeNode{$ELSE}TObject{$ENDIF}): Integer;
- var
- LObj1, LObj2 : TIdDNTreeNode;
- begin
- LObj1 := Item1 as TIdDNTreeNode;
- LObj2 := Item2 as TIdDNTreeNode;
- Result := CompareStr(LObj1.CLabel, LObj2.CLabel);
- end;
- // TODO: move to IdGlobal.pas
- function PosBytes(const SubBytes, SBytes: TIdBytes): Integer;
- var
- LSubLen, LBytesLen, I: Integer;
- begin
- LSubLen := Length(SubBytes);
- LBytesLen := Length(SBytes);
- if (LSubLen > 0) and (LBytesLen >= LSubLen) then
- begin
- for Result := 0 to LBytesLen-LSubLen do
- begin
- if SBytes[Result] = SubBytes[0] then
- begin
- for I := 1 to LSubLen-1 do
- begin
- if SBytes[Result+I] <> SubBytes[I] then begin
- Break;
- end;
- end;
- if I = LSubLen then begin
- Exit;
- end;
- end;
- end;
- end;
- Result := -1;
- end;
- // TODO: move to IdGlobal.pas
- function FetchBytes(var AInput: TIdBytes; const ADelim: TIdBytes;
- const ADelete: Boolean = IdFetchDeleteDefault): TIdBytes;
- var
- LPos: integer;
- begin
- LPos := PosBytes(ADelim, AInput);
- if LPos = -1 then begin
- Result := AInput;
- if ADelete then begin
- SetLength(AInput, 0);
- end;
- end
- else begin
- Result := ToBytes(AInput, LPos);
- if ADelete then begin
- //slower Delete(AInput, 1, LPos + Length(ADelim) - 1);
- RemoveBytes(AInput, LPos + Length(ADelim));
- end;
- end;
- end;
- { TIdMWayTreeNode }
- function TIdMWayTreeNode.AddChild: TIdMWayTreeNode;
- begin
- Result := FundmentalClass.Create(FundmentalClass);
- try
- SubTree.Add(Result);
- except
- Result.Free;
- raise;
- end;
- end;
- constructor TIdMWayTreeNode.Create(NodeClass : TIdMWayTreeNodeClass);
- begin
- inherited Create;
- FundmentalClass := NodeClass;
- SubTree := TIdObjectList{$IFDEF HAS_GENERICS_TObjectList}<TIdMWayTreeNode>{$ENDIF}.Create;
- end;
- destructor TIdMWayTreeNode.Destroy;
- begin
- SubTree.Free;
- inherited Destroy;
- end;
- function TIdMWayTreeNode.GetTreeNode(Index: Integer): TIdMWayTreeNode;
- begin
- Result := {$IFDEF HAS_GENERICS_TObjectList}SubTree.Items[Index]{$ELSE}TIdMWayTreeNode(SubTree.Items[Index]){$ENDIF};
- end;
- function TIdMWayTreeNode.InsertChild(Index: Integer): TIdMWayTreeNode;
- begin
- Result := FundmentalClass.Create(FundmentalClass);
- try
- SubTree.Insert(Index, Result);
- except
- Result.Free;
- raise;
- end;
- end;
- procedure TIdMWayTreeNode.RemoveChild(Index: Integer);
- begin
- SubTree.Delete(Index);
- end;
- procedure TIdMWayTreeNode.SetFundmentalClass(const Value: TIdMWayTreeNodeClass);
- begin
- FFundmentalClass := Value;
- end;
- procedure TIdMWayTreeNode.SetTreeNode(Index: Integer; const Value: TIdMWayTreeNode);
- begin
- {$IFNDEF USE_OBJECT_ARC}
- SubTree.Items[Index].Free;
- {$ENDIF}
- SubTree.Items[Index] := Value;
- end;
- { TIdDNTreeNode }
- function TIdDNTreeNode.AddChild: TIdDNTreeNode;
- begin
- Result := TIdDNTreeNode.Create(Self);
- try
- SubTree.Add(Result);
- except
- Result.Free;
- raise;
- end;
- end;
- procedure TIdDNTreeNode.Clear;
- var
- I : Integer;
- begin
- for I := SubTree.Count - 1 downto 0 do begin
- RemoveChild(I);
- end;
- end;
- function TIdDNTreeNode.ConvertToDNString: string;
- var
- Count : Integer;
- begin
- Result := '$ORIGIN ' + FullName + EOL; {do not localize}
- for Count := 0 to RRs.Count-1 do begin
- Result := Result + RRs.Items[Count].TextRecord(FullName);
- end;
- for Count := 0 to FChildIndex.Count-1 do begin
- Result := Result + Children[Count].ConvertToDNString;
- end;
- end;
- constructor TIdDNTreeNode.Create(AParentNode : TIdDNTreeNode);
- begin
- inherited Create(TIdDNTreeNode);
- FRRs := TIdTextModeRRs.Create;
- FChildIndex := TStringList.Create;
- FParentNode := AParentNode;
- end;
- destructor TIdDNTreeNode.Destroy;
- begin
- FRRs.Free;
- FChildIndex.Free;
- inherited Destroy;
- end;
- function TIdDNTreeNode.DumpAllBinaryData(var RecordCount: Integer): TIdBytes;
- var
- Count, ChildCount : integer;
- MyString, ChildString : TIdBytes;
- begin
- SetLength(ChildString, 0);
- SetLength(MyString, 0);
- Inc(RecordCount, RRs.Count + 1);
- for Count := 0 to RRs.Count -1 do
- begin
- AppendBytes(MyString, RRs.Items[Count].BinQueryRecord(FullName));
- end;
- for Count := 0 to FChildIndex.Count -1 do
- begin
- // RLebeau: should ChildCount be set to 0 each time?
- AppendBytes(ChildString, Children[Count].DumpAllBinaryData(ChildCount));
- Inc(RecordCount, ChildCount);
- end;
- if RRs.Count > 0 then begin
- if RRs.Items[0] is TIdRR_SOA then begin
- AppendBytes(MyString, RRs.Items[0].BinQueryRecord(FullName));
- Inc(RecordCount);
- end;
- end;
- Result := MyString;
- AppendBytes(Result, ChildString);
- if RRs.Count > 0 then begin
- AppendBytes(Result, RRs.Items[0].BinQueryRecord(FullName));
- end;
- end;
- function TIdDNTreeNode.GetFullName: string;
- begin
- if ParentNode = nil then begin
- if CLabel = '.' then begin
- Result := '';
- end else begin
- Result := CLabel;
- end;
- end else begin
- Result := CLabel + '.' + ParentNode.FullName;
- end;
- end;
- function TIdDNTreeNode.GetNode(Index: Integer): TIdDNTreeNode;
- begin
- Result := TIdDNTreeNode(SubTree.Items[Index]);
- end;
- function TIdDNTreeNode.IndexByLabel(CLabel: String): Integer;
- begin
- Result := FChildIndex.IndexOf(CLabel);
- end;
- function TIdDNTreeNode.IndexByNode(ANode: TIdDNTreeNode): Integer;
- begin
- Result := SubTree.IndexOf(ANode);
- end;
- function TIdDNTreeNode.InsertChild(Index: Integer): TIdDNTreeNode;
- begin
- Result := TIdDNTreeNode.Create(Self);
- try
- SubTree.Insert(Index, Result);
- except
- Result.Free;
- raise;
- end;
- end;
- procedure TIdDNTreeNode.RemoveChild(Index: Integer);
- begin
- SubTree.Remove(SubTree.Items[Index]);
- FChildIndex.Delete(Index);
- end;
- procedure TIdDNTreeNode.SaveToFile(Filename: String);
- var
- DNSs : TStrings;
- begin
- DNSs := TStringList.Create;
- try
- DNSs.Add(ConvertToDNString);
- ToDo('SaveToFile() method of TIdDNTreeNode class is not implemented yet'); {do not localized}
- // DNSs.SaveToFile(Filename);
- finally
- DNSs.Free;
- end;
- end;
- procedure TIdDNTreeNode.SetChildIndex(const Value: TStrings);
- begin
- FChildIndex.Assign(Value);
- end;
- procedure TIdDNTreeNode.SetCLabel(const Value: String);
- begin
- FCLabel := Value;
- if ParentNode <> nil then begin
- ParentNode.ChildIndex.Insert(ParentNode.SubTree.IndexOf(Self), Value);
- end;
- if AutoSortChild then begin
- SortChildren;
- end;
- end;
- procedure TIdDNTreeNode.SetNode(Index: Integer; const Value: TIdDNTreeNode);
- begin
- SubTree.Items[Index] := Value;
- end;
- procedure TIdDNTreeNode.SetRRs(const Value: TIdTextModeRRs);
- begin
- FRRs.Assign(Value);
- end;
- procedure TIdDNTreeNode.SortChildren;
- begin
- SubTree.BubbleSort(CompareItems);
- TStringList(FChildIndex).Sort;
- end;
- { TIdDNSServer }
- constructor TIdDNS_UDPServer.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FRootDNS_NET := TStringList.Create;
- FRootDNS_NET.Add('209.92.33.150'); // nic.net {do not localize}
- FRootDNS_NET.Add('209.92.33.130'); // nic.net {do not localize}
- FRootDNS_NET.Add('203.37.255.97'); // apnic.net {do not localize}
- FRootDNS_NET.Add('202.12.29.131'); // apnic.net {do not localize}
- FRootDNS_NET.Add('12.29.20.2'); // nanic.net {do not localize}
- FRootDNS_NET.Add('204.145.119.2'); // nanic.net {do not localize}
- FRootDNS_NET.Add('140.111.1.2'); // a.twnic.net.tw {do not localize}
- FCached_Tree := TIdDNTreeNode.Create(nil);
- FCached_Tree.AutoSortChild := True;
- FCached_Tree.CLabel := '.';
- FHanded_Tree := TIdDNTreeNode.Create(nil);
- FHanded_Tree.AutoSortChild := True;
- FHanded_Tree.CLabel := '.';
- FHanded_DomainList := TStringList.Create;
- FZoneMasterFiles := TStringList.Create;
- DefaultPort := IdPORT_DOMAIN;
- FCS := TIdCriticalSection.Create;
- FGlobalCS := TIdCriticalSection.Create;
- FBusy := False;
- end;
- destructor TIdDNS_UDPServer.Destroy;
- begin
- FCached_Tree.Free;
- FHanded_Tree.Free;
- FRootDNS_NET.Free;
- FHanded_DomainList.Free;
- FZoneMasterFiles.Free;
- FCS.Free;
- FGlobalCS.Free;
- inherited Destroy;
- end;
- procedure TIdDNS_UDPServer.DoAfterQuery(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var QueryResult: TIdBytes; var ResultCode : String;
- Query : TIdBytes);
- begin
- if Assigned(FOnAfterQuery) then begin
- FOnAfterQuery(ABinding, ADNSHeader, QueryResult, ResultCode, Query);
- end;
- end;
- procedure TIdDNS_UDPServer.DoBeforeQuery(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var ADNSQuery: TIdBytes);
- begin
- if Assigned(FOnBeforeQuery) then begin
- FOnBeforeQuery(ABinding, ADNSHeader, ADNSQuery);
- end;
- end;
- procedure TIdDNS_UDPServer.ExternalSearch(ADNSResolver : TIdDNSResolver;
- Header: TDNSHeader; Question: TIdBytes; var Answer: TIdBytes);
- var
- Server_Index : Integer;
- MyDNSResolver : TIdDNSResolver;
- begin
- if RootDNS_NET.Count = 0 then begin
- Exit;
- end;
- Server_Index := 0;
- if ADNSResolver = nil then begin
- MyDNSResolver := TIdDNSResolver.Create;
- MyDNSResolver.WaitingTime := 5000;
- end else begin
- MyDNSResolver := ADNSResolver;
- end;
- try
- repeat
- MyDNSResolver.Host := RootDNS_NET.Strings[Server_Index];
- try
- MyDNSResolver.InternalQuery := Question;
- MyDNSResolver.Resolve('');
- Answer := MyDNSResolver.PlainTextResult;
- except
- // Todo: Create DNS server interal resolver error.
- on EIdDnsResolverError do begin
- //Empty Event, for user to custom the event handle.
- end;
- on EIdSocketError do begin
- end;
- else
- begin
- end;
- end;
- Inc(Server_Index);
- until (Server_Index >= RootDNS_NET.Count) or (Answer <> nil);
- finally
- if ADNSResolver = nil then begin
- MyDNSResolver.Free;
- end;
- end;
- end;
- function TIdDNS_UDPServer.FindHandedNodeByName(QName: String; QType: UInt16): TIdDNTreeNode;
- begin
- Result := SearchTree(Handed_Tree, QName, QType);
- end;
- function TIdDNS_UDPServer.FindNodeFullName(Root: TIdDNTreeNode; QName: String; QType : UInt16): string;
- var
- MyNode : TIdDNTreeNode;
- begin
- MyNode := SearchTree(Root, QName, QType);
- if MyNode <> nil then begin
- Result := MyNode.FullName;
- end else begin
- Result := '';
- end;
- end;
- function TIdDNS_UDPServer.LoadZoneFromMasterFile(MasterFileName: String): Boolean;
- var
- FileStrings : TStrings;
- begin
- {MakeTagList;}
- Result := FileExists(MasterFileName);
- if Result then begin
- FileStrings := TStringList.Create;
- try
- Todo('LoadZoneFromMasterFile() method of TIdDNS_UDPServer class is not implemented yet'); {do not localize}
- // FileStrings.LoadFromFile(MasterFileName);
- Result := LoadZoneStrings(FileStrings, MasterFileName, Handed_Tree);
- finally
- FileStrings.Free;
- end;
- end;
- {FreeTagList;}
- end;
- function TIdDNS_UDPServer.LoadZoneStrings(FileStrings: TStrings; Filename : String;
- TreeRoot : TIdDNTreeNode): Boolean;
- var
- TagList : TStrings;
- function IsMSDNSFileName(theFileName : String; var DN: string) : Boolean;
- var
- namepart : TStrings;
- Fullname : string;
- Count : Integer;
- begin
- Fullname := theFilename;
- repeat
- if Pos('\', Fullname) > 0 then begin
- Fetch(Fullname, '\');
- end;
- until Pos('\', Fullname) = 0;
- namepart := TStringList.Create;
- try
- repeat
- namepart.Add(Fetch(Fullname, '.'));
- until Fullname = '';
- Result := namepart.Strings[namepart.Count-1] = 'dns'; {do not localize}
- if Result then begin
- Count := 0;
- DN := namepart.Strings[Count];
- repeat
- Inc(Count);
- if Count <= namepart.Count -2 then begin
- DN := DN + '.' + namepart.Strings[Count];
- end;
- until Count >= (namepart.Count-2);
- end;
- finally
- namepart.Free;
- end;
- end;
- procedure MakeTagList;
- begin
- TagList := TStringList.Create;
- try
- TagList.Add(cAAAA);
- TagList.Add(cA);
- TagList.Add(cNS);
- TagList.Add(cMD);
- TagList.Add(cMF);
- TagList.Add(cCName);
- TagList.Add(cSOA);
- TagList.Add(cMB);
- TagList.Add(cMG);
- TagList.Add(cMR);
- TagList.Add(cNULL);
- TagList.Add(cWKS);
- TagList.Add(cPTR);
- TagList.Add(cHINFO);
- TagList.Add(cMINFO);
- TagList.Add(cMX);
- TagList.Add(cTXT);
- // The Following Tags are used in master file, but not Resource Record.
- TagList.Add(cOrigin);
- TagList.Add(cInclude);
- //TagList.Add(cAt);
- except
- TagList.Free;
- raise;
- end;
- end;
- procedure FreeTagList;
- begin
- FreeAndNil(TagList);
- end;
- function ClearDoubleQutoa(Strs : TStrings): Boolean;
- var
- SSCount : Integer;
- Mark, Found : Boolean;
- begin
- SSCount := 0;
- Mark := False;
- while SSCount <= (Strs.Count-1) do begin
- Found := Pos('"', Strs.Strings[SSCount]) > 0;
- while Found do begin
- Mark := Mark xor Found;
- Strs.Strings[SSCount] := ReplaceSpecString(Strs.Strings[SSCount], '"', '', False);
- Found := Pos('"', Strs.Strings[SSCount]) > 0;
- end;
- if not Mark then begin
- Inc(SSCount);
- end else begin
- Strs.Strings[SSCount] := Strs.Strings[SSCount] + ' ' + Strs.Strings[SSCount + 1];
- Strs.Delete(SSCount + 1);
- end;
- end;
- Result := not Mark;
- end;
- function IsValidMasterFile : Boolean;
- var
- EachLinePart : TStrings;
- CurrentLineNum, TagField, Count : Integer;
- LineData, DataBody, {Comment,} FPart, LTag : string;
- Denoted, Stop, PassQuota : Boolean;
- begin
- EachLinePart := TStringList.Create;
- try
- CurrentLineNum := 0;
- Stop := False;
- // Check Denoted;
- Denoted := false;
- if FileStrings.Count > 0 then begin
- repeat
- LineData := Trim(FileStrings.Strings[CurrentLineNum]);
- DataBody := Fetch(LineData, ';');
- //Comment := LineData;
- PassQuota := Pos('(', DataBody) = 0;
- // Split each item into TStrings.
- repeat
- if not PassQuota then begin
- Inc(CurrentLineNum);
- LineData := Trim(FileStrings.Strings[CurrentLineNum]);
- DataBody := DataBody + ' ' + Fetch(LineData, ';');
- PassQuota := Pos(')', DataBody) > 0;
- end;
- until PassQuota or (CurrentLineNum > (FileStrings.Count-1));
- Stop := not PassQuota;
- if not Stop then begin
- EachLinePart.Clear;
- DataBody := ReplaceSpecString(DataBody, '(', '');
- DataBody := ReplaceSpecString(DataBody, ')', '');
- repeat
- DataBody := Trim(DataBody);
- FPart := Fetch(DataBody, #9);
- repeat
- FPart := Trim(FPart);
- LTag := Fetch(FPart,' ');
- if (LTag <> '') and (LTag <> '(') and (LTag <> ')') then begin
- EachLinePart.Add(LTag);
- end;
- until FPart = '';
- until DataBody = '';
- if not Denoted then begin
- if EachLinePart.Count > 1 then begin
- Denoted := (EachLinePart.Strings[0] = cOrigin) or (EachLinePart.IndexOf(cSOA) <> -1);
- end else begin
- Denoted := False;
- end;
- end;
- // Check Syntax;
- if not ((EachLinePart.Count > 0) and (EachLinePart.Strings[0] = cOrigin)) then
- begin
- if not Denoted then begin
- if EachLinePart.Count > 0 then begin
- Stop := (EachLinePart.Count > 0) and (EachLinePart.IndexOf(cSOA) = -1);
- end else begin
- Stop := False;
- end;
- end else begin
- //TagField := -1;
- //FieldCount := 0;
- // Search Tag Named 'IN';
- TagField := EachLinePart.IndexOf('IN'); {do not localize}
- if TagField = -1 then begin
- Count := 0;
- repeat
- if EachLinePart.Count > 0 then begin
- TagField := TagList.IndexOf(EachLinePart.Strings[Count]);
- end;
- Inc(Count);
- until (Count >= EachLinePart.Count -1) or (TagField <> -1);
- if TagField <> -1 then begin
- TagField := Count;
- end;
- end else begin
- if TagList.IndexOf(EachLinePart.Strings[TagField + 1]) = -1 then begin
- TagField := -1;
- end else begin
- Inc(TagField);
- end;
- end;
- if TagField > -1 then begin
- case TagList.IndexOf(EachLinePart.Strings[TagField]) of
- // Check ip
- TypeCode_A : Stop := not IsValidIP(EachLinePart.Strings[TagField + 1]);
- // Check ip v6
- 0 : Stop := not IsValidIPv6(EachLinePart.Strings[TagField + 1]);
- // Check Domain Name
- TypeCode_CName, TypeCode_NS, TypeCode_MR,
- TypeCode_MD, TypeCode_MB, TypeCode_MG,
- TypeCode_MF: Stop := not IsHostName(EachLinePart.Strings[TagField + 1]);
- // Can be anything
- TypeCode_TXT, TypeCode_NULL: Stop := False;
- // Must be FQDN.
- TypeCode_PTR: Stop := not IsFQDN(EachLinePart.Strings[TagField + 1]);
- // HINFO should has 2 fields : CPU and OS. but TStrings
- // is 0 base, so that we have to minus one
- TypeCode_HINFO:
- begin
- Stop := not (ClearDoubleQutoa(EachLinePart) and
- ((EachLinePart.Count - TagField - 1) = 2));
- end;
- // Check RMailBX and EMailBX but TStrings
- // is 0 base, so that we have to minus one
- TypeCode_MINFO:
- begin
- Stop := ((EachLinePart.Count - TagField - 1) <> 2);
- if not Stop then begin
- Stop := not (IsHostName(EachLinePart.Strings[TagField + 1]) and
- IsHostName(EachLinePart.Strings[TagField + 2]));
- end;
- end;
- // Check Pref(Numeric) and Exchange. but TStrings
- // is 0 base, so that we have to minus one
- TypeCode_MX:
- begin
- Stop := ((EachLinePart.Count - TagField - 1) <> 2);
- if not Stop then begin
- Stop := not (IsNumeric(EachLinePart.Strings[TagField + 1]) and
- IsHostName(EachLinePart.Strings[TagField + 2]));
- end;
- end;
- // TStrings is 0 base, so that we have to minus one
- TypeCode_SOA:
- begin
- Stop := ((EachLinePart.Count - TagField - 1) <> 7);
- if not Stop then begin
- Stop := not (IsHostName(EachLinePart.Strings[TagField + 1]) and
- IsHostName(EachLinePart.Strings[TagField + 2]) and
- IsNumeric(EachLinePart.Strings[TagField + 3]) and
- IsNumeric(EachLinePart.Strings[TagField + 4]) and
- IsNumeric(EachLinePart.Strings[TagField + 5]) and
- IsNumeric(EachLinePart.Strings[TagField + 6]) and
- IsNumeric(EachLinePart.Strings[TagField + 7])
- );
- end;
- end;
- TypeCode_WKS: Stop := ((EachLinePart.Count - TagField) = 1);
- end;
- end else begin
- if EachLinePart.Count > 0 then
- Stop := True;
- end;
- end;
- end;
- end;
- Inc(CurrentLineNum);
- until (CurrentLineNum > (FileStrings.Count-1)) or Stop;
- end;
- Result := not Stop;
- finally
- EachLinePart.Free;
- end;
- end;
- function LoadMasterFile : Boolean;
- var
- Checks, EachLinePart, DenotedDomain : TStrings;
- CurrentLineNum, TagField, Count, LastTTL : Integer;
- LineData, DataBody, FPart, LTag, LText,
- RName, LastDenotedDomain, LastTag, NewDomain, SingleHostName {CH: , PrevDNTag} : string;
- Stop, PassQuota, Found {, canChangPrevDNTag } : Boolean;
- LLRR_A : TIdRR_A;
- LLRR_AAAA : TIdRR_AAAA;
- LLRR_NS : TIdRR_NS;
- LLRR_MB : TIdRR_MB;
- LLRR_Name : TIdRR_CName;
- LLRR_SOA : TIdRR_SOA;
- LLRR_MG : TIdRR_MG;
- LLRR_MR : TIdRR_MR;
- LLRR_PTR : TIdRR_PTR;
- LLRR_HINFO : TIdRR_HINFO;
- LLRR_MINFO : TIdRR_MINFO;
- LLRR_MX : TIdRR_MX;
- LLRR_TXT : TIdRR_TXT;
- begin
- EachLinePart := TStringList.Create;
- try
- DenotedDomain := TStringList.Create;
- try
- CurrentLineNum := 0;
- LastDenotedDomain := '';
- LastTag := '';
- NewDomain := '';
- // PrevDNTag := '';
- Stop := False;
- //canChangPrevDNTag := True;
- if IsMSDNSFileName(FileName, LastDenotedDomain) then begin
- //canChangPrevDNTag := False;
- Filename := Uppercase(Filename);
- end else begin
- LastDenotedDomain := '';
- end;
- if FileStrings.Count > 0 then begin
- repeat
- LineData := Trim(FileStrings.Strings[CurrentLineNum]);
- DataBody := Fetch(LineData, ';');
- // Comment := LineData;
- PassQuota := Pos('(', DataBody) = 0;
- // Split each item into TStrings.
- repeat
- if not PassQuota then begin
- Inc(CurrentLineNum);
- LineData := Trim(FileStrings.Strings[CurrentLineNum]);
- DataBody := DataBody + ' ' + Fetch(LineData, ';');
- PassQuota := Pos(')', DataBody) > 0;
- end;
- until PassQuota;
- EachLinePart.Clear;
- DataBody := ReplaceSpecString(DataBody, '(', '');
- DataBody := ReplaceSpecString(DataBody, ')', '');
- repeat
- DataBody := Trim(DataBody);
- FPart := Fetch(DataBody, #9);
- repeat
- FPart := Trim(FPart);
- if Pos('"', FPart) = 1 then begin
- Fetch(FPart, '"');
- LText := Fetch(FPart, '"');
- EachLinePart.Add(LText);
- end;
- LTag := Fetch(FPart, ' ');
- if (TagList.IndexOf(LTag) = -1) and (LTag <> 'IN') then begin {do not localize}
- LTag := LowerCase(LTag);
- end;
- if (LTag <> '') and (LTag <> '(') and (LTag <> ')') then begin
- EachLinePart.Add(LTag);
- end;
- until FPart = '';
- until DataBody = '';
- if EachLinePart.Count > 0 then begin
- if EachLinePart.Strings[0] = cOrigin then begin
- // One Domain is found.
- NewDomain := EachLinePart.Strings[1];
- if TextEndsWith(NewDomain, '.') then begin
- LastDenotedDomain := NewDomain;
- NewDomain := '';
- end else begin
- LastDenotedDomain := NewDomain + '.' + LastDenotedDomain;
- NewDomain := '';
- end;
- end else begin
- // Search RR Type Tag;
- Count := 0;
- TagField := -1;
- repeat
- Found := TagList.IndexOf(EachLinePart.Strings[Count]) > -1;
- if Found then begin
- TagField := Count;
- end;
- Inc(Count);
- until Found or (Count > (EachLinePart.Count-1));
- // To initialize LastTTL;
- LastTTL := 86400;
- if TagField > -1 then begin
- case TagField of
- 1 :
- if EachLinePart.Strings[0] <> 'IN' then begin {do not localize}
- // canChangPrevDNTag := True;
- LastTag := EachLinePart.Strings[0];
- if EachLinePart.Strings[TagField] <> 'SOA' then begin {do not localize}
- // PrevDNTag := '';
- end else begin
- LastTTL := IndyStrToInt(EachLinePart.Strings[TagField + 6]);
- end;
- // end else begin
- // canChangPrevDNTag := False;
- end;
- 2 :
- if EachLinePart.Strings[1] = 'IN' then begin {do not localize}
- LastTag := EachLinePart.Strings[0];
- // canChangPrevDNTag := True;
- if EachLinePart.Strings[TagField] <> 'SOA' then begin {do not localize}
- // PrevDNTag := '';
- end else begin
- LastTTL := IndyStrToInt(EachLinePart.Strings[TagField + 6]);
- end;
- end else begin
- // canChangPrevDNTag := False;
- end;
- else
- begin
- // canChangPrevDNTag := False;
- LastTTL := 86400;
- end;
- end;
- //if (EachLinePart.Strings[0] = cAt) or (PrevDNTag = 'SOA') then
- if EachLinePart.Strings[0] = cAt then begin
- SingleHostName := LastDenotedDomain
- end else begin
- if LastTag = cAt then begin
- LastTag := SingleHostName;
- end;
- if not TextEndsWith(LastTag, '.') then begin
- SingleHostName := LastTag + '.' + LastDenotedDomain
- end else begin
- SingleHostName := LastTag;
- end;
- end;
- case TagList.IndexOf(EachLinePart.Strings[TagField]) of
- // Check ip
- TypeCode_A :
- begin
- LLRR_A := TIdRR_A.Create;
- LLRR_A.RRName := SingleHostName;
- LLRR_A.Address := EachLinePart.Strings[TagField + 1];
- LLRR_A.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_A);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'A';
- // end;
- end;
- // Check IPv6 ip address 10/29,2002
- 0 :
- begin
- LLRR_AAAA := TIdRR_AAAA.Create;
- LLRR_AAAA.RRName := SingleHostName;
- LLRR_AAAA.Address := ConvertToValidv6IP(EachLinePart.Strings[TagField + 1]);
- LLRR_AAAA.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_AAAA);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'AAAA'; {do not localize}
- // end;
- end;
- // Check Domain Name
- TypeCode_CName:
- begin
- LLRR_Name := TIdRR_CName.Create;
- LLRR_Name.RRName := SingleHostName;
- if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
- LLRR_Name.CName := EachLinePart.Strings[TagField + 1];
- end else begin
- LLRR_Name.CName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
- end;
- LLRR_Name.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_Name);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'CNAME'; {do not localize}
- // end;
- end;
- TypeCode_NS :
- begin
- LLRR_NS := TIdRR_NS.Create;
- LLRR_NS.RRName := SingleHostName;
- if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
- LLRR_NS.NSDName := EachLinePart.Strings[TagField + 1];
- end else begin
- LLRR_NS.NSDName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
- end;
- LLRR_NS.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_NS);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'NS'; {do not localize}
- // end;
- end;
- TypeCode_MR :
- begin
- LLRR_MR := TIdRR_MR.Create;
- LLRR_MR.RRName := SingleHostName;
- if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
- LLRR_MR.NewName := EachLinePart.Strings[TagField + 1];
- end else begin
- LLRR_MR.NewName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
- end;
- LLRR_MR.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_MR);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'MR'; {do not localize}
- // end;
- end;
- TypeCode_MD, TypeCode_MB, TypeCode_MF :
- begin
- LLRR_MB := TIdRR_MB.Create;
- LLRR_MB.RRName := SingleHostName;
- if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
- LLRR_MB.MADName := EachLinePart.Strings[TagField + 1];
- end else begin
- LLRR_MB.MADName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
- end;
- LLRR_MB.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_MB);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'MF'; {do not localize}
- // end;
- end;
- TypeCode_MG :
- begin
- LLRR_MG := TIdRR_MG.Create;
- LLRR_MG.RRName := SingleHostName;
- if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
- LLRR_MG.MGMName := EachLinePart.Strings[TagField + 1];
- end else begin
- LLRR_MG.MGMName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
- end;
- LLRR_MG.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_MG);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'MG'; {do not localize}
- // end;
- end;
- // Can be anything
- TypeCode_TXT, TypeCode_NULL:
- begin
- LLRR_TXT := TIdRR_TXT.Create;
- LLRR_TXT.RRName := SingleHostName;
- LLRR_TXT.TXT := EachLinePart.Strings[TagField + 1];
- LLRR_TXT.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_TXT);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'TXT'; {do not localize}
- // end;
- end;
- // Must be FQDN.
- TypeCode_PTR:
- begin
- LLRR_PTR := TIdRR_PTR.Create;
- LLRR_PTR.RRName := SingleHostName;
- if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
- LLRR_PTR.PTRDName := EachLinePart.Strings[TagField + 1];
- end else begin
- LLRR_PTR.PTRDName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
- end;
- LLRR_PTR.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_PTR);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'PTR'; {do not localize}
- // end;
- end;
- // HINFO should has 2 fields : CPU and OS. but TStrings
- // is 0 base, so that we have to minus one
- TypeCode_HINFO:
- begin
- ClearDoubleQutoa(EachLinePart);
- LLRR_HINFO := TIdRR_HINFO.Create;
- LLRR_HINFO.RRName := SingleHostName;
- LLRR_HINFO.CPU := EachLinePart.Strings[TagField + 1];
- LLRR_HINFO.OS := EachLinePart.Strings[TagField + 2];
- LLRR_HINFO.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_HINFO);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'HINFO'; {do not localize}
- // end;
- end;
- // Check RMailBX and EMailBX but TStrings
- // is 0 base, so that we have to minus one
- TypeCode_MINFO:
- begin
- LLRR_MINFO := TIdRR_MINFO.Create;
- LLRR_MINFO.RRName := SingleHostName;
- if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
- LLRR_MINFO.Responsible_Mail := EachLinePart.Strings[TagField + 1];
- end else begin
- LLRR_MINFO.Responsible_Mail := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
- end;
- if TextEndsWith(EachLinePart.Strings[TagField + 2], '.') then begin
- LLRR_MINFO.ErrorHandle_Mail := EachLinePart.Strings[TagField + 2];
- end else begin
- LLRR_MINFO.ErrorHandle_Mail := EachLinePart.Strings[TagField + 2] + '.' + LastDenotedDomain;
- end;
- LLRR_MINFO.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_MINFO);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'MINFO'; {do not localize}
- // end;
- end;
- // Check Pref(Numeric) and Exchange. but TStrings
- // is 0 base, so that we have to minus one
- TypeCode_MX:
- begin
- LLRR_MX := TIdRR_MX.Create;
- LLRR_MX.RRName := SingleHostName;
- LLRR_MX.Preference := EachLinePart.Strings[TagField + 1];
- if TextEndsWith(EachLinePart.Strings[TagField + 2], '.') then begin
- LLRR_MX.Exchange := EachLinePart.Strings[TagField + 2];
- end else begin
- LLRR_MX.Exchange := EachLinePart.Strings[TagField + 2] + '.' + LastDenotedDomain;
- end;
- LLRR_MX.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_MX);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'MX'; {do not localize}
- // end;
- end;
- // TStrings is 0 base, so that we have to minus one
- TypeCode_SOA:
- begin
- LLRR_SOA := TIdRR_SOA.Create;
- if TextEndsWith(EachLinePart.Strings[TagField + 1], '.') then begin
- LLRR_SOA.MName := EachLinePart.Strings[TagField + 1];
- end else begin
- LLRR_SOA.MName := EachLinePart.Strings[TagField + 1] + '.' + LastDenotedDomain;
- end;
- //LLRR_SOA.RRName:= LLRR_SOA.MName;
- if (SingleHostName = '') and (LastDenotedDomain = '') then begin
- LastDenotedDomain := String(LLRR_SOA.MName); // explicit convert to Unicode
- Fetch(LastDenotedDomain, '.');
- SingleHostName := LastDenotedDomain;
- end;
- LLRR_SOA.RRName := SingleHostName;
- // Update the Handed List
- {
- if Handed_DomainList.IndexOf(LLRR_SOA.MName) = -1 then begin
- Handed_DomainList.Add(LLRR_SOA.MName);
- end;
- }
- if Handed_DomainList.IndexOf(LLRR_SOA.RRName) = -1 then begin
- Handed_DomainList.Add(LLRR_SOA.RRName);
- end;
- {
- if DenotedDomain.IndexOf(LLRR_SOA.MName) = -1 then begin
- DenotedDomain.Add(LLRR_SOA.MName);
- end;
- LastDenotedDomain := LLRR_SOA.MName;
- }
- if DenotedDomain.IndexOf(LLRR_SOA.RRName) = -1 then begin
- DenotedDomain.Add(LLRR_SOA.RRName);
- end;
- //LastDenotedDomain := LLRR_SOA.RRName;
- if TextEndsWith(EachLinePart.Strings[TagField + 2], '.') then begin
- LLRR_SOA.RName := EachLinePart.Strings[TagField + 2];
- end else begin
- LLRR_SOA.RName := EachLinePart.Strings[TagField + 2] + '.' + LastDenotedDomain;
- end;
- Checks := TStringList.Create;
- try
- RName := String(LLRR_SOA.RName); // explicit convert to Unicode
- while RName <> '' do begin
- Checks.Add(Fetch(RName, '.'));
- end;
- RName := '';
- For Count := 0 to Checks.Count -1 do begin
- if Checks.Strings[Count] <> '' then begin
- RName := RName + Checks.Strings[Count] + '.';
- end;
- end;
- LLRR_SOA.RName := RName;
- finally
- Checks.Free;
- end;
- LLRR_SOA.Serial := EachLinePart.Strings[TagField + 3];
- LLRR_SOA.Refresh := EachLinePart.Strings[TagField + 4];
- LLRR_SOA.Retry := EachLinePart.Strings[TagField + 5];
- LLRR_SOA.Expire := EachLinePart.Strings[TagField + 6];
- LLRR_SOA.Minimum := EachLinePart.Strings[TagField + 7];
- LastTTL := IndyStrToInt(LLRR_SOA.Expire);
- LLRR_SOA.TTL := LastTTL;
- UpdateTree(TreeRoot, LLRR_SOA);
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'SOA'; {do not localize}
- // end;
- end;
- TypeCode_WKS:
- begin
- // if canChangPrevDNTag then begin
- // PrevDNTag := 'WKS'; {do not localize}
- // end;
- end;
- end;
- end;
- end; // if EachLinePart.Count == 0 => Only Comment
- end;
- Inc(CurrentLineNum);
- until (CurrentLineNum > (FileStrings.Count -1));
- end;
- Result := not Stop;
- finally
- DenotedDomain.Free;
- end;
- finally
- EachLinePart.Free;
- end;
- end;
- begin
- MakeTagList;
- try
- Result := IsValidMasterFile;
- // IsValidMasterFile is used in local, so I design with not
- // any parameter.
- if Result then begin
- Result := LoadMasterFile;
- end;
- finally
- FreeTagList;
- end;
- end;
- procedure TIdDNS_UDPServer.SaveToCache(ResourceRecord: TIdBytes; QueryName : string; OriginalQType : UInt16);
- var
- TempResolver : TIdDNSResolver;
- Count : Integer;
- begin
- TempResolver := TIdDNSResolver.Create(nil);
- try
- // RLebeau: FillResultWithOutCheckId() is deprecated, but not using FillResult()
- // here yet because it validates the DNSHeader.RCode, and I do not know if that
- // is needed here. I don't want to break this logic...
- TempResolver.FillResultWithOutCheckId(ResourceRecord);
- if TempResolver.DNSHeader.ANCount > 0 then begin
- for Count := 0 to TempResolver.QueryResult.Count - 1 do begin
- UpdateTree(Cached_Tree, TempResolver.QueryResult.Items[Count]);
- end;
- end;
- finally
- TempResolver.Free;
- end;
- end;
- function TIdDNS_UDPServer.SearchTree(Root: TIdDNTreeNode; QName: String; QType : UInt16): TIdDNTreeNode;
- var
- RRIndex : integer;
- NodeCursor : TIdDNTreeNode;
- NameLabels : TStrings;
- OneNode, FullName : string;
- Found : Boolean;
- begin
- Result := nil;
- NameLabels := TStringList.Create;
- try
- FullName := QName;
- NodeCursor := Root;
- Found := False;
- repeat
- OneNode := Fetch(FullName, '.');
- if OneNode <> '' then begin
- NameLabels.Add(OneNode);
- end;
- until FullName = '';
- repeat
- if QType <> TypeCode_SOA then begin
- RRIndex := NodeCursor.ChildIndex.IndexOf(NameLabels.Strings[NameLabels.Count - 1]);
- if RRIndex <> -1 then begin
- NameLabels.Delete(NameLabels.Count - 1);
- NodeCursor := NodeCursor.Children[RRIndex];
- if NameLabels.Count = 1 then begin
- Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
- end else begin
- Found := NameLabels.Count = 0;
- end;
- end else begin
- if NameLabels.Count = 1 then begin
- Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
- if not Found then begin
- NameLabels.Clear;
- end;
- end else begin
- NameLabels.Clear;
- end;
- end;
- end else begin
- RRIndex := NodeCursor.ChildIndex.IndexOf(NameLabels.Strings[NameLabels.Count - 1]);
- if RRIndex <> -1 then begin
- NameLabels.Delete(NameLabels.Count - 1);
- NodeCursor := NodeCursor.Children[RRIndex];
- if NameLabels.Count = 1 then begin
- Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
- end else begin
- Found := NameLabels.Count = 0;
- end;
- end else begin
- if NameLabels.Count = 1 then begin
- Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
- if not Found then begin
- NameLabels.Clear;
- end;
- end else begin
- NameLabels.Clear;
- end;
- end;
- end;
- until (NameLabels.Count = 0) or Found;
- if Found then begin
- Result := NodeCursor;
- end;
- finally
- NameLabels.Free;
- end;
- end;
- procedure TIdDNS_UDPServer.SetHanded_DomainList(const Value: TStrings);
- begin
- FHanded_DomainList.Assign(Value);
- end;
- procedure TIdDNS_UDPServer.SetRootDNS_NET(const Value: TStrings);
- begin
- FRootDNS_NET.Assign(Value);
- end;
- procedure TIdDNS_UDPServer.SetZoneMasterFiles(const Value: TStrings);
- begin
- FZoneMasterFiles.Assign(Value);
- end;
- procedure TIdDNS_UDPServer.UpdateTree(TreeRoot: TIdDNTreeNode; RR: TResultRecord);
- var
- NameNode : TStrings;
- RRName, APart : String;
- Count, NodeIndex : Integer;
- NodeCursor : TIdDNTreeNode;
- LRR_A : TIdRR_A;
- LRR_AAAA : TIdRR_AAAA;
- LRR_NS : TIdRR_NS;
- LRR_MB : TIdRR_MB;
- LRR_Name : TIdRR_CName;
- LRR_SOA : TIdRR_SOA;
- LRR_MG : TIdRR_MG;
- LRR_MR : TIdRR_MR;
- LRR_PTR : TIdRR_PTR;
- LRR_HINFO : TIdRR_HINFO;
- LRR_MINFO : TIdRR_MINFO;
- LRR_MX : TIdRR_MX;
- LRR_TXT : TIdRR_TXT;
- begin
- NameNode := TStringList.Create;
- try
- RRName := RR.Name;
- repeat
- APart := Fetch(RRName, '.');
- if APart <> '' then begin
- NameNode.Add(APart);
- end;
- until RRName = '';
- NodeCursor := TreeRoot;
- RRName := RR.Name;
- if not TextEndsWith(RRName, '.') then begin
- RRName := RRName + '.';
- end;
- if (RR.RecType <> qtSOA) and (Handed_DomainList.IndexOf(LowerCase(RRName)) = -1) and (RR.RecType <> qtNS) then begin
- for Count := NameNode.Count-1 downto 1 do begin
- NodeIndex := NodeCursor.ChildIndex.IndexOf(NameNode.Strings[Count]);
- if NodeIndex = -1 then begin
- NodeCursor := NodeCursor.AddChild;
- NodeCursor.AutoSortChild := True;
- NodeCursor.CLabel := NameNode.Strings[Count];
- end else begin
- NodeCursor := NodeCursor.Children[NodeIndex];
- end;
- end;
- RRName := NameNode.Strings[0];
- end else begin
- for Count := NameNode.Count-1 downto 0 do begin
- NodeIndex := NodeCursor.ChildIndex.IndexOf(NameNode.Strings[Count]);
- RRName := NameNode.Strings[Count];
- if NodeIndex = -1 then begin
- NodeCursor := NodeCursor.AddChild;
- //NodeCursor.CLabel := RRName;
- NodeCursor.AutoSortChild := True;
- NodeCursor.CLabel := RRName;
- end else begin
- NodeCursor := NodeCursor.Children[NodeIndex];
- end;
- end;
- RRName := RR.Name;
- end;
- NodeCursor.RRs.ItemNames.Add(RRName);
- case RR.RecType of
- qtA :
- begin
- LRR_A := TIdRR_A.Create;
- try
- NodeCursor.RRs.Add(LRR_A);
- except
- LRR_A.Free;
- raise;
- end;
- LRR_A.RRName := RRName;
- LRR_A.Address := TARecord(RR).IPAddress;
- LRR_A.TTL := TARecord(RR).TTL;
- if LRR_A.ifAddFullName(NodeCursor.FullName) then begin
- LRR_A.RRName := LRR_A.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtAAAA :
- begin
- LRR_AAAA := TIdRR_AAAA.Create;
- try
- NodeCursor.RRs.Add(LRR_AAAA);
- except
- LRR_AAAA.Free;
- raise;
- end;
- LRR_AAAA.RRName := RRName;
- LRR_AAAA.Address := TAAAARecord(RR).Address;
- LRR_AAAA.TTL := TAAAARecord(RR).TTL;
- if LRR_AAAA.ifAddFullName(NodeCursor.FullName) then begin
- LRR_AAAA.RRName := LRR_AAAA.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtNS:
- begin
- LRR_NS := TIdRR_NS.Create;
- try
- NodeCursor.RRs.Add(LRR_NS);
- except
- LRR_NS.Free;
- raise;
- end;
- LRR_NS.RRName := RRName;
- LRR_NS.NSDName := TNSRecord(RR).HostName;
- LRR_NS.TTL := TNSRecord(RR).TTL;
- if LRR_NS.ifAddFullName(NodeCursor.FullName) then begin
- LRR_NS.RRName := LRR_NS.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtMD, qtMF, qtMB:
- begin
- LRR_MB := TIdRR_MB.Create;
- try
- NodeCursor.RRs.Add(LRR_MB);
- except
- LRR_MB.Free;
- raise;
- end;
- LRR_MB.RRName := RRName;
- LRR_MB.MADName := TNAMERecord(RR).HostName;
- LRR_MB.TTL := TNAMERecord(RR).TTL;
- if LRR_MB.ifAddFullName(NodeCursor.FullName) then begin
- LRR_MB.RRName := LRR_MB.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtName:
- begin
- LRR_Name := TIdRR_CName.Create;
- try
- NodeCursor.RRs.Add(LRR_Name);
- except
- LRR_Name.Free;
- raise;
- end;
- LRR_Name.RRName := RRName;
- LRR_Name.CName := TNAMERecord(RR).HostName;
- LRR_Name.TTL:= TNAMERecord(RR).TTL;
- if LRR_Name.ifAddFullName(NodeCursor.FullName) then begin
- LRR_Name.RRName := LRR_Name.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtSOA:
- begin
- LRR_SOA := TIdRR_SOA.Create;
- try
- NodeCursor.RRs.Add(LRR_SOA);
- except
- LRR_SOA.Free;
- raise;
- end;
- LRR_SOA.RRName := RRName;
- LRR_SOA.MName := TSOARecord(RR).Primary;
- LRR_SOA.RName := TSOARecord(RR).ResponsiblePerson;
- LRR_SOA.Serial := IntToStr(TSOARecord(RR).Serial);
- LRR_SOA.Minimum := IntToStr(TSOARecord(RR).MinimumTTL);
- LRR_SOA.Refresh := IntToStr(TSOARecord(RR).Refresh);
- LRR_SOA.Retry := IntToStr(TSOARecord(RR).Retry);
- LRR_SOA.Expire := IntToStr(TSOARecord(RR).Expire);
- LRR_SOA.TTL:= TSOARecord(RR).TTL;
- if LRR_SOA.ifAddFullName(NodeCursor.FullName) then begin
- LRR_SOA.RRName := LRR_SOA.RRName + '.'+ NodeCursor.FullName;
- end
- else if not TextEndsWith(LRR_SOA.RRName, '.') then begin
- LRR_SOA.RRName := LRR_SOA.RRName + '.';
- end;
- end;
- qtMG :
- begin
- LRR_MG := TIdRR_MG.Create;
- try
- NodeCursor.RRs.Add(LRR_MG);
- except
- LRR_MG.Free;
- raise;
- end;
- LRR_MG.RRName := RRName;
- LRR_MG.MGMName := TNAMERecord(RR).HostName;
- LRR_MG.TTL := TNAMERecord(RR).TTL;
- if LRR_MG.ifAddFullName(NodeCursor.FullName) then begin
- LRR_MG.RRName := LRR_MG.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtMR :
- begin
- LRR_MR := TIdRR_MR.Create;
- try
- NodeCursor.RRs.Add(LRR_MR);
- except
- LRR_MR.Free;
- raise;
- end;
- LRR_MR.RRName := RRName;
- LRR_MR.NewName := TNAMERecord(RR).HostName;
- LRR_MR.TTL := TNAMERecord(RR).TTL;
- if LRR_MR.ifAddFullName(NodeCursor.FullName) then begin
- LRR_MR.RRName := LRR_MR.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtWKS:
- begin
- end;
- qtPTR:
- begin
- LRR_PTR := TIdRR_PTR.Create;
- try
- NodeCursor.RRs.Add(LRR_PTR);
- except
- LRR_PTR.Free;
- raise;
- end;
- LRR_PTR.RRName := RRName;
- LRR_PTR.PTRDName := TPTRRecord(RR).HostName;
- LRR_PTR.TTL := TPTRRecord(RR).TTL;
- if LRR_PTR.ifAddFullName(NodeCursor.FullName) then begin
- LRR_PTR.RRName := LRR_PTR.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtHINFO:
- begin
- LRR_HINFO := TIdRR_HINFO.Create;
- try
- NodeCursor.RRs.Add(LRR_HINFO);
- except
- LRR_HINFO.Free;
- raise;
- end;
- LRR_HINFO.RRName := RRName;
- LRR_HINFO.CPU := THINFORecord(RR).CPU;
- LRR_HINFO.OS := THINFORecord(RR).OS;
- LRR_HINFO.TTL := THINFORecord(RR).TTL;
- if LRR_HINFO.ifAddFullName(NodeCursor.FullName) then begin
- LRR_HINFO.RRName := LRR_HINFO.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtMINFO:
- begin
- LRR_MINFO := TIdRR_MINFO.Create;
- try
- NodeCursor.RRs.Add(LRR_MINFO);
- except
- LRR_MINFO.Free;
- raise;
- end;
- LRR_MINFO.RRName := RRName;
- LRR_MINFO.Responsible_Mail := TMINFORecord(RR).ResponsiblePersonMailbox;
- LRR_MINFO.ErrorHandle_Mail := TMINFORecord(RR).ErrorMailbox;
- LRR_MINFO.TTL := TMINFORecord(RR).TTL;
- if LRR_MINFO.ifAddFullName(NodeCursor.FullName) then begin
- LRR_MINFO.RRName := LRR_MINFO.RRName + '.' + NodeCursor.FullName;
- end;
- end;
- qtMX:
- begin
- LRR_MX := TIdRR_MX.Create;
- try
- NodeCursor.RRs.Add(LRR_MX);
- except
- LRR_MX.Free;
- raise;
- end;
- LRR_MX.RRName := RRName;
- LRR_MX.Exchange := TMXRecord(RR).ExchangeServer;
- LRR_MX.Preference := IntToStr(TMXRecord(RR).Preference);
- LRR_MX.TTL := TMXRecord(RR).TTL;
- if LRR_MX.ifAddFullName(NodeCursor.FullName) then begin
- LRR_MX.RRName := LRR_MX.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- qtTXT, qtNULL:
- begin
- LRR_TXT := TIdRR_TXT.Create;
- try
- NodeCursor.RRs.Add(LRR_TXT);
- except
- LRR_TXT.Free;
- raise;
- end;
- LRR_TXT.RRName := RRName;
- LRR_TXT.TXT := TTextRecord(RR).Text.Text;
- LRR_TXT.TTL := TTextRecord(RR).TTL;
- if LRR_TXT.ifAddFullName(NodeCursor.FullName) then begin
- LRR_TXT.RRName := LRR_TXT.RRName + '.'+ NodeCursor.FullName;
- end;
- end;
- end;
- finally
- NameNode.Free;
- end;
- end;
- procedure TIdDNS_UDPServer.UpdateTree(TreeRoot: TIdDNTreeNode; RR: TIdTextModeResourceRecord);
- var
- NameNode : TStrings;
- RRName, APart : String;
- Count, NodeIndex, RRIndex : Integer;
- NodeCursor : TIdDNTreeNode;
- LRR_AAAA : TIdRR_AAAA;
- LRR_A : TIdRR_A;
- LRR_NS : TIdRR_NS;
- LRR_MB : TIdRR_MB;
- LRR_Name : TIdRR_CName;
- LRR_SOA : TIdRR_SOA;
- LRR_MG : TIdRR_MG;
- LRR_MR : TIdRR_MR;
- LRR_PTR : TIdRR_PTR;
- LRR_HINFO : TIdRR_HINFO;
- LRR_MINFO : TIdRR_MINFO;
- LRR_MX : TIdRR_MX;
- LRR_TXT : TIdRR_TXT;
- LRR_Error : TIdRR_Error;
- begin
- NameNode := TStringList.Create;
- try
- RRName := RR.RRName;
- repeat
- APart := Fetch(RRName, '.');
- if APart <> '' then begin
- NameNode.Add(APart);
- end;
- until RRName = '';
- NodeCursor := TreeRoot;
- RRName := RR.RRName;
- if not TextEndsWith(RRName, '.') then begin
- RR.RRName := RR.RRName + '.';
- end;
- // VC: in2002-02-24-1715, it just denoted TIdRR_A and TIdRR_PTR,
- // but that make search a domain name RR becoming complex,
- // therefor I replace it with all RRs but not TIdRR_SOA
- // SOA should own independent node.
- if (not (RR is TIdRR_SOA)) and (Handed_DomainList.IndexOf(LowerCase(RR.RRName)) = -1) then begin
- for Count := NameNode.Count - 1 downto 1 do begin
- NodeIndex := NodeCursor.ChildIndex.IndexOf(NameNode.Strings[Count]);
- if NodeIndex = -1 then begin
- NodeCursor := NodeCursor.AddChild;
- NodeCursor.AutoSortChild := True;
- NodeCursor.CLabel := NameNode.Strings[Count];
- end else begin
- NodeCursor := NodeCursor.Children[NodeIndex];
- end;
- end;
- RRName := NameNode.Strings[0];
- end else begin
- for Count := NameNode.Count -1 downto 0 do begin
- NodeIndex := NodeCursor.ChildIndex.IndexOf(NameNode.Strings[Count]);
- RRName := NameNode.Strings[Count];
- if NodeIndex = -1 then begin
- NodeCursor := NodeCursor.AddChild;
- NodeCursor.AutoSortChild := True;
- NodeCursor.CLabel := RRName;
- end else begin
- NodeCursor := NodeCursor.Children[NodeIndex];
- end;
- end;
- RRName := RR.RRName;
- end;
- RRIndex := NodeCursor.RRs.ItemNames.IndexOf(RRName);
- if RRIndex = -1 then begin
- NodeCursor.RRs.ItemNames.Add(RRName);
- end else begin
- repeat
- Inc(RRIndex);
- if RRIndex > NodeCursor.RRs.ItemNames.Count -1 then begin
- RRIndex := -1;
- Break;
- end;
- if NodeCursor.RRs.ItemNames.Strings[RRIndex] <> RRName then begin
- Break;
- end;
- until RRIndex > (NodeCursor.RRs.ItemNames.Count-1);
- if RRIndex = -1 then begin
- NodeCursor.RRs.ItemNames.Add(RRName);
- end else begin
- NodeCursor.RRs.ItemNames.Insert(RRIndex, RRName);
- end;
- end;
- case RR.TypeCode of
- TypeCode_Error :
- begin
- LRR_Error := TIdRR_Error(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_Error);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_Error);
- end;
- end;
- TypeCode_A :
- begin
- LRR_A := TIdRR_A(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_A);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_A);
- end;
- end;
- TypeCode_AAAA :
- begin
- LRR_AAAA := TIdRR_AAAA(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_AAAA);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_AAAA);
- end;
- end;
- TypeCode_NS:
- begin
- LRR_NS := TIdRR_NS(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_NS);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_NS);
- end;
- end;
- TypeCode_MF:
- begin
- LRR_MB := TIdRR_MB(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_MB);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_MB);
- end;
- end;
- TypeCode_CName:
- begin
- LRR_Name := TIdRR_CName(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_Name);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_Name);
- end;
- end;
- TypeCode_SOA:
- begin
- LRR_SOA := TIdRR_SOA(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_SOA);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_SOA);
- end;
- end;
- TypeCode_MG :
- begin
- LRR_MG := TIdRR_MG(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_MG);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_MG);
- end;
- end;
- TypeCode_MR :
- begin
- LRR_MR := TIdRR_MR(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_MR);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_MR);
- end;
- end;
- TypeCode_WKS:
- begin
- end;
- TypeCode_PTR:
- begin
- LRR_PTR := TIdRR_PTR(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_PTR);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_PTR);
- end;
- end;
- TypeCode_HINFO:
- begin
- LRR_HINFO := TIdRR_HINFO(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_HINFO);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_HINFO);
- end;
- end;
- TypeCode_MINFO:
- begin
- LRR_MINFO := TIdRR_MINFO(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_MINFO);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_MINFO);
- end;
- end;
- TypeCode_MX:
- begin
- LRR_MX := TIdRR_MX(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_MX);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_MX);
- end;
- end;
- TypeCode_TXT, TypeCode_NULL:
- begin
- LRR_TXT := TIdRR_TXT(RR);
- if RRIndex = -1 then begin
- NodeCursor.RRs.Add(LRR_TXT);
- end else begin
- NodeCursor.RRs.Insert(RRIndex, LRR_TXT);
- end;
- end;
- end;
- finally
- NameNode.Free;
- end;
- end;
- procedure TIdDNS_UDPServer.DoAfterSendBack(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var QueryResult: TIdBytes; var ResultCode: String;
- Query : TIdBytes);
- begin
- if Assigned(FOnAfterSendBack) then begin
- FOnAfterSendBack(ABinding, ADNSHeader, QueryResult, ResultCode, Query);
- end;
- end;
- function TIdDNS_UDPServer.AXFR(Header : TDNSHeader; Question: string; var Answer: TIdBytes): string;
- var
- TargetNode : TIdDNTreeNode;
- IsMyDomains : Boolean;
- RRcount : Integer;
- Temp: TIdBytes;
- begin
- Question := LowerCase(Question);
- IsMyDomains := Handed_DomainList.IndexOf(Question) > -1;
- if not IsMyDomains then begin
- Fetch(Question, '.');
- IsMyDomains := Handed_DomainList.IndexOf(Question) > -1;
- end;
- // Is my domain, go for searching the node.
- TargetNode := nil;
- SetLength(Answer, 0);
- Header.ANCount := 0;
- if IsMyDomains then begin
- TargetNode := SearchTree(Handed_Tree, Question, TypeCode_SOA);
- end;
- if IsMyDomains and (TargetNode <> nil) then begin
- // combine the AXFR Data(So many)
- RRCount := 0;
- Answer := TargetNode.DumpAllBinaryData(RRCount);
- Header.ANCount := RRCount;
- Header.QR := iQr_Answer;
- Header.AA := iAA_Authoritative;
- Header.RCode := iRCodeNoError;
- Header.QDCount := 0;
- Header.ARCount := 0;
- Header.TC := 0;
- Temp := Header.GenerateBinaryHeader;
- AppendBytes(Temp, Answer);
- Answer := Temp;
- Result := cRCodeQueryOK;
- end else begin
- Header.QR := iQr_Answer;
- Header.AA := iAA_Authoritative;
- Header.RCode := iRCodeNameError;
- Header.QDCount := 0;
- Header.ARCount := 0;
- Header.TC := 0;
- Answer := Header.GenerateBinaryHeader;
- Result := cRCodeQueryNotFound;
- end;
- end;
- procedure TIdDNS_UDPServer.InternalSearch(Header: TDNSHeader; QName: string;
- QType : UInt16; var Answer: TIdBytes; IfMainQuestion : Boolean;
- IsSearchCache : Boolean = False; IsAdditional : Boolean = False;
- IsWildCard : Boolean = False; WildCardOrgName : string = '');
- var
- MoreAddrSearch : TStrings;
- TargetNode : TIdDNTreeNode;
- Server_Index, RRIndex, Count : Integer;
- LocalAnswer, TempBytes, TempAnswer: TIdBytes;
- temp_QName, temp: string;
- AResult: TIdBytes;
- Stop, Extra, IsMyDomains, ifAdditional : Boolean;
- LDNSResolver : TIdDNSResolver;
- procedure CheckMoreAddrSearch(const AStr: String);
- begin
- if (not IsValidIP(AStr)) and IsHostName(AStr) then begin
- MoreAddrSearch.Add(AStr);
- end;
- end;
- begin
- SetLength(Answer, 0);
- SetLength(Aresult, 0);
- // Search the Handed Tree first.
- MoreAddrSearch := TStringList.Create;
- try
- Extra := False;
- //Pushed := False;
- if not IsSearchCache then begin
- TargetNode := SearchTree(Handed_Tree, QName, QType);
- if TargetNode <> nil then begin //Assemble the Answer.
- RRIndex := TargetNode.RRs.ItemNames.IndexOf(LowerCase(QName));
- if RRIndex = -1 then begin
- { below are added again by Dennies Chang in 2004/7/15
- { According RFC 1035, a full domain name must be tailed by a '.',
- { but in normal behavior, user will not input '.' in last
- { position of the full name. So we have to compare both of the
- { cases. }
- if TextEndsWith(QName, '.') then begin
- SetLength(QName, Length(QName)-1);
- end;
- RRIndex := TargetNode.RRs.ItemNames.IndexOf(LowerCase(QName));
- { above are added again by Dennies Chang in 2004/7/15}
- if RRIndex = -1 then begin
- QName := Fetch(QName, '.');
- RRIndex := TargetNode.RRs.ItemNames.IndexOf(LowerCase(QName));
- end;
- { marked by Dennies Chang in 2004/7/15
- QName:= Fetch(QName, '.');
- RRIndex := TargetNode.RRs.ItemNames.IndexOf(IndyLowerCase(QName));
- }
- end;
- repeat
- temp_QName := QName;
- SetLength(LocalAnswer, 0);
- if RRIndex <> -1 then begin
- case QType of
- TypeCode_A:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_A then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_AAAA:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_AAAA then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_NS:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_NS then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_NS).NSDName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MD:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MF:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_CName:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_CName then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_CName).CName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_SOA:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_SOA then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_SOA).MName);
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_SOA).RName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MB:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MG:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MG then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MG).MGMName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MR:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MR then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MR).NewName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_NULL:
- begin
- {
- if TargetNode.RRs.Items[RRIndex] is TIdRR_NULL then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- }
- end;
- TypeCode_WKS:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_WKS then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_PTR:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_PTR then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_HINFO:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_HINFO then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MINFO:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MINFO then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MX:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MX then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MX).Exchange);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_TXT:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_TXT then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_STAR:
- begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- if IsWildCard and (LocalAnswer <> nil) then begin
- {
- temp := DomainNameToDNSStr(QName+'.'+TargetNode.FullName);
- Fetch(LocalAnswer, temp);
- }
- TempBytes := DomainNameToDNSStr(TargetNode.FullName);
- FetchBytes(LocalAnswer, TempBytes);
- TempBytes := DomainNameToDNSStr(WildCardOrgName);
- AppendBytes(TempBytes, LocalAnswer);
- LocalAnswer := TempBytes;
- //LocalAnswer := DomainNameToDNSStr(WildCardOrgName) + LocalAnswer;
- end;
- if LocalAnswer <> nil then begin
- AppendBytes(Answer, LocalAnswer);
- if ((not Extra) and (not IsAdditional)) or (QType = TypeCode_AAAA) then begin
- if (TargetNode.RRs.Items[RRIndex] is TIdRR_NS) then begin
- if IfMainQuestion then begin
- Header.ANCount := Header.ANCount + 1;
- end else begin
- Header.NSCount := Header.NSCount + 1;
- end;
- end
- else if IfMainQuestion then begin
- Header.ANCount := Header.ANCount + 1;
- end else begin
- Header.ARCount := Header.ARCount + 1;
- end;
- end
- else if IsAdditional then begin
- Header.ARCount := Header.ARCount + 1;
- end
- else begin
- Header.ANCount := Header.ANCount + 1;
- end;
- Header.Qr := iQr_Answer;
- Header.AA := iAA_Authoritative;
- Header.RCode := iRCodeNoError;
- end;
- if RRIndex < (TargetNode.RRs.ItemNames.Count-1) then begin
- Stop := False;
- Inc(RRIndex);
- end else begin
- Stop := True;
- end;
- end else begin
- Stop := True;
- end;
- if QName = temp_QName then begin
- temp_QName := '';
- end;
- until (RRIndex = -1) or
- (not ((not TextIsSame(TargetNode.RRs.ItemNames.Strings[RRIndex], QName)) xor
- (not TextIsSame(TargetNode.RRs.ItemNames.Strings[RRIndex], Fetch(temp_QName, '.')))))
- or Stop;
- // Finish the Loop, but n record is found, we need to search if
- // there is a widechar record in its subdomain.
- // Main, Cache, Additional, Wildcard
- if Answer <> nil then begin
- InternalSearch(Header, '*.' + QName, QType, LocalAnswer, IfMAinQuestion, False, False, True, QName);
- if LocalAnswer <> nil then begin
- AppendBytes(Answer, LocalAnswer);
- end;
- end;
- end else begin // Node can't be found.
- MoreAddrSearch.Clear;
- end;
- if MoreAddrSearch.Count > 0 then begin
- for Count := 0 to MoreAddrSearch.Count -1 do begin
- Server_Index := 0;
- if Handed_DomainList.Count > 0 then begin
- repeat
- IsMyDomains := IndyPos(
- LowerCase(Handed_DomainList.Strings[Server_Index]),
- LowerCase(MoreAddrSearch.Strings[Count])) > 0;
- Inc(Server_Index);
- until IsMyDomains or (Server_Index > (Handed_DomainList.Count-1));
- end else begin
- IsMyDomains := False;
- end;
- if IsMyDomains then begin
- //ifAdditional := (QType <> TypeCode_A) or (QType <> TypeCode_AAAA);
- // modified by Dennies Chang in 2004/7/15.
- ifAdditional := (QType <> TypeCode_CName);
- //Search A record first.
- // Main, Cache, Additional, Wildcard
- InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_A, LocalAnswer, True, False, ifAdditional, False);
- { modified by Dennies Chang in 2004/7/15.
- InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_A,
- LocalAnswer, True, ifAdditional, True);
- }
- if LocalAnswer = nil then begin
- temp := MoreAddrSearch.Strings[Count];
- Fetch(temp, '.');
- temp := '*.' + temp;
- InternalSearch(Header, temp, TypeCode_A, LocalAnswer, True, False, ifAdditional, True, MoreAddrSearch.Strings[Count]);
- { marked by Dennies Chang in 2004/7/15.
- InternalSearch(Header, temp, TypeCode_A, LocalAnswer, True, ifAdditional, True, True, MoreAddrSearch.Strings[Count]);
- }
- end;
- TempAnswer := LocalAnswer;
- // Search for AAAA also.
- InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_AAAA, LocalAnswer, True, False, ifAdditional, True);
- { marked by Dennies Chang in 2004/7/15.
- InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_AAAA, LocalAnswer, True, ifAdditional, True);
- }
- if LocalAnswer = nil then begin
- temp := MoreAddrSearch.Strings[Count];
- Fetch(temp, '.');
- temp := '*.' + temp;
- InternalSearch(Header, temp, TypeCode_AAAA, LocalAnswer, True, False, ifAdditional, True, MoreAddrSearch.Strings[Count]);
- { marked by Dennies Chang in 2004/7/15.
- InternalSearch(Header, temp, TypeCode_AAAA, LocalAnswer, True, ifAdditional, True, True, MoreAddrSearch.Strings[Count]);
- }
- end;
- AppendBytes(TempAnswer, LocalAnswer);
- LocalAnswer := TempAnswer;
- end else begin
- // Need add AAAA Search in future.
- //QType := TypeCode_A;
- LDNSResolver := TIdDNSResolver.Create;
- try
- Server_Index := 0;
- repeat
- LDNSResolver.Host := RootDNS_NET.Strings[Server_Index];
- LDNSResolver.QueryType := [qtA];
- LDNSResolver.Resolve(MoreAddrSearch.Strings[Count]);
- AResult := LDNSResolver.PlainTextResult;
- Header.ARCount := Header.ARCount + LDNSResolver.QueryResult.Count;
- until (Server_Index >= (RootDNS_NET.Count-1)) or (AResult <> nil);
- AppendBytes(LocalAnswer, AResult, 12);
- finally
- LDNSResolver.Free;
- end;
- end;
- if LocalAnswer <> nil then begin
- AppendBytes(Answer, LocalAnswer);
- end;
- //Answer := LocalAnswer;
- end;
- end;
- end else begin
- //Search the Cache Tree;
- { marked by Dennies Chang in 2004/7/15.
- { it's mark for querying cache only.
- { if Answer = nil then begin }
- TargetNode := SearchTree(Cached_Tree, QName, QType);
- if TargetNode <> nil then begin
- //Assemble the Answer.
- { modified by Dennies Chang in 2004/7/15}
- if (QType in [TypeCode_A, TypeCode_PTR, TypeCode_AAAA, TypeCode_Error, TypeCode_CName]) then begin
- QName := Fetch(QName, '.');
- end;
- RRIndex := TargetNode.RRs.ItemNames.IndexOf(QName);
- repeat
- temp_QName := QName;
- SetLength(LocalAnswer, 0);
- if RRIndex <> -1 then begin
- // TimeOut, update the record.
- if CompareDate(Now, StrToDateTime(TargetNode.RRs.Items[RRIndex].TimeOut)) = 1 then begin
- SetLength(LocalAnswer, 0);
- end else begin
- case QType of
- TypeCode_Error:
- begin
- AppendString(Answer, 'Error'); {do not localize}
- end;
- TypeCode_A:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_A then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_AAAA:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_AAAA then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_NS:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_NS then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_NS).NSDName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MD:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MF:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_CName:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_CName then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_CName).CName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_SOA:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_SOA then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_SOA).MName);
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_SOA).RName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MB:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MB then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MB).MADName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MG:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MG then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MG).MGMName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MR:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MR then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MR).NewName);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_NULL:
- begin
- {
- if TargetNode.RRs.Items[RRIndex] is TIdRR_NULL then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- }
- end;
- TypeCode_WKS:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_WKS then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_PTR:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_PTR then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_HINFO:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_HINFO then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MINFO:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MINFO then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_MX:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_MX then begin
- CheckMoreAddrSearch((TargetNode.RRs.Items[RRIndex] as TIdRR_MX).Exchange);
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_TXT:
- begin
- if TargetNode.RRs.Items[RRIndex] is TIdRR_TXT then begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- TypeCode_STAR:
- begin
- LocalAnswer := TargetNode.RRs.Items[RRIndex].BinQueryRecord(TargetNode.FullName);
- end;
- end;
- end;
- if BytesToString(LocalAnswer) = 'Error' then begin {do not localize}
- Stop := True;
- end else begin
- if LocalAnswer <> nil then begin
- AppendBytes(Answer, LocalAnswer);
- if TargetNode.RRs.Items[RRIndex] is TIdRR_NS then begin
- if IfMainQuestion then begin
- Header.ANCount := Header.ANCount + 1;
- end else begin
- Header.NSCount := Header.NSCount + 1;
- end;
- end
- else if IfMainQuestion then begin
- Header.ANCount := Header.ANCount + 1;
- end
- else begin
- Header.ARCount := Header.ARCount + 1;
- end;
- Header.Qr := iQr_Answer;
- Header.AA := iAA_NotAuthoritative;
- Header.RCode := iRCodeNoError;
- end;
- if RRIndex < (TargetNode.RRs.ItemNames.Count-1) then begin
- Stop := False;
- Inc(RRIndex);
- end else begin
- Stop := True;
- end;
- end;
- end else begin
- Stop := True;
- end;
- until (RRIndex = -1) or
- (not ((not TextIsSame(TargetNode.RRs.ItemNames.Strings[RRIndex], QName)) xor
- (not TextIsSame(TargetNode.RRs.ItemNames.Strings[RRIndex], Fetch(temp_QName, '.')))))
- or Stop;
- end;
- // Search MoreAddrSearch it's added in 2004/7/15, but the need is
- // found in 2004 Feb.
- if MoreAddrSearch.Count > 0 then begin
- for Count := 0 to MoreAddrSearch.Count -1 do begin
- Server_Index := 0;
- if Handed_DomainList.Count > 0 then begin
- repeat
- IsMyDomains := IndyPos(
- LowerCase(Handed_DomainList.Strings[Server_Index]),
- LowerCase(MoreAddrSearch.Strings[Count])) > 0;
- Inc(Server_Index);
- until IsMyDomains or (Server_Index > (Handed_DomainList.Count-1));
- end else begin
- IsMyDomains := False;
- end;
- if IsMyDomains then begin
- ifAdditional := (QType <> TypeCode_A) or (QType <> TypeCode_AAAA);
- //Search A record first.
- // Main, Cache, Additional, Wildcard
- InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_A, LocalAnswer, True, False, ifAdditional, False);
- if LocalAnswer = nil then begin
- temp := MoreAddrSearch.Strings[Count];
- Fetch(temp, '.');
- temp := '*.' + temp;
- InternalSearch(Header, temp, TypeCode_A, LocalAnswer, True, False, ifAdditional, True, MoreAddrSearch.Strings[Count]);
- end;
- TempAnswer := LocalAnswer;
- // Search for AAAA also.
- InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_AAAA, LocalAnswer, True, False, ifAdditional, True);
- if LocalAnswer = nil then begin
- temp := MoreAddrSearch.Strings[Count];
- Fetch(temp, '.');
- temp := '*.' + temp;
- InternalSearch(Header, temp, TypeCode_AAAA, LocalAnswer, True, False, ifAdditional, True, MoreAddrSearch.Strings[Count]);
- end;
- AppendBytes(TempAnswer, LocalAnswer);
- LocalAnswer := TempAnswer;
- end else begin
- // 找Cache
- TempAnswer := LocalAnswer;
- ifAdditional := (QType <> TypeCode_A) or (QType <> TypeCode_AAAA);
- //Search A record first.
- // Main, Cache, Additional, Wildcard
- InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_A, LocalAnswer, True, True, ifAdditional, False);
- if LocalAnswer = nil then begin
- temp := MoreAddrSearch.Strings[Count];
- Fetch(temp, '.');
- temp := '*.' + temp;
- InternalSearch(Header, temp, TypeCode_A, LocalAnswer, True, True, ifAdditional, True, MoreAddrSearch.Strings[Count]);
- end;
- AppendBytes(TempAnswer, LocalAnswer);
- LocalAnswer := TempAnswer;
- // Search for AAAA also.
- InternalSearch(Header, MoreAddrSearch.Strings[Count], TypeCode_AAAA, LocalAnswer, True, True, ifAdditional, True);
- if LocalAnswer <> nil then begin
- AppendBytes(TempAnswer, LocalAnswer);
- LocalAnswer := TempAnswer;
- end;
- Answer := LocalAnswer;
- end;
- end;
- end;
- end;
- finally
- MoreAddrSearch.Free;
- end;
- end;
- { TIdDNSServer }
- constructor TIdDNSServer.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FAccessList := TStringList.Create;
- FUDPTunnel := TIdDNS_UDPServer.Create(Self);
- FTCPTunnel := TIdDNS_TCPServer.Create(Self);
- FBindings := TIdSocketHandles.Create(Self);
- FTCPTunnel.DefaultPort := IdPORT_DOMAIN;
- FUDPTunnel.DefaultPort := IdPORT_DOMAIN;
- ServerType := stPrimary;
- BackupDNSMap := TIdDNSMap.Create(FUDPTunnel);
- end;
- destructor TIdDNSServer.Destroy;
- begin
- FAccessList.Free;
- FUDPTunnel.Free;
- FTCPTunnel.Free;
- FBindings.Free;
- BackupDNSMap.Free;
- inherited Destroy;
- end;
- procedure TIdDNSServer.CheckIfExpire(Sender: TObject);
- begin
- end;
- procedure TIdDNSServer.SetAccessList(const Value: TStrings);
- begin
- FAccessList.Assign(Value);
- FTCPTunnel.AccessList.Assign(Value);
- end;
- procedure TIdDNSServer.SetActive(const Value: Boolean);
- var
- Count : Integer;
- DNSMap : TIdDomainNameServerMapping;
- begin
- FActive := Value;
- FUDPTunnel.Active := Value;
- if ServerType = stSecondary then begin
- TCPTunnel.Active := False;
- // TODO: should this loop only be run if Value=True?
- for Count := 0 to BackupDNSMap.Count-1 do begin
- DNSMap := BackupDNSMap.Items[Count];
- DNSMap.CheckScheduler.Start;
- end;
- end else begin
- TCPTunnel.Active := Value;
- end;
- end;
- procedure TIdDNSServer.SetBindings(const Value: TIdSocketHandles);
- begin
- FBindings.Assign(Value);
- FUDPTunnel.Bindings.Assign(Value);
- FTCPTunnel.Bindings.Assign(Value);
- end;
- procedure TIdDNSServer.SetTCPACLActive(const Value: Boolean);
- begin
- FTCPACLActive := Value;
- TCPTunnel.AccessControl := Value;
- if Value then begin
- FTCPTunnel.FAccessList.Assign(FAccessList);
- end else begin
- FTCPTunnel.FAccessList.Clear;
- end;
- end;
- procedure TIdDNSServer.TimeToUpdateNodeData(Sender: TObject);
- var
- Resolver : TIdDNSResolver;
- Count : Integer;
- begin
- Resolver := TIdDNSResolver.Create(Self);
- try
- Resolver.Host := UDPTunnel.RootDNS_NET.Strings[0];
- Resolver.QueryType := [qtAXFR];
- Resolver.Resolve((Sender as TIdDNTreeNode).FullName);
- for Count := 0 to Resolver.QueryResult.Count-1 do begin
- UDPTunnel.UpdateTree(UDPTunnel.Handed_Tree, Resolver.QueryResult.Items[Count]);
- end;
- finally
- Resolver.Free;
- end;
- end;
- { TIdDNS_TCPServer }
- constructor TIdDNS_TCPServer.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FAccessList := TStringList.Create;
- end;
- destructor TIdDNS_TCPServer.Destroy;
- begin
- FAccessList.Free;
- inherited Destroy;
- end;
- procedure TIdDNS_TCPServer.DoConnect(AContext: TIdContext);
- var
- Answer, Data, Question: TIdBytes;
- QName, QLabel, QResult, PeerIP : string;
- LData, QPos, LLength : Integer;
- TestHeader : TDNSHeader;
- procedure GenerateAXFRData;
- begin
- TestHeader := TDNSHeader.Create;
- try
- TestHeader.ParseQuery(Data);
- if TestHeader.QDCount > 0 then begin
- // parse the question.
- QPos := 13;
- QLabel := '';
- QName := '';
- repeat
- LLength := Byte(Data[QPos]);
- Inc(QPos);
- QLabel := BytesToString(Data, QPos, LLength);
- Inc(QPos, LLength);
- QName := QName + QLabel + '.';
- until (QPos >= LData) or (Data[QPos] = 0);
- Question := Copy(Data, 13, Length(Data)-12);
- QResult := TIdDNSServer(Owner).UDPTunnel.AXFR(TestHeader, QName, Answer);
- end;
- finally
- TestHeader.Free;
- end;
- end;
- procedure GenerateAXFRRefuseData;
- begin
- TestHeader := TDNSHeader.Create;
- try
- TestHeader.ParseQuery(Data);
- TestHeader.Qr := iQr_Answer;
- TestHeader.RCode := iRCodeRefused;
- Answer := TestHeader.GenerateBinaryHeader;
- finally
- TestHeader.Free;
- end;
- end;
- begin
- inherited DoConnect(AContext);
- LData := AContext.Connection.IOHandler.ReadInt16;
- SetLength(Data, 0);
- // RLebeau - why not use ReadBuffer() here?
- // Dennies - Sure, in older version, my concern is for real time generate system
- // might not generate the data with correct data size we expect.
- AContext.Connection.IOHandler.ReadBytes(Data, LData);
- {for Count := 1 to LData do begin
- AppendByte(Data, AThread.Connection.IOHandler.ReadByte);
- end;
- }
- // PeerIP is ip address.
- PeerIP := AContext.Binding.PeerIP;
- if AccessControl and (AccessList.IndexOf(PeerIP) = -1) then begin
- GenerateAXFRRefuseData;
- end else begin
- GenerateAXFRData;
- end;
- if Length(Answer) > 32767 then begin
- SetLength(Answer, 32767);
- end;
- AContext.Connection.IOHandler.Write(Int16(Length(Answer)));
- AContext.Connection.IOHandler.Write(Answer);
- end;
- procedure TIdDNS_TCPServer.SetAccessList(const Value: TStrings);
- begin
- FAccessList.Assign(Value);
- end;
- { TIdDomainExpireCheckThread }
- procedure TIdDomainExpireCheckThread.Run;
- var
- LInterval, LStep: Integer;
- begin
- LInterval := FInterval;
- while LInterval > 0 do begin
- LStep := IndyMin(LInterval, 500);
- IndySleep(LStep);
- Dec(LInterval, LStep);
- if Terminated then begin
- Exit;
- end;
- if Assigned(FTimerEvent) then begin
- Synchronize(TimerEvent);
- end;
- end;
- end;
- procedure TIdDomainExpireCheckThread.TimerEvent;
- begin
- if Assigned(FTimerEvent) then begin
- FTimerEvent(FSender);
- end;
- end;
- { TIdDomainNameServerMapping }
- constructor TIdDomainNameServerMapping.Create(AList : TIdDNSMap);
- begin
- inherited Create;
- CheckScheduler := TIdDomainExpireCheckThread.Create;
- CheckScheduler.FInterval := 100000;
- CheckScheduler.FSender := Self;
- CheckScheduler.FDomain := DomainName;
- CheckScheduler.FHost := Host;
- CheckScheduler.FTimerEvent := SyncAndUpdate;
- FList := List;
- FBusy := False;
- end;
- destructor TIdDomainNameServerMapping.Destroy;
- begin
- if Assigned(CheckScheduler) then
- begin
- //Self.CheckScheduler.TerminateAndWaitFor;
- CheckScheduler.Terminate;
- CheckScheduler.Free;
- end;
- inherited Destroy;
- end;
- procedure TIdDomainNameServerMapping.SetHost(const Value: string);
- begin
- if (not IsValidIP(Value)) and (not IsValidIPv6(Value)) then begin
- raise EIdDNSServerSettingException.Create(RSDNSServerSettingError_MappingHostError);
- end;
- FHost := Value;
- end;
- procedure TIdDomainNameServerMapping.SetInterval(const Value: UInt32);
- begin
- FInterval := Value;
- CheckScheduler.FInterval := Value;
- end;
- procedure TIdDomainNameServerMapping.SyncAndUpdate(Sender: TObject);
- //Todo - Dennies Chang should append axfr and update Tree.
- var
- Resolver : TIdDNSResolver;
- RR : TResultRecord;
- TNode : TIdDNTreeNode;
- Server : TIdDNS_UDPServer;
- NeedUpdated, NotThis : Boolean;
- Count, TIndex : Integer;
- RRName : string;
- begin
- if FBusy then begin
- Exit;
- end;
- FBusy := True;
- try
- Resolver := TIdDNSResolver.Create(nil);
- try
- Resolver.Host := Host;
- Resolver.QueryType := [qtAXFR];
- Resolver.Resolve(DomainName);
- if Resolver.QueryResult.Count = 0 then begin
- raise EIdDNSServerSyncException.Create(RSDNSServerAXFRError_QuerySequenceError);
- end;
- RR := Resolver.QueryResult.Items[0];
- if RR.RecType <> qtSOA then begin
- raise EIdDNSServerSyncException.Create(RSDNSServerAXFRError_QuerySequenceError);
- end;
- Server := List.Server;
- Interval := TSOARecord(RR).Expire * 1000;
- {
- //Update MyDomain
- if not TextEndsWith(RR.Name, '.') then begin
- RRName := RR.Name + '.';
- end;
- }
- if Server.Handed_DomainList.IndexOf(RR.Name) = -1 then begin
- Server.Handed_DomainList.Add(RR.Name);
- end;
- TNode := Server.SearchTree(Server.Handed_Tree, RR.Name, TypeCode_SOA);
- if TNode = nil then begin
- NeedUpdated := True;
- end else begin
- RRName := RRName;
- RRName := Fetch(RRName, '.');
- TIndex := TNode.RRs.ItemNames.IndexOf(RR.Name);
- NotThis := True;
- while (TIndex > -1) and (TIndex <= (TNode.RRs.Count-1)) and
- (TNode.RRs.Items[TIndex].RRName = RR.Name) and NotThis do
- begin
- NotThis := not (TNode.RRs.Items[TIndex] is TIdRR_SOA);
- Inc(TIndex);
- end;
- if not NotThis then begin
- Dec(TIndex);
- NeedUpdated := (TNode.RRs.Items[TIndex] as TIdRR_SOA).Serial = IntToStr(TSOARecord(RR).Serial);
- end else begin
- NeedUpdated := True;
- end;
- end;
- if NeedUpdated then begin
- if TNode <> nil then begin
- Server.Handed_Tree.RemoveChild(Server.Handed_Tree.IndexByNode(TNode));
- end;
- for Count := 0 to Resolver.QueryResult.Count-1 do begin
- RR := Resolver.QueryResult.Items[Count];
- Server.UpdateTree(Server.Handed_Tree, RR);
- end;
- end;
- finally
- Resolver.Free;
- end;
- finally
- FBusy := False;
- end;
- end;
- { TIdDNSMap }
- constructor TIdDNSMap.Create(Server: TIdDNS_UDPServer);
- begin
- inherited Create;
- FServer := Server;
- end;
- {$IFNDEF USE_OBJECT_ARC}
- destructor TIdDNSMap.Destroy;
- var
- I : Integer;
- DNSMP : TIdDomainNameServerMapping;
- begin
- if Count > 0 then begin
- for I := Count-1 downto 0 do begin
- DNSMP := Items[I];
- Delete(I);
- DNSMP.Free;
- end;
- end;
- inherited Destroy;
- end;
- {$ENDIF}
- {$IFNDEF HAS_GENERICS_TObjectList}
- function TIdDNSMap.GetItem(Index: Integer): TIdDomainNameServerMapping;
- begin
- Result := TIdDomainNameServerMapping(inherited GetItem(Index));
- end;
- procedure TIdDNSMap.SetItem(Index: Integer; const Value: TIdDomainNameServerMapping);
- begin
- inherited SetItem(Index, Value);
- end;
- {$ENDIF}
- procedure TIdDNSMap.SetServer(const Value: TIdDNS_UDPServer);
- begin
- FServer := Value;
- end;
- { TIdDNS_ProcessThread }
- constructor TIdDNS_ProcessThread.Create(ACreateSuspended: Boolean;
- Data: TIdBytes; MainBinding, Binding: TIdSocketHandle;
- Server: TIdDNS_UDPServer);
- begin
- inherited Create(ACreateSuspended);
- FMyData := nil;
- FData := Data;
- FMyBinding := Binding;
- FMainBinding := MainBinding;
- FServer := Server;
- FreeOnTerminate := True;
- end;
- procedure TIdDNS_ProcessThread.ComposeErrorResult(var VFinal: TIdBytes;
- OriginalHeader: TDNSHeader; OriginalQuestion : TIdBytes;
- ErrorStatus: Integer);
- begin
- case ErrorStatus of
- iRCodeQueryNotImplement :
- begin
- OriginalHeader.Qr := iQr_Answer;
- OriginalHeader.RCode := iRCodeNotImplemented;
- VFinal := OriginalHeader.GenerateBinaryHeader;
- AppendBytes(VFinal, OriginalQuestion, 12);
- end;
- iRCodeQueryNotFound :
- begin
- OriginalHeader.Qr := iQr_Answer;
- OriginalHeader.RCode := iRCodeNameError;
- OriginalHeader.ANCount := 0;
- VFinal := OriginalHeader.GenerateBinaryHeader;
- //VFinal := VFinal;
- end;
- end;
- end;
- destructor TIdDNS_ProcessThread.Destroy;
- begin
- FServer := nil;
- FMainBinding := nil;
- if Assigned(FMyBinding) then begin
- FMyBinding.CloseSocket;
- FMyBinding.Free;
- end;
- FMyData.Free;
- inherited Destroy;
- end;
- procedure TIdDNS_ProcessThread.QueryDomain;
- var
- QName, QLabel, RString : string;
- Temp, ExternalQuery, Answer, FinalResult : TIdBytes;
- DNSHeader_Processing : TDNSHeader;
- QType, QClass : UInt16;
- QPos, QLength, LLength : Integer;
- ABinding: TIdSocketHandle;
- begin
- ExternalQuery := FData;
- ABinding := MyBinding;
- Temp := Copy(FData, 0, Length(FData));
- SetLength(FinalResult, 0);
- QType := TypeCode_A;
- if Length(FData) >= 12 then begin
- DNSHeader_Processing := TDNSHeader.Create;
- try
- // RLebeau: this does not make sense to me. ParseQuery() always returns
- // 0 when the data length is >= 12 unless an exception is raised, which
- // should only happen if the GStack object is invalid...
- //
- if DNSHeader_Processing.ParseQuery(ExternalQuery) <> 0 then begin
- FServer.DoAfterQuery(ABinding, DNSHeader_Processing, Temp, RString, ExternalQuery);
- AppendBytes(FinalResult, Temp);
- end else begin
- if DNSHeader_Processing.QDCount > 0 then begin
- QPos := 12; //13; Modified in Dec. 13, 2004 by Dennies
- QLength := Length(ExternalQuery);
- if QLength > 12 then begin
- QName := '';
- repeat
- SetLength(Answer, 0);
- LLength := ExternalQuery[QPos];
- Inc(QPos);
- QLabel := BytesToString(ExternalQuery, QPos, LLength);
- Inc(QPos, LLength);
- QName := QName + QLabel + '.';
- until (QPos >= QLength) or (ExternalQuery[QPos] = 0);
- Inc(QPos);
- QType := GStack.NetworkToHost(TwoByteToUInt16(ExternalQuery[QPos], ExternalQuery[QPos + 1]));
- Inc(QPos, 2);
- QClass := GStack.NetworkToHost(TwoByteToUInt16(ExternalQuery[QPos], ExternalQuery[QPos + 1]));
- FServer.DoBeforeQuery(ABinding, DNSHeader_Processing, Temp);
- RString := CompleteQuery(DNSHeader_Processing, QName, ExternalQuery, Answer, QType, QClass, nil);
- if RString = cRCodeQueryNotImplement then begin
- ComposeErrorResult(FinalResult, DNSHeader_Processing, ExternalQuery, iRCodeQueryNotImplement);
- end
- else if (RString = cRCodeQueryReturned) then begin
- FinalResult := Answer;
- end
- else if (RString = cRCodeQueryNotFound) or (RString = cRCodeQueryCacheFindError) then begin
- ComposeErrorResult(FinalResult, DNSHeader_Processing, ExternalQuery, iRCodeQueryNotFound);
- end
- else begin
- FinalResult := CombineAnswer(DNSHeader_Processing, ExternalQuery, Answer);
- end;
- FServer.DoAfterQuery(ABinding, DNSHeader_Processing, FinalResult, RString, Temp);
- //AppendString(FinalResult, Temp);
- end;
- end;
- end;
- finally
- try
- FData := FinalResult;
- FServer.DoAfterSendBack(ABinding, DNSHeader_Processing, FinalResult, RString, ExternalQuery);
- if (FServer.CacheUnknowZone) and
- (RString <> cRCodeQueryCacheFindError) and
- (RString <> cRCodeQueryCacheOK) and
- (RString <> cRCodeQueryOK) and
- (RString <> cRCodeQueryNotImplement) then
- begin
- FServer.SaveToCache(FinalResult, QName, QType);
- FServer.DoAfterCacheSaved(Self.FServer.FCached_Tree);
- end;
- finally
- DNSHeader_Processing.Free;
- end;
- end;
- end;
- end;
- procedure TIdDNS_ProcessThread.Run;
- begin
- try
- QueryDomain;
- SendData;
- finally
- Stop;
- Terminate;
- end;
- end;
- procedure TIdDNS_ProcessThread.SetMyBinding(const Value: TIdSocketHandle);
- begin
- FMyBinding := Value;
- end;
- procedure TIdDNS_ProcessThread.SetMyData(const Value: TStream);
- begin
- FMyData := Value;
- end;
- procedure TIdDNS_ProcessThread.SetServer(const Value: TIdDNS_UDPServer);
- begin
- FServer := Value;
- end;
- function TIdDNS_ProcessThread.CombineAnswer(Header: TDNSHeader; const EQuery, Answer: TIdBytes): TIdBytes;
- begin
- Result := Header.GenerateBinaryHeader;
- AppendBytes(Result, EQuery, 12);
- AppendBytes(Result, Answer);
- end;
- procedure TIdDNS_ProcessThread.ExternalSearch(ADNSResolver: TIdDNSResolver; Header: TDNSHeader;
- Question: TIdBytes; var Answer: TIdBytes);
- var
- Server_Index : Integer;
- MyDNSResolver : TIdDNSResolver;
- begin
- Server_Index := 0;
- if ADNSResolver = nil then begin
- MyDNSResolver := TIdDNSResolver.Create;
- MyDNSResolver.WaitingTime := 2000;
- end else
- begin
- MyDNSResolver := ADNSResolver;
- end;
- try
- repeat
- MyDNSResolver.Host := FServer.RootDNS_NET.Strings[Server_Index];
- try
- MyDNSResolver.InternalQuery := Question;
- MyDNSResolver.Resolve('');
- Answer := MyDNSResolver.PlainTextResult;
- except
- // Todo: Create DNS server interal resolver error.
- on EIdDnsResolverError do
- begin
- //Empty Event, for user to custom the event handle.
- end;
- on EIdSocketError do
- begin
- end;
- else
- begin
- end;
- end;
- Inc(Server_Index);
- until (Server_Index >= FServer.RootDNS_NET.Count) or (Answer <> nil);
- finally
- if ADNSResolver = nil then begin
- MyDNSResolver.Free;
- end;
- end;
- end;
- procedure TIdDNS_ProcessThread.InternalSearch(Header: TDNSHeader; QName: string; QType: UInt16;
- var Answer: TIdBytes; IfMainQuestion: boolean; IsSearchCache: Boolean = False;
- IsAdditional: boolean = false; IsWildCard : boolean = false;
- WildCardOrgName: string = '');
- begin
- end;
- procedure TIdDNS_ProcessThread.SaveToCache(ResourceRecord: TIdBytes; QueryName: string; OriginalQType: UInt16);
- var
- TempResolver : TIdDNSResolver;
- Count : Integer;
- TNode : TIdDNTreeNode;
- RR_Err : TIdRR_Error;
- begin
- TempResolver := TIdDNSResolver.Create(nil);
- try
- // RLebeau: FillResultWithOutCheckId() is deprecated, but not using FillResult()
- // here yet because it validates the DNSHeader.RCode, and I do not know if that
- // is needed here. I don't want to break this logic...
- TempResolver.FillResultWithOutCheckId(ResourceRecord);
- if TempResolver.DNSHeader.ANCount > 0 then begin
- for Count := 0 to TempResolver.QueryResult.Count-1 do begin
- FServer.UpdateTree(FServer.Cached_Tree, TempResolver.QueryResult.Items[Count]);
- end; // for loop
- end else begin
- TNode := Self.SearchTree(FServer.Cached_Tree, QueryName, TypeCode_Error);
- if TNode = nil then begin
- RR_Err := TIdRR_Error.Create;
- RR_Err.RRName := QueryName;
- RR_Err.TTL := 600;
- FServer.UpdateTree(FServer.Cached_Tree, RR_Err);
- end;
- end;
- finally
- TempResolver.Free;
- end;
- end;
- function TIdDNS_ProcessThread.SearchTree(Root: TIdDNTreeNode; QName: String; QType: UInt16): TIdDNTreeNode;
- var
- RRIndex : integer;
- NodeCursor : TIdDNTreeNode;
- NameLabels : TStrings;
- OneNode, FullName : string;
- Found : Boolean;
- begin
- Result := nil;
- NameLabels := TStringList.Create;
- try
- FullName := QName;
- NodeCursor := Root;
- Found := False;
- repeat
- OneNode := Fetch(FullName, '.');
- if OneNode <> '' then begin
- NameLabels.Add(OneNode);
- end;
- until FullName = '';
- repeat
- IndySleep(0);
- if QType <> TypeCode_SOA then begin
- RRIndex := NodeCursor.ChildIndex.IndexOf(NameLabels.Strings[NameLabels.Count - 1]);
- if RRIndex <> -1 then begin
- NameLabels.Delete(NameLabels.Count - 1);
- NodeCursor := NodeCursor.Children[RRIndex];
- if NameLabels.Count = 1 then begin
- Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
- end else begin
- Found := NameLabels.Count = 0;
- end;
- end
- else if NameLabels.Count = 1 then begin
- Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
- if not Found then begin
- NameLabels.Clear;
- end;
- end
- else begin
- NameLabels.Clear;
- end;
- end else begin
- RRIndex := NodeCursor.ChildIndex.IndexOf(NameLabels.Strings[NameLabels.Count - 1]);
- if RRIndex <> -1 then begin
- NameLabels.Delete(NameLabels.Count - 1);
- NodeCursor := NodeCursor.Children[RRIndex];
- if NameLabels.Count = 1 then begin
- Found := NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1;
- end else begin
- Found := NameLabels.Count = 0;
- end;
- end
- else if NameLabels.Count = 1 then begin
- Found := (NodeCursor.RRs.ItemNames.IndexOf(NameLabels.Strings[0]) <> -1);
- if not Found then begin
- NameLabels.Clear;
- end;
- end
- else begin
- NameLabels.Clear;
- end;
- end;
- until (NameLabels.Count = 0) or Found;
- if Found then begin
- Result := NodeCursor;
- end;
- finally
- NameLabels.Free;
- end;
- end;
- function TIdDNS_ProcessThread.CompleteQuery(DNSHeader: TDNSHeader;
- Question: string; OriginalQuestion: TIdBytes; var Answer : TIdBytes;
- QType, QClass : UInt16; DNSResolver : TIdDNSResolver) : string;
- var
- IsMyDomains : boolean;
- LAnswer, TempAnswer, RRData: TIdBytes;
- WildQuestion, TempDomain : string;
- LIdx: Integer;
- begin
- // QClass = 1 => IN, we support only "IN" class now.
- // QClass = 2 => CS,
- // QClass = 3 => CH, we suppor "CHAOS" class now, but only "version.bind." info.
- // from 2004/6/28
- // QClass = 4 => HS.
- RRData := nil;
- TempAnswer := nil;
- TempDomain := LowerCase(Question);
- case QClass of
- Class_IN :
- begin
- IsMyDomains := FServer.Handed_DomainList.IndexOf(TempDomain) > -1;
- if not IsMyDomains then begin
- Fetch(TempDomain, '.');
- IsMyDomains := FServer.Handed_DomainList.IndexOf(TempDomain) > -1;
- end;
- if IsMyDomains then begin
- FServer.InternalSearch(DNSHeader, Question, QType, LAnswer, True, False, False);
- Answer := LAnswer;
- if (QType in [TypeCode_A, TypeCode_AAAA]) and (Answer = nil) then begin
- FServer.InternalSearch(DNSHeader, Question, TypeCode_CNAME, LAnswer, True, False, True);
- if LAnswer <> nil then begin
- AppendBytes(Answer, LAnswer);
- end;
- end;
- WildQuestion := Question;
- Fetch(WildQuestion, '.');
- WildQuestion := '*.' + WildQuestion;
- FServer.InternalSearch(DNSHeader, WildQuestion, QType, LAnswer, True, False, False, True, Question);
- {
- FServer.InternalSearch(DNSHeader, Question, QType, LAnswer, True, True, False);
- }
- if LAnswer <> nil then begin
- AppendBytes(Answer, LAnswer);
- end;
- if Answer <> nil then begin
- Result := cRCodeQueryOK;
- end else begin
- Result := cRCodeQueryNotFound;
- end;
- end else begin
- FServer.InternalSearch(DNSHeader, Question, QType, Answer, True, True, False);
- if (QType in [TypeCode_A, TypeCode_AAAA]) and (Answer = nil) then begin
- FServer.InternalSearch(DNSHeader, Question, TypeCode_CNAME, LAnswer, True, True, False);
- if LAnswer <> nil then begin
- AppendBytes(Answer, LAnswer);
- end;
- end;
- if Answer <> nil then begin
- Result := cRCodeQueryCacheOK;
- end else begin
- //QType := TypeCode_Error;
- FServer.InternalSearch(DNSHeader, Question, QType, Answer, True, True, False);
- if BytesToString(Answer) = 'Error' then begin {do not localize}
- Result := cRCodeQueryCacheFindError;
- end else begin
- FServer.ExternalSearch(DNSResolver, DNSHeader, OriginalQuestion, Answer);
- if Answer <> nil then begin
- Result := cRCodeQueryReturned;
- end else begin
- Result := cRCodeQueryNotImplement;
- end;
- end;
- end;
- end;
- end;
- Class_CHAOS :
- begin
- if TempDomain = 'version.bind.' then begin {do not localize}
- if FServer.offerDNSVersion then begin
- TempAnswer := DomainNameToDNSStr('version.bind.'); {do not localize}
- RRData := NormalStrToDNSStr(FServer.DNSVersion);
- SetLength(LAnswer, Length(TempAnswer) + (SizeOf(UInt16)*3) + SizeOf(UInt32) + Length(RRData));
- CopyTIdBytes(TempAnswer, 0, LAnswer, 0, Length(TempAnswer));
- LIdx := Length(TempAnswer);
- CopyTIdUInt16(GStack.HostToNetwork(UInt16(TypeCode_TXT)), LAnswer, LIdx);
- Inc(LIdx, SizeOf(UInt16));
- CopyTIdUInt16(GStack.HostToNetwork(UInt16(Class_CHAOS)), LAnswer, LIdx);
- Inc(LIdx, SizeOf(UInt16));
- CopyTIdUInt32(GStack.HostToNetwork(UInt32(86400)), LAnswer, LIdx); {do not localize}
- Inc(LIdx, SizeOf(UInt32));
- CopyTIdUInt16(GStack.HostToNetwork(UInt16(Length(RRData))), LAnswer, LIdx);
- Inc(LIdx, SizeOf(UInt16));
- CopyTIdBytes(RRData, 0, LAnswer, LIdx, Length(RRData));
- Answer := LAnswer;
- DNSHeader.ANCount := 1;
- DNSHeader.AA := 1;
- Result := cRCodeQueryOK;
- end else begin
- Result := cRCodeQueryNotImplement;
- end;
- end else begin
- Result := cRCodeQueryNotImplement;
- end;
- end;
- else
- begin
- Result := cRCodeQueryNotImplement;
- end;
- end;
- end;
- procedure TIdDNS_ProcessThread.SendData;
- begin
- FServer.GlobalCS.Enter;
- try
- FMainBinding.SendTo(FMyBinding.PeerIP, FMyBinding.PeerPort, FData, FMyBinding.IPVersion);
- finally
- FServer.GlobalCS.Leave;
- end;
- end;
- procedure TIdDNS_UDPServer.DoAfterCacheSaved(CacheRoot: TIdDNTreeNode);
- begin
- if Assigned(FOnAfterCacheSaved) then begin
- FOnAfterCacheSaved(CacheRoot);
- end;
- end;
- procedure TIdDNS_UDPServer.DoUDPRead(AThread: TIdUDPListenerThread;
- const AData: TIdBytes; ABinding: TIdSocketHandle);
- var
- PThread : TIdDNS_ProcessThread;
- BBinding : TIdSocketHandle;
- Binded : Boolean;
- begin
- inherited DoUDPRead(AThread, AData, ABinding);
- Binded := False;
- BBinding := TIdSocketHandle.Create(nil);
- try
- BBinding.SetPeer(ABinding.PeerIP, ABinding.PeerPort, ABinding.IPVersion);
- BBinding.IP := ABinding.IP;
- repeat
- try
- BBinding.Port := 53;
- BBinding.AllocateSocket(Id_SOCK_DGRAM);
- Binded := True;
- except
- end;
- until Binded;
- PThread := TIdDNS_ProcessThread.Create(True, AData, ABinding, BBinding, Self);
- except
- BBinding.Free;
- raise;
- end;
- PThread.Start;
- end;
- end.
|