| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161 |
- {
- $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 InitComponent; override;
- procedure SetAccessList(const Value: TStrings);
- public
- 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.
- procedure InitComponent; override;
- // 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
- destructor Destroy; override;
- function AXFR(Header : TDNSHeader; Question : string; var Answer : TIdBytes) : string;
- function CompleteQuery(DNSHeader: TDNSHeader; Question: string;
- OriginalQuestion: TIdBytes; var Answer : TIdBytes; QType, QClass : UInt16;
- DNSResolver : TIdDNSResolver) : string; {$IFDEF HAS_DEPRECATED}deprecated;{$ENDIF}
- 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);
- procedure InitComponent; override;
- public
- BackupDNSMap : TIdDNSMap;
- 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 VCL_XE3_OR_ABOVE}
- {$IFNDEF NEXTGEN}
- System.Contnrs,
- {$ENDIF}
- System.SyncObjs,
- System.Types,
- {$ENDIF}
- IdException,
- {$IFDEF DOTNET}
- {$IFDEF USE_INLINE}
- System.Threading,
- System.IO,
- {$ENDIF}
- {$ENDIF}
- {$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
- FreeAndNil(Result);
- 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
- FreeAndNil(SubTree);
- 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
- FreeAndNil(Result);
- 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
- FreeAndNil(Result);
- 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
- FreeAndNil(FRRs);
- FreeAndNil(FChildIndex);
- 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
- FreeAndNil(Result);
- 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
- FreeAndNil(DNSs);
- 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 }
- {$I IdDeprecatedImplBugOff.inc}
- function TIdDNS_UDPServer.CompleteQuery(DNSHeader : TDNSHeader; Question: string;
- OriginalQuestion: TIdBytes; var Answer: TIdBytes; QType, QClass: UInt16;
- DNSResolver : TIdDNSResolver): string;
- {$I IdDeprecatedImplBugOn.inc}
- var
- IsMyDomains : Boolean;
- LAnswer: TIdBytes;
- WildQuestion, TempDomain : string;
- begin
- // QClass = 1 => IN, we support only "IN" class now.
- // QClass = 2 => CS,
- // QClass = 3 => CH,
- // QClass = 4 => HS.
- if QClass <> 1 then begin
- Result := cRCodeQueryNotImplement;
- Exit;
- end;
- TempDomain := LowerCase(Question);
- IsMyDomains := (Handed_DomainList.IndexOf(TempDomain) > -1);
- if not IsMyDomains then begin
- Fetch(TempDomain, '.');
- IsMyDomains := (Handed_DomainList.IndexOf(TempDomain) > -1);
- end;
- if IsMyDomains then begin
- InternalSearch(DNSHeader, Question, QType, LAnswer, True, False, False);
- Answer := LAnswer;
- if (QType in [TypeCode_A, TypeCode_AAAA]) and (Length(Answer) = 0) then
- begin
- InternalSearch(DNSHeader, Question, TypeCode_CNAME, LAnswer, True, False, True);
- AppendBytes(Answer, LAnswer);
- end;
- WildQuestion := Question;
- Fetch(WildQuestion, '.');
- WildQuestion := '*.' + WildQuestion;
- InternalSearch(DNSHeader, WildQuestion, QType, LAnswer, True, False, False, True, Question);
- AppendBytes(Answer, LAnswer);
- if Length(Answer) > 0 then begin
- Result := cRCodeQueryOK;
- end else begin
- Result := cRCodeQueryNotFound;
- end;
- end else
- begin
- InternalSearch(DNSHeader, Question, QType, Answer, True, True, False);
- if (QType in [TypeCode_A, TypeCode_AAAA]) and (Length(Answer) = 0) then
- begin
- InternalSearch(DNSHeader, Question, TypeCode_CNAME, LAnswer, True, True, False);
- AppendBytes(Answer, LAnswer);
- end;
- if Length(Answer) > 0 then begin
- Result := cRCodeQueryCacheOK;
- Exit;
- end;
- InternalSearch(DNSHeader, Question, TypeCode_Error, Answer, True, True, False);
- if BytesToString(Answer) = 'Error' then begin {do not localize}
- Result := cRCodeQueryCacheFindError;
- Exit;
- end;
- ExternalSearch(DNSResolver, DNSHeader, OriginalQuestion, Answer);
- if Length(Answer) > 0 then begin
- Result := cRCodeQueryReturned;
- end else begin
- Result := cRCodeQueryNotImplement;
- end;
- end
- end;
- procedure TIdDNS_UDPServer.InitComponent;
- begin
- inherited InitComponent;
- 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
- FreeAndNil(FCached_Tree);
- FreeAndNil(FHanded_Tree);
- FreeAndNil(FRootDNS_NET);
- FreeAndNil(FHanded_DomainList);
- FreeAndNil(FZoneMasterFiles);
- FreeAndNil(FCS);
- FreeAndNil(FGlobalCS);
- 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(Self);
- 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 (Length(Answer) > 0);
- finally
- if ADNSResolver = nil then begin
- FreeAndNil(MyDNSResolver);
- 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
- FreeAndNil(FileStrings);
- 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
- FreeAndNil(namepart);
- 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
- FreeAndNil(TagList);
- 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
- FreeAndNil(EachLinePart);
- 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
- {$IFDEF STRING_IS_UNICODE}
- LastDenotedDomain := String(LLRR_SOA.MName); // explicit convert to Unicode
- {$ELSE}
- LastDenotedDomain := LLRR_SOA.MName;
- {$ENDIF}
- 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
- {$IFDEF STRING_IS_UNICODE}
- RName := String(LLRR_SOA.RName); // explicit convert to Unicode
- {$ELSE}
- RName := LLRR_SOA.RName;
- {$ENDIF}
- 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
- FreeAndNil(Checks);
- 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
- FreeAndNil(DenotedDomain);
- end;
- finally
- FreeAndNil(EachLinePart);
- 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
- FreeAndNil(TempResolver);
- 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
- FreeAndNil(NameLabels);
- 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
- FreeAndNil(NameNode);
- 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
- FreeAndNil(NameNode);
- 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
- QName := Copy(QName, 1, 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 (Length(LocalAnswer) > 0) 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 Length(LocalAnswer) > 0 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 Length(Answer) > 0 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 Length(LocalAnswer) = 0 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 Length(LocalAnswer) = 0 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(Self);
- 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 (Length(AResult) > 0);
- AppendBytes(LocalAnswer, AResult, 12);
- finally
- FreeAndNil(LDNSResolver);
- end;
- end;
- if Length(LocalAnswer) > 0 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 Length(Answer) = 0 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 Length(LocalAnswer) > 0 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 Length(LocalAnswer) = 0 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 Length(LocalAnswer) = 0 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 Length(LocalAnswer) = 0 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 Length(LocalAnswer) > 0 then begin
- AppendBytes(TempAnswer, LocalAnswer);
- LocalAnswer := TempAnswer;
- end;
- Answer := LocalAnswer;
- end;
- end;
- end;
- end;
- finally
- FreeAndNil(MoreAddrSearch);
- end;
- end;
- { TIdDNSServer }
- procedure TIdDNSServer.CheckIfExpire(Sender: TObject);
- begin
- end;
- procedure TIdDNSServer.InitComponent;
- begin
- inherited InitComponent;
- 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
- FreeAndNil(FAccessList);
- FreeAndNil(FUDPTunnel);
- FreeAndNil(FTCPTunnel);
- FreeAndNil(FBindings);
- FreeAndNil(BackupDNSMap);
- inherited Destroy;
- 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
- FreeAndNil(Resolver);
- end;
- end;
- { TIdDNS_TCPServer }
- procedure TIdDNS_TCPServer.InitComponent;
- begin
- inherited InitComponent;
- FAccessList := TStringList.Create;
- end;
- destructor TIdDNS_TCPServer.Destroy;
- begin
- FreeAndNil(FAccessList);
- 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
- FreeAndNil(TestHeader);
- end;
- end;
- procedure GenerateAXFRRefuseData;
- begin
- TestHeader := TDNSHeader.Create;
- try
- TestHeader.ParseQuery(Data);
- TestHeader.Qr := iQr_Answer;
- TestHeader.RCode := iRCodeRefused;
- Answer := TestHeader.GenerateBinaryHeader;
- finally
- FreeAndNil(TestHeader);
- 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
- //Self.CheckScheduler.TerminateAndWaitFor;
- CheckScheduler.Terminate;
- FreeAndNil(CheckScheduler);
- 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
- FreeAndNil(Resolver);
- 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];
- FreeAndNil(DNSMP);
- Delete(I);
- 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;
- FMyBinding.CloseSocket;
- FreeAndNil(FMyBinding);
- FreeAndNil(FMyData);
- 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
- FreeAndNil(DNSHeader_Processing);
- 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 (Length(Answer) > 0);
- finally
- if ADNSResolver = nil then begin
- FreeAndNil(MyDNSResolver);
- 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
- FreeAndNil(TempResolver);
- 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
- FreeAndNil(NameLabels);
- 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 (Length(Answer) = 0) then begin
- FServer.InternalSearch(DNSHeader, Question, TypeCode_CNAME, LAnswer, True, False, True);
- if Length(LAnswer) > 0 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 Length(LAnswer) > 0 then begin
- AppendBytes(Answer, LAnswer);
- end;
- if Length(Answer) > 0 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 (Length(Answer) = 0) then begin
- FServer.InternalSearch(DNSHeader, Question, TypeCode_CNAME, LAnswer, True, True, False);
- if Length(LAnswer) > 0 then begin
- AppendBytes(Answer, LAnswer);
- end;
- end;
- if Length(Answer) > 0 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 Length(Answer) > 0 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
- FreeAndNil(BBinding);
- raise;
- end;
- PThread.Start;
- end;
- end.
|