gaddrinf.c 116 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. gaddrinf.c
  9. Abstract:
  10. This module implements support for the getaddrinfo function.
  11. Author:
  12. Evan Green 5-Dec-2013
  13. Environment:
  14. User Mode C Library
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "libcp.h"
  20. #include <minoca/devinfo/net.h>
  21. #include <arpa/inet.h>
  22. #include <assert.h>
  23. #include <errno.h>
  24. #include <fcntl.h>
  25. #include <limits.h>
  26. #include <netdb.h>
  27. #include <poll.h>
  28. #include <stdlib.h>
  29. #include "net.h"
  30. //
  31. // ---------------------------------------------------------------- Definitions
  32. //
  33. #define DNS_CLASS_INTERNET 1
  34. #define DNS_RECORD_TYPE_A 1
  35. #define DNS_RECORD_TYPE_NS 2
  36. #define DNS_RECORD_TYPE_CNAME 5
  37. #define DNS_RECORD_TYPE_SOA 6
  38. #define DNS_RECORD_TYPE_PTR 12
  39. #define DNS_RECORD_TYPE_MX 15
  40. #define DNS_RECORD_TYPE_TXT 16
  41. #define DNS_RECORD_TYPE_AAAA 28
  42. #define DNS_MAX_QUERY_COUNT 50
  43. //
  44. // Define the safe guess size of a DNS response.
  45. //
  46. #define DNS_RESPONSE_ALLOCATION_SIZE 4096
  47. //
  48. // Define the amount of time to wait for a response before giving up, in
  49. // milliseconds.
  50. //
  51. #define DNS_RESPONSE_TIMEOUT 30000
  52. //
  53. // Define the maximum size of the reverse DNS string.
  54. //
  55. #define DNS_IP4_REVERSE_TRANSLATION_NAME_SIZE \
  56. sizeof("255.255.255.255.in-addr.arpa")
  57. #define DNS_IP6_REVERSE_TRANSLATION_NAME_SIZE \
  58. sizeof("F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F." \
  59. "F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.ip6.arpa")
  60. //
  61. // Define the IPv4 and IPv6 reverse DNS lookup formats.
  62. //
  63. #define DNS_IP4_REVERSE_TRANSLATION_FORMAT "%d.%d.%d.%d.in-addr.arpa"
  64. #define DNS_IP6_REVERSE_TRANSLATION_FORMAT \
  65. "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." \
  66. "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa"
  67. //
  68. // Define the suffix for the IPv6 reverse DNS lookup string.
  69. //
  70. #define DNS_IP6_REVERSE_TRANSLATION_SUFFIX "ip6.arpa"
  71. #define DNS_IP6_REVERSE_TRANSLATION_SUFFIX_SIZE \
  72. sizeof(DNS_IP6_REVERSE_TRANSLATION_SUFFIX)
  73. //
  74. // Define the strings for the default and DGRAM protocols used by getnameinfo.
  75. //
  76. #define NAME_INFORMATION_DEFAULT_PROTOCOL_NAME "TCP"
  77. #define NAME_INFORMATION_DGRAM_PROTOCOL_NAME "UDP"
  78. //
  79. // ------------------------------------------------------ Data Type Definitions
  80. //
  81. /*++
  82. Structure Description:
  83. This structure defines the internal format (just for software, not anything
  84. out on the network) of a DNS response.
  85. Members:
  86. ListEntry - Stores pointers to the next and previous results.
  87. Name - Stores a pointer to the heap allocated name of the resource.
  88. Type - Stores the type of the resource. See DNS_RECORD_TYPE_* definitions.
  89. Class - Stores the class of the resource. See DNS_CLASS_* definitions.
  90. ExpirationTime - Stores the time at which this record expires.
  91. Value - Stores a pointer to the heap allocated value string for record
  92. types whose values are also names.
  93. Address - Stores the network address value for record types whose values
  94. are addresses.
  95. --*/
  96. typedef struct _DNS_RESULT {
  97. LIST_ENTRY ListEntry;
  98. PSTR Name;
  99. USHORT Type;
  100. USHORT Class;
  101. time_t ExpirationTime;
  102. PSTR Value;
  103. struct sockaddr Address;
  104. } DNS_RESULT, *PDNS_RESULT;
  105. //
  106. // ----------------------------------------------- Internal Function Prototypes
  107. //
  108. INT
  109. ClpPerformDnsTranslation (
  110. PSTR Name,
  111. UCHAR RecordType,
  112. NET_DOMAIN_TYPE Domain,
  113. PLIST_ENTRY ListHead,
  114. ULONG RecursionDepth
  115. );
  116. INT
  117. ClpPerformDnsReverseTranslation (
  118. const struct sockaddr *SocketAddress,
  119. socklen_t SocketAddressLength,
  120. PLIST_ENTRY ListHead
  121. );
  122. INT
  123. ClpPerformDnsQuery (
  124. PSTR Name,
  125. CHAR RecordType,
  126. struct sockaddr *NameServer,
  127. socklen_t NameServerSize,
  128. PLIST_ENTRY ListHead
  129. );
  130. INT
  131. ClpCreateDnsQuery (
  132. PSTR Name,
  133. UCHAR ResponseType,
  134. PDNS_HEADER *NewRequest,
  135. PULONG RequestSize
  136. );
  137. INT
  138. ClpExecuteDnsQuery (
  139. struct sockaddr *NameServer,
  140. socklen_t NameServerSize,
  141. PDNS_HEADER Request,
  142. ULONG RequestSize,
  143. PDNS_HEADER *Response,
  144. PULONG ResponseSize
  145. );
  146. INT
  147. ClpParseDnsResponse (
  148. PDNS_HEADER Response,
  149. ULONG ResponseSize,
  150. PLIST_ENTRY ListHead
  151. );
  152. INT
  153. ClpParseDnsResponseElement (
  154. PDNS_HEADER Response,
  155. ULONG ResponseSize,
  156. PUCHAR *ResponseEntry,
  157. PLIST_ENTRY ListHead
  158. );
  159. INT
  160. ClpDecompressDnsName (
  161. PDNS_HEADER Response,
  162. ULONG ResponseSize,
  163. PUCHAR *DnsName,
  164. PSTR *OutputName
  165. );
  166. INT
  167. ClpScanDnsName (
  168. PUCHAR Response,
  169. ULONG ResponseSize,
  170. PUCHAR Name,
  171. PSTR OutputName,
  172. PULONG OutputNameSize
  173. );
  174. VOID
  175. ClpDestroyDnsResultList (
  176. PLIST_ENTRY ListHead
  177. );
  178. VOID
  179. ClpDestroyDnsResult (
  180. PDNS_RESULT Result
  181. );
  182. VOID
  183. ClpDebugPrintDnsResult (
  184. PDNS_RESULT Result
  185. );
  186. INT
  187. ClpGetNameServerAddress (
  188. PDNS_RESULT NameServer,
  189. UCHAR RecordType,
  190. PLIST_ENTRY TranslationList,
  191. struct sockaddr *NameServerAddress,
  192. ULONG RecursionDepth
  193. );
  194. INT
  195. ClpFindNameServerAddress (
  196. PDNS_RESULT NameServer,
  197. UCHAR RecordType,
  198. PLIST_ENTRY TranslationList,
  199. struct sockaddr *NameServerAddress
  200. );
  201. INT
  202. ClpSearchDnsResultList (
  203. PSTR Name,
  204. UCHAR RecordType,
  205. time_t CurrentTime,
  206. PLIST_ENTRY ListHead,
  207. PLIST_ENTRY DestinationListHead
  208. );
  209. INT
  210. ClpConvertDnsResultListToAddressInformation (
  211. PLIST_ENTRY ListHead,
  212. const struct addrinfo *Hints,
  213. ULONG Port,
  214. BOOL MapV4Addresses,
  215. struct addrinfo **AddressInformation
  216. );
  217. INT
  218. ClpConvertDnsResultToAddressInformation (
  219. PDNS_RESULT Result,
  220. BOOL CopyCanonicalName,
  221. ULONG Port,
  222. struct addrinfo **AddressInformation
  223. );
  224. INT
  225. ClpGetAddressInformationPort (
  226. PSTR ServiceName,
  227. const struct addrinfo *Hints,
  228. PULONG Port
  229. );
  230. VOID
  231. ClpDebugPrintAddressInformation (
  232. struct addrinfo *AddressInformation
  233. );
  234. VOID
  235. ClpFillInLoopbackAddress (
  236. int AddressFamily,
  237. struct sockaddr *Address
  238. );
  239. INT
  240. ClpGetDnsServers (
  241. NET_DOMAIN_TYPE Domain,
  242. struct sockaddr *PrimaryServer,
  243. PLIST_ENTRY AlternateList
  244. );
  245. INT
  246. ClpGetNetworkStatus (
  247. PBOOL Ip4Configured,
  248. PBOOL Ip6Configured
  249. );
  250. INT
  251. ClpGetLocalAddressInformation (
  252. int AddressFamily,
  253. PLIST_ENTRY ListHead
  254. );
  255. INT
  256. ClpIsLocalAddress (
  257. const struct sockaddr *SocketAddress,
  258. socklen_t SocketAddressLength,
  259. PBOOL LocalAddress,
  260. PBOOL UnspecifiedAddress
  261. );
  262. BOOL
  263. ClpIsNameSubdomain (
  264. PCSTR Query,
  265. PCSTR Domain
  266. );
  267. //
  268. // -------------------------------------------------------------------- Globals
  269. //
  270. //
  271. // Set this boolean to debug DNS queries.
  272. //
  273. BOOL ClDebugDns = FALSE;
  274. //
  275. // Define the address information error strings.
  276. //
  277. PSTR ClGetAddressInformationErrorStrings[] = {
  278. "No error",
  279. "Address family not supported for hostname",
  280. "Try again",
  281. "Invalid flags",
  282. "Failed",
  283. "Invalid address family",
  284. "Out of memory",
  285. "No address associated with hostname",
  286. "Name not found",
  287. "Service not supported",
  288. "Invalid socket type",
  289. "System error",
  290. "Buffer overflow"
  291. };
  292. //
  293. // Define the network device information UUID.
  294. //
  295. UUID ClNetworkDeviceInformationUuid = NETWORK_DEVICE_INFORMATION_UUID;
  296. //
  297. // ------------------------------------------------------------------ Functions
  298. //
  299. LIBC_API
  300. void
  301. freeaddrinfo (
  302. struct addrinfo *AddressInformation
  303. )
  304. /*++
  305. Routine Description:
  306. This routine frees the address structure returned by the getaddrinfo, along
  307. with any additional storage associated with those structures. If the
  308. ai_next field of the structure is not null, the entire list of structures
  309. shall be freed. This routine supports the freeing of arbitrary sublists of
  310. an addrinfo structure originally returned by getaddrinfo. This routine is
  311. thread safe.
  312. Arguments:
  313. AddressInformation - Supplies a pointer to the address information to free.
  314. Return Value:
  315. None.
  316. --*/
  317. {
  318. struct addrinfo *Next;
  319. while (AddressInformation != NULL) {
  320. Next = AddressInformation->ai_next;
  321. if (AddressInformation->ai_canonname != NULL) {
  322. free(AddressInformation->ai_canonname);
  323. }
  324. AddressInformation->ai_next = NULL;
  325. free(AddressInformation);
  326. AddressInformation = Next;
  327. }
  328. return;
  329. }
  330. LIBC_API
  331. int
  332. getaddrinfo (
  333. const char *NodeName,
  334. const char *ServiceName,
  335. const struct addrinfo *Hints,
  336. struct addrinfo **Result
  337. )
  338. /*++
  339. Routine Description:
  340. This routine trnalsates the name of a service location (a host name for
  341. example) and/or a service name and returns a set of socket addresses and
  342. associated information to be used in creating a socket with which to
  343. address the given service. In many cases this is backed by DNS. This
  344. routine is thread safe.
  345. Arguments:
  346. NodeName - Supplies an optional pointer to a null-terminated string
  347. containing the node (host) name to get address information for. If no
  348. service name is supplied, this routine returns the network-level
  349. addresses for the specified node name. At least one (or both) of the
  350. node name and service name parameter must be non-null (they cannot both
  351. be null).
  352. ServiceName - Supplies an optional pointer to a null-terminated string
  353. containing the service name to get address information for. This can
  354. be a descriptive name string or a decimal port number string.
  355. Hints - Supplies an optional pointer to an address structure that may
  356. limit the returned information to a specific socket type, address
  357. family, and/or protocol. In this hints structure every member other
  358. than ai_flags, ai_faimly, ai_socktype, and ai_protocol shall be set to
  359. zero or NULL. A value of AF_UNSPEC for ai_family means that the caller
  360. accepts any address family. A value of zero for ai_socktype means that
  361. the caller accepts any socket type. A value of zero for ai_protocol
  362. means that the caller accepts any protocol. If this parameter is not
  363. supplied, it's the same as if a parameter were passed with zero for all
  364. these values. The ai_flags member can be set to any combination of the
  365. following flags:
  366. AI_PASSIVE - Specifies that the returned address information shall be
  367. suitable for use in binding a socket for incoming connections. If the
  368. node name argument is NULL, then the IP address portion of the returned
  369. structure will be INADDR_ANY or IN6ADDR_ANY_INIT. Otherwise, the
  370. returned information shall be suitable for a call to connect. If the
  371. node name parameter is NULL in this case, then the address returned
  372. shall be set to the loopback address. This flag is ignored if the node
  373. name is not NULL.
  374. AI_CANONNAME - Specifies that this routine should try to determine the
  375. canonical name of the given node name (for example, if the given node
  376. name is an alias or shorthand notation for a complete name).
  377. AI_NUMERICHOST - Specifies that a non-null node name parameter is a
  378. numeric host address string. Otherwise, an EAI_NONAME error shall be
  379. returned. This prevents any sort of name resolution service (like DNS)
  380. from being invoked.
  381. AI_NUMERICSERV - Specifies that a non-null service name supplied is a
  382. numeric port string. Otherwise, an EAI_NONAME error shall be returned.
  383. This flag prevents any sort of name resolution service (like NIS+) from
  384. being invoked.
  385. AI_V4MAPPED - Specifies that this routine should returne IPv4-mapped
  386. IPv6 address on finding no matching IPv6 addresses. This is ignored
  387. unless the ai_family parameter is set to AF_INET6. If the AI_ALL flag
  388. is used as well, then this routine returns all IPv6 and IPv4 addresses.
  389. The AI_ALL flag without the AI_V4MAPPED flag is ignored.
  390. AI_ADDRCONFIG - Specifies that IPv4 addresses should be returned only
  391. if an IPv4 address is configured on the local system, and IPv6
  392. addresses shall be returned only if an IPv6 address is configured on
  393. the local system.
  394. Result - Supplies a pointer where a linked list of address results will be
  395. returned on success.
  396. Return Value:
  397. 0 on success.
  398. Non-zero on failure, and errno will contain more information. Common values
  399. of errno include:
  400. EAI_AGAIN if the name could not be resolved at this time. Future attempts
  401. may succeed.
  402. EAI_BADFLAGS if the flags parameter had an invalid value.
  403. EAI_FAIL if a non-recoverable error occurred when attempting to resolve the
  404. name.
  405. EAI_FAMILY if the address family was not recognized.
  406. EAI_MEMORY if there was a memory allocation failure.
  407. EAI_NONAME if the name does not resolve for the supplied parameters, or
  408. neither the node name or service name were supplied.
  409. EAI_SERVICE if the service passed was not recognized for the given socket
  410. type.
  411. EAI_SOCKTYPE if the given socket type was not recognized.
  412. EAI_SYSTEM if a system error occurred.
  413. EAI_OVERFLOW if an argument buffer overflowed.
  414. --*/
  415. {
  416. PLIST_ENTRY CurrentEntry;
  417. PDNS_RESULT DnsResult;
  418. INT Family;
  419. char HostName[HOST_NAME_MAX];
  420. struct addrinfo *Information;
  421. struct sockaddr_in *Ip4Address;
  422. BOOL Ip4Configured;
  423. struct sockaddr_in6 *Ip6Address;
  424. BOOL Ip6Configured;
  425. DNS_RESULT LocalResult[2];
  426. BOOL MapV4Addresses;
  427. ULONG Port;
  428. LIST_ENTRY ResultList;
  429. int Status;
  430. Family = 0;
  431. memset(&LocalResult, 0, sizeof(DNS_RESULT) * 2);
  432. Information = NULL;
  433. LocalResult[0].Class = DNS_CLASS_INTERNET;
  434. LocalResult[1].Class = DNS_CLASS_INTERNET;
  435. MapV4Addresses = FALSE;
  436. Port = 0;
  437. INITIALIZE_LIST_HEAD(&ResultList);
  438. //
  439. // One or both of the node name and service name must be supplied.
  440. //
  441. if ((NodeName == NULL) && (ServiceName == NULL)) {
  442. return EAI_NONAME;
  443. }
  444. //
  445. // Validate hints.
  446. //
  447. if (Hints != NULL) {
  448. if ((Hints->ai_addrlen != 0) ||
  449. (Hints->ai_canonname != NULL) ||
  450. (Hints->ai_addr != NULL) ||
  451. (Hints->ai_next != NULL)) {
  452. Status = EAI_BADFLAGS;
  453. goto getaddrinfoEnd;
  454. }
  455. if ((Hints->ai_family != AF_UNSPEC) &&
  456. (Hints->ai_family != AF_INET) &&
  457. (Hints->ai_family != AF_INET6)) {
  458. Status = EAI_FAMILY;
  459. goto getaddrinfoEnd;
  460. }
  461. if ((Hints->ai_socktype != 0) &&
  462. (Hints->ai_socktype != SOCK_STREAM) &&
  463. (Hints->ai_socktype != SOCK_DGRAM) &&
  464. (Hints->ai_socktype != SOCK_RAW)) {
  465. Status = EAI_SOCKTYPE;
  466. goto getaddrinfoEnd;
  467. }
  468. Family = Hints->ai_family;
  469. //
  470. // If the address configuration flag is supplied, limit the family to
  471. // what is configured on the local system.
  472. //
  473. if ((Hints->ai_flags & AI_ADDRCONFIG) != 0) {
  474. Status = ClpGetNetworkStatus(&Ip4Configured, &Ip6Configured);
  475. if (Status != 0) {
  476. goto getaddrinfoEnd;
  477. }
  478. if (Family == AF_UNSPEC) {
  479. if ((Ip4Configured == FALSE) && (Ip6Configured == FALSE)) {
  480. Status = EAI_AGAIN;
  481. goto getaddrinfoEnd;
  482. } else if (Ip4Configured == FALSE) {
  483. Family = AF_INET6;
  484. } else if (Ip6Configured == FALSE) {
  485. Family = AF_INET;
  486. }
  487. } else if (((Family == AF_INET) && (Ip4Configured == FALSE)) ||
  488. ((Family == AF_INET6) && (Ip6Configured == FALSE))) {
  489. Status = EAI_NONAME;
  490. goto getaddrinfoEnd;
  491. }
  492. }
  493. }
  494. //
  495. // Convert the service name into a port number.
  496. //
  497. Status = ClpGetAddressInformationPort((PSTR)ServiceName, Hints, &Port);
  498. if (Status != 0) {
  499. goto getaddrinfoEnd;
  500. }
  501. //
  502. // If there is no node name, then honor the passive flag.
  503. //
  504. if (NodeName == NULL) {
  505. //
  506. // If passive is selected, stick the "any address" into the address
  507. // (which is just the zeroed address it already is).
  508. //
  509. if ((Hints != NULL) && ((Hints->ai_flags & AI_PASSIVE) != 0)) {
  510. if (Family != 0) {
  511. LocalResult[0].Address.sa_family = Family;
  512. INSERT_BEFORE(&(LocalResult[0].ListEntry), &ResultList);
  513. } else {
  514. LocalResult[0].Address.sa_family = AF_INET;
  515. INSERT_BEFORE(&(LocalResult[0].ListEntry), &ResultList);
  516. LocalResult[1].Address.sa_family = AF_INET6;
  517. INSERT_BEFORE(&(LocalResult[1].ListEntry), &ResultList);
  518. }
  519. //
  520. // Otherwise use the local loopback address.
  521. //
  522. } else {
  523. if (Family != 0) {
  524. ClpFillInLoopbackAddress(Family, &(LocalResult[0].Address));
  525. INSERT_BEFORE(&(LocalResult[0].ListEntry), &ResultList);
  526. } else {
  527. ClpFillInLoopbackAddress(AF_INET, &(LocalResult[0].Address));
  528. INSERT_BEFORE(&(LocalResult[0].ListEntry), &ResultList);
  529. ClpFillInLoopbackAddress(AF_INET6, &(LocalResult[1].Address));
  530. INSERT_BEFORE(&(LocalResult[1].ListEntry), &ResultList);
  531. }
  532. }
  533. //
  534. // Go do the hard work and translate the host name.
  535. //
  536. } else {
  537. //
  538. // First try to translate the host name to a number.
  539. //
  540. Status = 0;
  541. LocalResult[0].Name = (PSTR)NodeName;
  542. if ((Family == AF_UNSPEC) || (Family == AF_INET6)) {
  543. LocalResult[0].Type = DNS_RECORD_TYPE_AAAA;
  544. LocalResult[0].Address.sa_family = AF_INET6;
  545. Ip6Address = (struct sockaddr_in6 *)&(LocalResult[0].Address);
  546. Status = inet_pton(AF_INET6, NodeName, &(Ip6Address->sin6_addr));
  547. }
  548. if ((Status == 0) && ((Family == AF_UNSPEC) || (Family == AF_INET))) {
  549. LocalResult[0].Type = DNS_RECORD_TYPE_A;
  550. LocalResult[0].Address.sa_family = AF_INET;
  551. Ip4Address = (struct sockaddr_in *)&(LocalResult[0].Address);
  552. Status = inet_pton(AF_INET, NodeName, &(Ip4Address->sin_addr));
  553. }
  554. //
  555. // If the numeric translation worked, convert and finish.
  556. //
  557. if (Status == 1) {
  558. INSERT_BEFORE(&(LocalResult[0].ListEntry), &ResultList);
  559. Status = ClpConvertDnsResultListToAddressInformation(&ResultList,
  560. Hints,
  561. Port,
  562. MapV4Addresses,
  563. &Information);
  564. goto getaddrinfoEnd;
  565. }
  566. //
  567. // If the caller doesn't want name resolution, then this is where they
  568. // get off the bus.
  569. //
  570. if ((Hints != NULL) && ((Hints->ai_flags & AI_NUMERICHOST) != 0)) {
  571. Status = EAI_FAIL;
  572. goto getaddrinfoEnd;
  573. }
  574. //
  575. // Before reaching out with a DNS query, take a look at the local host
  576. // name.
  577. //
  578. Status = gethostname(HostName, sizeof(HostName));
  579. if (Status == 0) {
  580. if (strcmp(NodeName, HostName) == 0) {
  581. //
  582. // Get the local IP addresses based on the family type.
  583. //
  584. Status = ClpGetLocalAddressInformation(Family, &ResultList);
  585. if (Status != 0) {
  586. goto getaddrinfoEnd;
  587. }
  588. Status = ClpConvertDnsResultListToAddressInformation(
  589. &ResultList,
  590. Hints,
  591. Port,
  592. MapV4Addresses,
  593. &Information);
  594. goto getaddrinfoEnd;
  595. }
  596. }
  597. //
  598. // TODO: Remove this when IPv6 is supported. Allowing the IPv6
  599. // translation is problematic because the name servers returned may
  600. // also be IPv6 addresses, causing the translation to fail rather than
  601. // fall back to IPv4.
  602. //
  603. if (Family == AF_UNSPEC) {
  604. Family = AF_INET;
  605. }
  606. //
  607. // This is going to take the big leagues, translating a real address.
  608. // If IPv6 or any family is requested, get IPv6 translations.
  609. //
  610. if ((Family == AF_UNSPEC) || (Family == AF_INET6)) {
  611. Status = ClpPerformDnsTranslation((char *)NodeName,
  612. DNS_RECORD_TYPE_AAAA,
  613. NetDomainIp6,
  614. &ResultList,
  615. 0);
  616. if (Status != 0) {
  617. goto getaddrinfoEnd;
  618. }
  619. }
  620. //
  621. // If IPv4 or any family is requested, get IPv4 translations.
  622. // Additionally, if the family is IPv6, the v4-mapped flag is set, and
  623. // there were no IPv6 translations (or the 'all' flag is set), also
  624. // get IPv4 translations.
  625. //
  626. if ((Family == AF_UNSPEC) || (Family == AF_INET) ||
  627. ((Family == AF_INET6) && (Hints != NULL) &&
  628. ((Hints->ai_flags & AI_V4MAPPED) != 0) &&
  629. (((Hints->ai_flags & AI_ALL) != 0) ||
  630. (LIST_EMPTY(&ResultList) != 0)))) {
  631. if (Family == AF_INET6) {
  632. MapV4Addresses = TRUE;
  633. }
  634. Status = ClpPerformDnsTranslation((char *)NodeName,
  635. DNS_RECORD_TYPE_A,
  636. NetDomainIp4,
  637. &ResultList,
  638. 0);
  639. if (Status != 0) {
  640. goto getaddrinfoEnd;
  641. }
  642. }
  643. //
  644. // For a good time, print the DNS result list.
  645. //
  646. if (ClDebugDns != FALSE) {
  647. if (Status != 0) {
  648. fprintf(stderr,
  649. "DNS: Translation failed: (%d) %s.\n",
  650. Status,
  651. gai_strerror(Status));
  652. } else if (LIST_EMPTY(&ResultList) != FALSE) {
  653. fprintf(stderr, "DNS: Found no translation.\n");
  654. } else {
  655. fprintf(stderr, "DNS: Final Results:\n");
  656. CurrentEntry = ResultList.Next;
  657. while (CurrentEntry != &ResultList) {
  658. DnsResult = LIST_VALUE(CurrentEntry, DNS_RESULT, ListEntry);
  659. ClpDebugPrintDnsResult(DnsResult);
  660. CurrentEntry = CurrentEntry->Next;
  661. }
  662. }
  663. }
  664. }
  665. Status = ClpConvertDnsResultListToAddressInformation(&ResultList,
  666. Hints,
  667. Port,
  668. MapV4Addresses,
  669. &Information);
  670. if (Status != 0) {
  671. goto getaddrinfoEnd;
  672. }
  673. Status = 0;
  674. getaddrinfoEnd:
  675. if (ResultList.Next != &(LocalResult[0].ListEntry)) {
  676. assert(ResultList.Next != &(LocalResult[1].ListEntry));
  677. ClpDestroyDnsResultList(&ResultList);
  678. }
  679. if (Status != 0) {
  680. if (Information != NULL) {
  681. freeaddrinfo(Information);
  682. Information = NULL;
  683. }
  684. }
  685. if (ClDebugDns != FALSE) {
  686. fprintf(stderr,
  687. "getaddrinfo: Name %s Service %s: %s.\n",
  688. NodeName,
  689. ServiceName,
  690. gai_strerror(Status));
  691. ClpDebugPrintAddressInformation(Information);
  692. }
  693. //
  694. // If a success status is being returned, the result better be non-null.
  695. //
  696. assert((Status != 0) || (Information != NULL));
  697. *Result = Information;
  698. return Status;
  699. }
  700. LIBC_API
  701. int
  702. getnameinfo (
  703. const struct sockaddr *SocketAddress,
  704. socklen_t SocketAddressLength,
  705. char *Node,
  706. socklen_t NodeLength,
  707. char *Service,
  708. socklen_t ServiceLength,
  709. int Flags
  710. )
  711. /*++
  712. Routine Description:
  713. This routine translates the given socket address to a node name and service
  714. location, defined as in getaddrinfo.
  715. Arguments:
  716. SocketAddress - Supplies a pointer to the socket address to be translated.
  717. If this is an IPv4-mapped IPv6 address or an IPv4-compatible IPv6
  718. address then the implementation shall extract the IPv4 address and look
  719. up the node name for that IPv4 address. The IPv6 unspecified address
  720. ("::") and the IPv6 loopback address ("::1") are not IPv4-compatible
  721. addresses.
  722. SocketAddressLength - Supplies the size of the socket address data.
  723. Node - Supplies an optional pointer to a buffer where the node name string
  724. will be returned on success. If the node name cannot be determined, the
  725. numeric form of the address will be returned.
  726. NodeLength - Supplies the size of the node buffer in bytes.
  727. Service - Supplies an optional pointer to a buffer where the service name
  728. string will be returned. If the service name cannot be returned, the
  729. numeric form of the service address (port number) shall be returned
  730. instead of its name.
  731. ServiceLength - Supplies the length of the service buffer in bytes.
  732. Flags - Supplies a bitfield of flags that governs the behavior of the
  733. function. See NI_* definitions.
  734. Return Value:
  735. 0 on success.
  736. Returns an EAI_* error code on failure.
  737. --*/
  738. {
  739. void *Address;
  740. char AddressString[INET6_ADDRSTRLEN];
  741. PLIST_ENTRY CurrentEntry;
  742. PDNS_RESULT DnsResult;
  743. char *DomainName;
  744. struct sockaddr_in *Ip4Address;
  745. struct sockaddr_in Ip4MappedAddress;
  746. struct sockaddr_in6 *Ip6Address;
  747. BOOL LocalAddress;
  748. const struct sockaddr *LookupAddress;
  749. socklen_t LookupAddressLength;
  750. in_port_t Port;
  751. const char *Protocol;
  752. LIST_ENTRY ResultList;
  753. struct servent *ServiceEntry;
  754. int Status;
  755. BOOL UnspecifiedAddress;
  756. if (SocketAddressLength < sizeof(struct sockaddr_in)) {
  757. Status = EAI_FAIL;
  758. goto getnameinfoEnd;
  759. }
  760. LookupAddress = SocketAddress;
  761. LookupAddressLength = SocketAddressLength;
  762. //
  763. // Collect the port information and determine whether or not the address
  764. // is one of the loopback address or unspecified address.
  765. //
  766. switch (SocketAddress->sa_family) {
  767. case AF_INET:
  768. Ip4Address = (struct sockaddr_in *)SocketAddress;
  769. Port = Ip4Address->sin_port;
  770. Address = &(Ip4Address->sin_addr.s_addr);
  771. break;
  772. case AF_INET6:
  773. Ip6Address = (struct sockaddr_in6 *)SocketAddress;
  774. Port = Ip6Address->sin6_port;
  775. Address = &(Ip6Address->sin6_addr.s6_addr);
  776. //
  777. // If this is an IPv4-mapped or IPv4-compatible address, then build out
  778. // an IPv4 structure for DNS lookup.
  779. //
  780. if ((IN6_IS_ADDR_V4MAPPED(&(Ip6Address->sin6_addr)) != FALSE) ||
  781. (IN6_IS_ADDR_V4COMPAT(&(Ip6Address->sin6_addr)) != FALSE)) {
  782. Ip4MappedAddress.sin_family = AF_INET;
  783. Ip4MappedAddress.sin_port = Port;
  784. memcpy(&(Ip4MappedAddress.sin_addr.s_addr),
  785. &(Ip6Address->sin6_addr.s6_addr[12]),
  786. sizeof(in_addr_t));
  787. LookupAddress = (struct sockaddr *)&Ip4MappedAddress;
  788. LookupAddressLength = sizeof(struct sockaddr_in);
  789. }
  790. break;
  791. default:
  792. Status = EAI_ADDRFAMILY;
  793. goto getnameinfoEnd;
  794. }
  795. //
  796. // Get the node name if requested.
  797. //
  798. if ((Node != NULL) && (NodeLength != 0)) {
  799. Status = EAI_NONAME;
  800. if ((Flags & NI_NUMERICHOST) == 0) {
  801. //
  802. // Test to see if the lookup address is a local address.
  803. //
  804. Status = ClpIsLocalAddress(LookupAddress,
  805. LookupAddressLength,
  806. &LocalAddress,
  807. &UnspecifiedAddress);
  808. if (Status == 0) {
  809. //
  810. // If the address cannot be resolved locally, setup up and
  811. // perform a reverse DNS lookup. If this succeeds then return
  812. // the information for the first PTR entry in the list of
  813. // results.
  814. //
  815. if (LocalAddress == FALSE) {
  816. INITIALIZE_LIST_HEAD(&ResultList);
  817. Status = ClpPerformDnsReverseTranslation(
  818. LookupAddress,
  819. LookupAddressLength,
  820. &ResultList);
  821. if (Status == 0) {
  822. DnsResult = NULL;
  823. CurrentEntry = ResultList.Next;
  824. while (CurrentEntry != &(ResultList)) {
  825. DnsResult = LIST_VALUE(ResultList.Next,
  826. DNS_RESULT,
  827. ListEntry);
  828. if (DnsResult->Type == DNS_RECORD_TYPE_PTR) {
  829. break;
  830. }
  831. DnsResult = NULL;
  832. }
  833. if (DnsResult != NULL) {
  834. strncpy(Node, DnsResult->Value, NodeLength);
  835. } else {
  836. Status = EAI_NONAME;
  837. }
  838. ClpDestroyDnsResultList(&ResultList);
  839. }
  840. //
  841. // Otherwise if it is a local address that is not the any
  842. // address, then return the host name.
  843. //
  844. } else if (UnspecifiedAddress == FALSE) {
  845. Status = gethostname(Node, NodeLength);
  846. if (Status != 0) {
  847. Status = EAI_NONAME;
  848. //
  849. // On success, strip the domain if only the node name was
  850. // requested.
  851. //
  852. } else if ((Flags & NI_NOFQDN) != 0) {
  853. DomainName = strchr(Node, '.');
  854. if (DomainName != NULL) {
  855. *DomainName = '\0';
  856. }
  857. }
  858. //
  859. // Lastly, the unspecified address was supplied. There is no
  860. // name for that, unfortunately.
  861. //
  862. } else {
  863. Status = EAI_NONAME;
  864. }
  865. }
  866. if ((Status != 0) && ((Flags & NI_NAMEREQD) != 0)) {
  867. goto getnameinfoEnd;
  868. }
  869. }
  870. //
  871. // If the lookup failed, or was never attempted, get the numeric string
  872. // and copy it into the node string.
  873. //
  874. if (Status != 0) {
  875. inet_ntop(SocketAddress->sa_family,
  876. Address,
  877. AddressString,
  878. sizeof(AddressString));
  879. strncpy(Node, AddressString, NodeLength);
  880. }
  881. }
  882. //
  883. // Convert the service into a string.
  884. //
  885. if ((Service != NULL) && (ServiceLength != 0)) {
  886. ServiceEntry = NULL;
  887. if ((Flags & NI_NUMERICSERV) == 0) {
  888. if ((Flags & NI_DGRAM) != 0) {
  889. Protocol = NAME_INFORMATION_DGRAM_PROTOCOL_NAME;
  890. } else {
  891. Protocol = NAME_INFORMATION_DEFAULT_PROTOCOL_NAME;
  892. }
  893. ServiceEntry = getservbyport(Port, Protocol);
  894. }
  895. if (ServiceEntry != NULL) {
  896. strncpy(Service, ServiceEntry->s_name, ServiceLength);
  897. } else {
  898. snprintf(Service, ServiceLength, "%d", ntohs(Port));
  899. }
  900. }
  901. Status = 0;
  902. getnameinfoEnd:
  903. return Status;
  904. }
  905. LIBC_API
  906. const char *
  907. gai_strerror (
  908. int ErrorCode
  909. )
  910. /*++
  911. Routine Description:
  912. This routine returns a string describing the given error value set by
  913. getaddrinfo or getnameinfo.
  914. Arguments:
  915. ErrorCode - Supplies the value of errno set by the function. This routine
  916. returns strings for at least the following values: EAI_AGAIN,
  917. EAI_BADFLAGS, EAI_FAIL, EAI_FAMILY, EAI_MEMORY, EAI_NONAME,
  918. EAI_OVERFLOW, EAI_SERVICE, EAI_SOCKTYPE, and EAI_SYSTEM.
  919. Return Value:
  920. Returns a pointer to a string describing the error.
  921. --*/
  922. {
  923. if ((ErrorCode < 0) || (ErrorCode > EAI_OVERFLOW)) {
  924. return "Unknown error";
  925. }
  926. return ClGetAddressInformationErrorStrings[ErrorCode];
  927. }
  928. //
  929. // --------------------------------------------------------- Internal Functions
  930. //
  931. INT
  932. ClpPerformDnsTranslation (
  933. PSTR Name,
  934. UCHAR RecordType,
  935. NET_DOMAIN_TYPE Domain,
  936. PLIST_ENTRY ListHead,
  937. ULONG RecursionDepth
  938. )
  939. /*++
  940. Routine Description:
  941. This routine performs a DNS query on the given name.
  942. Arguments:
  943. Name - Supplies the name to execute the DNS request for.
  944. RecordType - Supplies the type of record to query for. See
  945. DNS_RECORD_TYPE_* definitions.
  946. Domain - Supplies the default network domain to use for DNS queries.
  947. ListHead - Supplies a pointer to the initialized list head where the
  948. desired DNS results will be returned.
  949. RecursionDepth - Supplies the recursion depth of this function, used to
  950. avoid getting in a loop of calling nameservers to translate nameservers.
  951. Supply 0 initially.
  952. Return Value:
  953. 0 on success.
  954. Returns an EAI_* error code on failure.
  955. --*/
  956. {
  957. PDNS_RESULT Alias;
  958. BOOL FollowedAlias;
  959. INT MatchCount;
  960. PDNS_RESULT NameServer;
  961. struct sockaddr NameServerAddress;
  962. LIST_ENTRY NameServerList;
  963. INT QueryCount;
  964. LIST_ENTRY ResultList;
  965. time_t StartTime;
  966. INT Status;
  967. LIST_ENTRY TranslationList;
  968. assert((RecordType == DNS_RECORD_TYPE_A) ||
  969. (RecordType == DNS_RECORD_TYPE_AAAA) ||
  970. (RecordType == DNS_RECORD_TYPE_PTR));
  971. assert((Domain == NetDomainIp4) ||
  972. (Domain == NetDomainIp6));
  973. assert((RecordType != DNS_RECORD_TYPE_A) ||
  974. (Domain == NetDomainIp4));
  975. assert((RecordType != DNS_RECORD_TYPE_AAAA) ||
  976. (Domain == NetDomainIp6));
  977. QueryCount = 0;
  978. INITIALIZE_LIST_HEAD(&NameServerList);
  979. INITIALIZE_LIST_HEAD(&ResultList);
  980. INITIALIZE_LIST_HEAD(&TranslationList);
  981. StartTime = time(NULL);
  982. if (RecursionDepth > 10) {
  983. fprintf(stderr, "Error: DNS recursion loop.\n");
  984. return EAI_AGAIN;
  985. }
  986. //
  987. // Attempt to get the DNS servers. If the default does not exist, then try
  988. // to perform the lookup on another network.
  989. //
  990. Status = ClpGetDnsServers(Domain, &NameServerAddress, &NameServerList);
  991. if (Status != 0) {
  992. if (Status == ENOENT) {
  993. if (Domain == NetDomainIp4) {
  994. Domain = NetDomainIp6;
  995. } else {
  996. Domain = NetDomainIp4;
  997. }
  998. Status = ClpGetDnsServers(Domain,
  999. &NameServerAddress,
  1000. &NameServerList);
  1001. }
  1002. if (Status != 0) {
  1003. if (Status == ENOENT) {
  1004. Status = EAI_AGAIN;
  1005. } else {
  1006. errno = Status;
  1007. Status = EAI_SYSTEM;
  1008. }
  1009. goto PerformDnsTranslationEnd;
  1010. }
  1011. }
  1012. //
  1013. // Loop querying name servers for results.
  1014. //
  1015. while (TRUE) {
  1016. Status = ClpPerformDnsQuery(Name,
  1017. RecordType,
  1018. &NameServerAddress,
  1019. sizeof(struct sockaddr),
  1020. &ResultList);
  1021. if (Status != 0) {
  1022. goto PerformDnsTranslationEnd;
  1023. }
  1024. QueryCount += 1;
  1025. if (QueryCount >= DNS_MAX_QUERY_COUNT) {
  1026. Status = EAI_FAIL;
  1027. goto PerformDnsTranslationEnd;
  1028. }
  1029. //
  1030. // Loop following CNAME entries.
  1031. //
  1032. FollowedAlias = FALSE;
  1033. while (TRUE) {
  1034. //
  1035. // Look directly for a result that matches the record and name.
  1036. //
  1037. MatchCount = ClpSearchDnsResultList(Name,
  1038. RecordType,
  1039. StartTime,
  1040. &ResultList,
  1041. ListHead);
  1042. if (MatchCount != 0) {
  1043. if (ClDebugDns != FALSE) {
  1044. fprintf(stderr, "DNS: Found %d results.\n", MatchCount);
  1045. }
  1046. Status = 0;
  1047. goto PerformDnsTranslationEnd;
  1048. }
  1049. //
  1050. // Look for a CNAME entry.
  1051. //
  1052. MatchCount = ClpSearchDnsResultList(Name,
  1053. DNS_RECORD_TYPE_CNAME,
  1054. StartTime,
  1055. &ResultList,
  1056. ListHead);
  1057. if (MatchCount == 0) {
  1058. break;
  1059. }
  1060. //
  1061. // There shouldn't be multiple aliases for the same name.
  1062. //
  1063. if (MatchCount > 1) {
  1064. Status = EAI_FAIL;
  1065. goto PerformDnsTranslationEnd;
  1066. }
  1067. //
  1068. // Set the name to the alias name, and try again.
  1069. //
  1070. FollowedAlias = TRUE;
  1071. Alias = LIST_VALUE(ListHead->Previous, DNS_RESULT, ListEntry);
  1072. Name = Alias->Value;
  1073. assert(Name != NULL);
  1074. if (ClDebugDns != FALSE) {
  1075. fprintf(stderr, "DNS: Following alias to %s.\n", Name);
  1076. }
  1077. //
  1078. // Following an alias counts as a query to detect alias loops.
  1079. //
  1080. QueryCount += 1;
  1081. if (QueryCount >= DNS_MAX_QUERY_COUNT) {
  1082. Status = EAI_FAIL;
  1083. goto PerformDnsTranslationEnd;
  1084. }
  1085. }
  1086. //
  1087. // If an alias was followed, keep the current name server.
  1088. //
  1089. if (FollowedAlias != FALSE) {
  1090. continue;
  1091. }
  1092. //
  1093. // Clear out any old translation results.
  1094. //
  1095. ClpDestroyDnsResultList(&TranslationList);
  1096. //
  1097. // Move all translations onto the translation list, and all name
  1098. // servers onto the name server list.
  1099. //
  1100. ClpSearchDnsResultList(NULL,
  1101. DNS_RECORD_TYPE_A,
  1102. StartTime,
  1103. &ResultList,
  1104. &TranslationList);
  1105. ClpSearchDnsResultList(NULL,
  1106. DNS_RECORD_TYPE_AAAA,
  1107. StartTime,
  1108. &ResultList,
  1109. &TranslationList);
  1110. ClpSearchDnsResultList(NULL,
  1111. DNS_RECORD_TYPE_NS,
  1112. StartTime,
  1113. &ResultList,
  1114. &NameServerList);
  1115. ClpSearchDnsResultList(NULL,
  1116. DNS_RECORD_TYPE_SOA,
  1117. StartTime,
  1118. &ResultList,
  1119. &NameServerList);
  1120. ClpDestroyDnsResultList(&ResultList);
  1121. //
  1122. // Loop trying to find the next name server to query.
  1123. //
  1124. while (TRUE) {
  1125. //
  1126. // Get the next name server in the list. Translate the name server
  1127. // to the the address of the name server.
  1128. //
  1129. if (LIST_EMPTY(&NameServerList) != FALSE) {
  1130. if (ClDebugDns != FALSE) {
  1131. fprintf(stderr, "Out of DNS servers to try.\n");
  1132. }
  1133. Status = 0;
  1134. goto PerformDnsTranslationEnd;
  1135. }
  1136. NameServer = LIST_VALUE(NameServerList.Next, DNS_RESULT, ListEntry);
  1137. //
  1138. // If the name server returned is a subdomain of the name being
  1139. // translated, then skip it unless the answer's already there.
  1140. //
  1141. if ((NameServer->Value != NULL) &&
  1142. (ClpIsNameSubdomain(NameServer->Value, Name) != FALSE)) {
  1143. Status = ClpFindNameServerAddress(NameServer,
  1144. RecordType,
  1145. &TranslationList,
  1146. &NameServerAddress);
  1147. if (Status != 0) {
  1148. if (ClDebugDns != FALSE) {
  1149. fprintf(stderr,
  1150. "Skipping name server %s, subdomain of %s\n",
  1151. NameServer->Value,
  1152. Name);
  1153. }
  1154. }
  1155. } else {
  1156. if (ClDebugDns != FALSE) {
  1157. fprintf(stderr,
  1158. "Trying name server '%s'.\n",
  1159. NameServer->Value);
  1160. }
  1161. Status = ClpGetNameServerAddress(NameServer,
  1162. RecordType,
  1163. &TranslationList,
  1164. &NameServerAddress,
  1165. RecursionDepth);
  1166. }
  1167. //
  1168. // Remove this name server from the list of name servers to try.
  1169. //
  1170. LIST_REMOVE(&(NameServer->ListEntry));
  1171. ClpDestroyDnsResult(NameServer);
  1172. if (Status == 0) {
  1173. break;
  1174. }
  1175. }
  1176. }
  1177. PerformDnsTranslationEnd:
  1178. ClpDestroyDnsResultList(&ResultList);
  1179. ClpDestroyDnsResultList(&TranslationList);
  1180. ClpDestroyDnsResultList(&NameServerList);
  1181. return Status;
  1182. }
  1183. INT
  1184. ClpPerformDnsReverseTranslation (
  1185. const struct sockaddr *SocketAddress,
  1186. socklen_t SocketAddressLength,
  1187. PLIST_ENTRY ListHead
  1188. )
  1189. /*++
  1190. Routine Description:
  1191. This routine performs a reverse DNS query on the given IP address.
  1192. Arguments:
  1193. SocketAddress - Supplies a pointer to the socket address to be translated.
  1194. This routine does not handle IPv4-mapped IPv6 addresses.
  1195. SocketAddressLength - Supplies the size of the socket address data.
  1196. ListHead - Supplies a pointer to the initialized list head where the
  1197. desired reverse DNS results will be returned.
  1198. Return Value:
  1199. 0 on success.
  1200. Returns an EAI_* error code on failure.
  1201. --*/
  1202. {
  1203. unsigned char *Address;
  1204. NET_DOMAIN_TYPE Domain;
  1205. ULONG Index;
  1206. struct sockaddr_in *Ip4Address;
  1207. struct sockaddr_in6 *Ip6Address;
  1208. uint8_t *Ip6AddressArray;
  1209. char Name[DNS_IP6_REVERSE_TRANSLATION_NAME_SIZE];
  1210. INT Status;
  1211. char *String;
  1212. ASSERT(DNS_IP6_REVERSE_TRANSLATION_NAME_SIZE >=
  1213. DNS_IP4_REVERSE_TRANSLATION_NAME_SIZE);
  1214. if (SocketAddressLength < sizeof(struct sockaddr_in)) {
  1215. Status = EAI_FAIL;
  1216. goto PerformDnsReverseTranslationEnd;
  1217. }
  1218. switch (SocketAddress->sa_family) {
  1219. case AF_INET6:
  1220. Ip6Address = (struct sockaddr_in6 *)SocketAddress;
  1221. Ip6AddressArray = Ip6Address->sin6_addr.s6_addr;
  1222. Domain = NetDomainIp6;
  1223. String = Name;
  1224. for (Index = 16; Index > 0; Index -= 1) {
  1225. String += snprintf(String,
  1226. 5,
  1227. "%x.%x.",
  1228. Ip6AddressArray[Index - 1] & 0xF,
  1229. (Ip6AddressArray[Index - 1] >> 4) & 0xF);
  1230. }
  1231. memcpy(String,
  1232. DNS_IP6_REVERSE_TRANSLATION_SUFFIX,
  1233. DNS_IP6_REVERSE_TRANSLATION_SUFFIX_SIZE);
  1234. break;
  1235. case AF_INET:
  1236. Domain = NetDomainIp4;
  1237. Ip4Address = (struct sockaddr_in *)SocketAddress;
  1238. Address = (unsigned char *)&(Ip4Address->sin_addr.s_addr);
  1239. snprintf(Name,
  1240. DNS_IP4_REVERSE_TRANSLATION_NAME_SIZE,
  1241. DNS_IP4_REVERSE_TRANSLATION_FORMAT,
  1242. Address[3],
  1243. Address[2],
  1244. Address[1],
  1245. Address[0]);
  1246. break;
  1247. default:
  1248. Status = EAI_ADDRFAMILY;
  1249. goto PerformDnsReverseTranslationEnd;
  1250. }
  1251. Status = ClpPerformDnsTranslation(Name,
  1252. DNS_RECORD_TYPE_PTR,
  1253. Domain,
  1254. ListHead,
  1255. 0);
  1256. if (Status != 0) {
  1257. goto PerformDnsReverseTranslationEnd;
  1258. }
  1259. PerformDnsReverseTranslationEnd:
  1260. return Status;
  1261. }
  1262. INT
  1263. ClpPerformDnsQuery (
  1264. PSTR Name,
  1265. CHAR RecordType,
  1266. struct sockaddr *NameServer,
  1267. socklen_t NameServerSize,
  1268. PLIST_ENTRY ListHead
  1269. )
  1270. /*++
  1271. Routine Description:
  1272. This routine performs a DNS query on the given name.
  1273. Arguments:
  1274. Name - Supplies the name to execute the DNS request for.
  1275. RecordType - Supplies the type of record to query for. See
  1276. DNS_RECORD_TYPE_* definitions.
  1277. NameServer - Supplies a pointer to the address to connect to for DNS name
  1278. resolutions.
  1279. NameServerSize - Supplies the size of the name server address in bytes.
  1280. ListHead - Supplies a pointer to the initialized list head where DNS
  1281. results will be returned.
  1282. Return Value:
  1283. 0 on success.
  1284. Returns an EAI_* error code on failure.
  1285. --*/
  1286. {
  1287. PLIST_ENTRY CurrentEntry;
  1288. PDNS_RESULT DnsResult;
  1289. const char *ErrorString;
  1290. PDNS_HEADER Request;
  1291. ULONG RequestSize;
  1292. PDNS_HEADER Response;
  1293. ULONG ResponseSize;
  1294. INT Status;
  1295. Request = NULL;
  1296. Response = NULL;
  1297. if (ClDebugDns != FALSE) {
  1298. fprintf(stderr, "DNS: Lookup '%s'.\n", Name);
  1299. }
  1300. Status = ClpCreateDnsQuery(Name, RecordType, &Request, &RequestSize);
  1301. if (Status != 0) {
  1302. goto PerformDnsQueryEnd;
  1303. }
  1304. Status = ClpExecuteDnsQuery(NameServer,
  1305. NameServerSize,
  1306. Request,
  1307. RequestSize,
  1308. &Response,
  1309. &ResponseSize);
  1310. if (Status != 0) {
  1311. goto PerformDnsQueryEnd;
  1312. }
  1313. if (Response->Identifier != Request->Identifier) {
  1314. if (ClDebugDns != FALSE) {
  1315. fprintf(stderr,
  1316. "DNS: Error: Identifier mismatch %x, %x.\n",
  1317. Request->Identifier,
  1318. Response->Identifier);
  1319. Status = EAI_FAIL;
  1320. goto PerformDnsQueryEnd;
  1321. }
  1322. }
  1323. //
  1324. // Save the current end of the list, and parse the response packet into
  1325. // more entries that get stuck on the end of the list.
  1326. //
  1327. CurrentEntry = ListHead->Previous;
  1328. Status = ClpParseDnsResponse(Response, ResponseSize, ListHead);
  1329. if (Status != 0) {
  1330. goto PerformDnsQueryEnd;
  1331. }
  1332. //
  1333. // For a good time, print the DNS result list.
  1334. //
  1335. if (ClDebugDns != FALSE) {
  1336. //
  1337. // If the previous entry is still the end of the list, nothing was
  1338. // added.
  1339. //
  1340. if (ListHead->Previous == CurrentEntry) {
  1341. fprintf(stderr, "No responses\n");
  1342. } else {
  1343. //
  1344. // If there was no previous entry, start at the first entry.
  1345. //
  1346. if (CurrentEntry == ListHead) {
  1347. CurrentEntry = CurrentEntry->Next;
  1348. }
  1349. while (CurrentEntry != ListHead) {
  1350. DnsResult = LIST_VALUE(CurrentEntry, DNS_RESULT, ListEntry);
  1351. ClpDebugPrintDnsResult(DnsResult);
  1352. CurrentEntry = CurrentEntry->Next;
  1353. }
  1354. }
  1355. }
  1356. PerformDnsQueryEnd:
  1357. if (Status != 0) {
  1358. if (ClDebugDns != FALSE) {
  1359. if (Status == EAI_SYSTEM) {
  1360. ErrorString = strerror(errno);
  1361. } else {
  1362. ErrorString = gai_strerror(Status);
  1363. }
  1364. fprintf(stderr, "DNS: Failed to execute query: %s.\n", ErrorString);
  1365. }
  1366. }
  1367. if (Request != NULL) {
  1368. free(Request);
  1369. }
  1370. if (Response != NULL) {
  1371. free(Response);
  1372. }
  1373. return Status;
  1374. }
  1375. INT
  1376. ClpCreateDnsQuery (
  1377. PSTR Name,
  1378. UCHAR ResponseType,
  1379. PDNS_HEADER *NewRequest,
  1380. PULONG RequestSize
  1381. )
  1382. /*++
  1383. Routine Description:
  1384. This routine creates and initializes a DNS query packet.
  1385. Arguments:
  1386. Name - Supplies the name of the host to query.
  1387. ResponseType - Supplies the type of response requested.
  1388. NewRequest - Supplies a pointer where a pointer to the new request will be
  1389. returned. The caller is responsible for freeing this memory.
  1390. RequestSize - Supplies a pointer where the size of the request in bytes
  1391. will be returned.
  1392. Return Value:
  1393. 0 on success.
  1394. Returns an EAI_ error code on failure.
  1395. --*/
  1396. {
  1397. ULONG AllocationSize;
  1398. PSTR CurrentString;
  1399. INT Error;
  1400. ULONG FieldLength;
  1401. PUCHAR FieldLengthPointer;
  1402. PUCHAR NameBuffer;
  1403. PUSHORT Pointer16;
  1404. PDNS_HEADER Request;
  1405. size_t StringLength;
  1406. Error = 0;
  1407. StringLength = strlen(Name);
  1408. //
  1409. // The allocation size is the header, plus the name length (where dots get
  1410. // converted into length bytes), plus extras for the initial field length
  1411. // and terminator, plus a type and class field.
  1412. //
  1413. AllocationSize = sizeof(DNS_HEADER) + (2 * sizeof(USHORT)) + StringLength +
  1414. 2;
  1415. Request = malloc(AllocationSize);
  1416. if (Request == NULL) {
  1417. return EAI_MEMORY;
  1418. }
  1419. memset(Request, 0, AllocationSize);
  1420. Request->Identifier = time(NULL) ^ rand();
  1421. Request->Flags = (DNS_HEADER_OPCODE_QUERY << DNS_HEADER_OPCODE_SHIFT) |
  1422. DNS_HEADER_FLAG_RECURSION_DESIRED;
  1423. Request->QuestionCount = htons(1);
  1424. NameBuffer = (PUCHAR)(Request + 1);
  1425. CurrentString = Name;
  1426. //
  1427. // Convert the name request into a DNS formatted name. DNS names are
  1428. // broken into fields by the '.' character, and each field is preceded by
  1429. // a length. The name is finally terminated by a zero-length field.
  1430. //
  1431. FieldLengthPointer = NameBuffer;
  1432. NameBuffer += 1;
  1433. FieldLength = 0;
  1434. while (TRUE) {
  1435. if ((*CurrentString == '.') || (*CurrentString == '\0')) {
  1436. if ((FieldLength == 0) || (FieldLength > MAX_UCHAR)) {
  1437. Error = EAI_FAIL;
  1438. goto CreateDnsQueryEnd;
  1439. }
  1440. *FieldLengthPointer = FieldLength;
  1441. FieldLengthPointer = NameBuffer;
  1442. FieldLength = 0;
  1443. if (*CurrentString == '\0') {
  1444. break;
  1445. }
  1446. } else {
  1447. *NameBuffer = *CurrentString;
  1448. FieldLength += 1;
  1449. }
  1450. CurrentString += 1;
  1451. NameBuffer += 1;
  1452. }
  1453. //
  1454. // Terminate the name.
  1455. //
  1456. *NameBuffer = 0;
  1457. NameBuffer += 1;
  1458. //
  1459. // Now add the type and class.
  1460. //
  1461. Pointer16 = (PUSHORT)NameBuffer;
  1462. *Pointer16 = htons(ResponseType);
  1463. Pointer16 += 1;
  1464. *Pointer16 = htons(DNS_CLASS_INTERNET);
  1465. Pointer16 += 1;
  1466. assert((UINTN)Pointer16 - (UINTN)Request == AllocationSize);
  1467. CreateDnsQueryEnd:
  1468. if (Error != 0) {
  1469. if (Request != NULL) {
  1470. free(Request);
  1471. Request = NULL;
  1472. }
  1473. AllocationSize = 0;
  1474. }
  1475. *NewRequest = Request;
  1476. *RequestSize = AllocationSize;
  1477. return Error;
  1478. }
  1479. INT
  1480. ClpExecuteDnsQuery (
  1481. struct sockaddr *NameServer,
  1482. socklen_t NameServerSize,
  1483. PDNS_HEADER Request,
  1484. ULONG RequestSize,
  1485. PDNS_HEADER *Response,
  1486. PULONG ResponseSize
  1487. )
  1488. /*++
  1489. Routine Description:
  1490. This routine sends a DNS query and returns the response.
  1491. Arguments:
  1492. NameServer - Supplies a pointer to the address to connect to for DNS name
  1493. resolutions.
  1494. NameServerSize - Supplies the size of the name server parameter.
  1495. Request - Supplies a pointer to the DNS request.
  1496. RequestSize - Supplies the size of the query in bytes.
  1497. Response - Supplies a pointer where a pointer to the response will be
  1498. returned on success. It is the caller's responsibility to free this
  1499. memory when finished.
  1500. ResponseSize - Supplies a pointer where the response size in bytes will be
  1501. returned on success.
  1502. Return Value:
  1503. 0 on success.
  1504. Returns an EAI_* error code on failure.
  1505. --*/
  1506. {
  1507. ssize_t ByteCount;
  1508. PDNS_HEADER DnsResponse;
  1509. INT Error;
  1510. struct sockaddr_in Ip4Address;
  1511. struct sockaddr_in6 Ip6Address;
  1512. struct pollfd Poll;
  1513. INT Result;
  1514. INT Socket;
  1515. Socket = -1;
  1516. DnsResponse = malloc(DNS_RESPONSE_ALLOCATION_SIZE);
  1517. if (DnsResponse == NULL) {
  1518. Error = EAI_MEMORY;
  1519. goto ExecuteDnsQueryEnd;
  1520. }
  1521. Socket = socket(NameServer->sa_family, SOCK_DGRAM, IPPROTO_UDP);
  1522. if (Socket == -1) {
  1523. Error = EAI_SYSTEM;
  1524. goto ExecuteDnsQueryEnd;
  1525. }
  1526. //
  1527. // Create a local address with the same family as the name server
  1528. // destination and bind to it.
  1529. //
  1530. switch (NameServer->sa_family) {
  1531. case AF_INET:
  1532. memset(&Ip4Address, 0, sizeof(struct sockaddr_in));
  1533. Ip4Address.sin_family = AF_INET;
  1534. Result = bind(Socket,
  1535. (struct sockaddr *)&Ip4Address,
  1536. sizeof(Ip4Address));
  1537. if (Result != 0) {
  1538. Error = EAI_SYSTEM;
  1539. goto ExecuteDnsQueryEnd;
  1540. }
  1541. break;
  1542. case AF_INET6:
  1543. memset(&Ip6Address, 0, sizeof(struct sockaddr_in6));
  1544. Ip6Address.sin6_family = AF_INET6;
  1545. Result = bind(Socket,
  1546. (struct sockaddr *)&Ip6Address,
  1547. sizeof(Ip6Address));
  1548. if (Result != 0) {
  1549. Error = EAI_SYSTEM;
  1550. goto ExecuteDnsQueryEnd;
  1551. }
  1552. break;
  1553. default:
  1554. assert(FALSE);
  1555. Error = EAI_FAMILY;
  1556. goto ExecuteDnsQueryEnd;
  1557. }
  1558. ByteCount = sendto(Socket,
  1559. Request,
  1560. RequestSize,
  1561. 0,
  1562. NameServer,
  1563. NameServerSize);
  1564. if (ByteCount != RequestSize) {
  1565. Error = EAI_SYSTEM;
  1566. goto ExecuteDnsQueryEnd;
  1567. }
  1568. //
  1569. // Wait for a response.
  1570. //
  1571. Poll.fd = Socket;
  1572. Poll.events = POLLIN;
  1573. Poll.revents = 0;
  1574. do {
  1575. Result = poll(&Poll, 1, DNS_RESPONSE_TIMEOUT);
  1576. } while ((Result < 0) && (errno == EINTR));
  1577. if (Result <= 0) {
  1578. Error = EAI_AGAIN;
  1579. goto ExecuteDnsQueryEnd;
  1580. }
  1581. do {
  1582. ByteCount = recv(Socket, DnsResponse, DNS_RESPONSE_ALLOCATION_SIZE, 0);
  1583. } while ((ByteCount == 0) && (errno == EINTR));
  1584. if (ByteCount == 0) {
  1585. Error = EAI_SYSTEM;
  1586. goto ExecuteDnsQueryEnd;
  1587. }
  1588. *ResponseSize = ByteCount;
  1589. Error = 0;
  1590. ExecuteDnsQueryEnd:
  1591. if (Error != 0) {
  1592. if (DnsResponse != NULL) {
  1593. free(DnsResponse);
  1594. DnsResponse = NULL;
  1595. }
  1596. }
  1597. if (Socket != -1) {
  1598. close(Socket);
  1599. }
  1600. *Response = DnsResponse;
  1601. return Error;
  1602. }
  1603. INT
  1604. ClpParseDnsResponse (
  1605. PDNS_HEADER Response,
  1606. ULONG ResponseSize,
  1607. PLIST_ENTRY ListHead
  1608. )
  1609. /*++
  1610. Routine Description:
  1611. This routine parses a DNS response to a list of dns result structures,
  1612. decompressing names along the way.
  1613. Arguments:
  1614. Response - Supplies a pointer to the DNS response packet.
  1615. ResponseSize - Supplies the size of the DNS response packet in bytes.
  1616. ListHead - Supplies a pointer to an initialized list head where result
  1617. structures will be returned. This list may have items on it even if
  1618. the return code is failing. It is the caller's responsibility to free
  1619. these items.
  1620. Return Value:
  1621. 0 on success.
  1622. Returns an EAI_* error code on failure.
  1623. --*/
  1624. {
  1625. ULONG AdditionalResourceCount;
  1626. ULONG AdditionalResourceIndex;
  1627. ULONG AnswerCount;
  1628. ULONG AnswerIndex;
  1629. PUCHAR Buffer;
  1630. ULONG NameServerCount;
  1631. ULONG NameServerIndex;
  1632. ULONG QuestionCount;
  1633. ULONG QuestionIndex;
  1634. UCHAR ResponseCode;
  1635. INT Status;
  1636. //
  1637. // Validate that the flags field came back okay.
  1638. //
  1639. if ((Response->Flags & DNS_HEADER_FLAG_RESPONSE) == 0) {
  1640. Status = EAI_BADFLAGS;
  1641. goto ParseDnsResponseEnd;
  1642. }
  1643. ResponseCode = (Response->Flags >> DNS_HEADER_RESPONSE_SHIFT) &
  1644. DNS_HEADER_RESPONSE_MASK;
  1645. if (ResponseCode != DNS_HEADER_RESPONSE_SUCCESS) {
  1646. if (ResponseCode == DNS_HEADER_RESPONSE_NAME_ERROR) {
  1647. Status = EAI_NONAME;
  1648. } else if (ResponseCode == DNS_HEADER_RESPONSE_REFUSED) {
  1649. Status = EAI_AGAIN;
  1650. } else {
  1651. Status = EAI_FAIL;
  1652. }
  1653. goto ParseDnsResponseEnd;
  1654. }
  1655. QuestionCount = ntohs(Response->QuestionCount);
  1656. AnswerCount = ntohs(Response->AnswerCount);
  1657. NameServerCount = ntohs(Response->NameServerCount);
  1658. AdditionalResourceCount = ntohs(Response->AdditionalResourceCount);
  1659. if ((AnswerCount == 0) &&
  1660. (NameServerCount == 0) &&
  1661. (AdditionalResourceCount == 0)) {
  1662. Status = 0;
  1663. goto ParseDnsResponseEnd;
  1664. }
  1665. //
  1666. // Zoom through the questions.
  1667. //
  1668. Buffer = (PUCHAR)(Response + 1);
  1669. for (QuestionIndex = 0; QuestionIndex < QuestionCount; QuestionIndex += 1) {
  1670. Status = ClpDecompressDnsName(Response, ResponseSize, &Buffer, NULL);
  1671. if (Status != 0) {
  1672. goto ParseDnsResponseEnd;
  1673. }
  1674. //
  1675. // Also scan past the rest of the structure, which contains the type
  1676. // and class, both 16-bits.
  1677. //
  1678. Buffer += 4;
  1679. if ((UINTN)Buffer - (UINTN)Response > ResponseSize) {
  1680. Status = EAI_OVERFLOW;
  1681. goto ParseDnsResponseEnd;
  1682. }
  1683. }
  1684. //
  1685. // Parse the answers.
  1686. //
  1687. for (AnswerIndex = 0; AnswerIndex < AnswerCount; AnswerIndex += 1) {
  1688. Status = ClpParseDnsResponseElement(Response,
  1689. ResponseSize,
  1690. &Buffer,
  1691. ListHead);
  1692. if (Status != 0) {
  1693. goto ParseDnsResponseEnd;
  1694. }
  1695. }
  1696. //
  1697. // Parse the name servers.
  1698. //
  1699. for (NameServerIndex = 0;
  1700. NameServerIndex < NameServerCount;
  1701. NameServerIndex += 1) {
  1702. Status = ClpParseDnsResponseElement(Response,
  1703. ResponseSize,
  1704. &Buffer,
  1705. ListHead);
  1706. if (Status != 0) {
  1707. goto ParseDnsResponseEnd;
  1708. }
  1709. }
  1710. //
  1711. // Parse the additional data.
  1712. //
  1713. for (AdditionalResourceIndex = 0;
  1714. AdditionalResourceIndex < AdditionalResourceCount;
  1715. AdditionalResourceIndex += 1) {
  1716. Status = ClpParseDnsResponseElement(Response,
  1717. ResponseSize,
  1718. &Buffer,
  1719. ListHead);
  1720. if (Status != 0) {
  1721. goto ParseDnsResponseEnd;
  1722. }
  1723. }
  1724. Status = 0;
  1725. ParseDnsResponseEnd:
  1726. return Status;
  1727. }
  1728. INT
  1729. ClpParseDnsResponseElement (
  1730. PDNS_HEADER Response,
  1731. ULONG ResponseSize,
  1732. PUCHAR *ResponseEntry,
  1733. PLIST_ENTRY ListHead
  1734. )
  1735. /*++
  1736. Routine Description:
  1737. This routine parses a single DNS response entry.
  1738. Arguments:
  1739. Response - Supplies a pointer to the DNS response packet.
  1740. ResponseSize - Supplies the size of the DNS response packet in bytes.
  1741. ResponseEntry - Supplies a pointer that on input points to the response
  1742. entry. On output, this buffer will be advanced past the response entry.
  1743. ListHead - Supplies a pointer to an initialized list head where result
  1744. structures will be returned. This list may have items on it even if
  1745. the return code is failing. It is the caller's responsibility to free
  1746. these items.
  1747. Return Value:
  1748. 0 on success.
  1749. Returns an EAI_* error code on failure.
  1750. --*/
  1751. {
  1752. PUCHAR Buffer;
  1753. USHORT DataLength;
  1754. struct sockaddr_in *Ip4Address;
  1755. struct sockaddr_in6 *Ip6Address;
  1756. PDNS_RESULT Result;
  1757. INT Status;
  1758. ULONG TimeToLive;
  1759. Result = malloc(sizeof(DNS_RESULT));
  1760. if (Result == NULL) {
  1761. Status = EAI_MEMORY;
  1762. goto ParseDnsResponseElementEnd;
  1763. }
  1764. memset(Result, 0, sizeof(DNS_RESULT));
  1765. Buffer = *ResponseEntry;
  1766. if ((UINTN)Buffer - (UINTN)Response >= ResponseSize) {
  1767. Status = EAI_OVERFLOW;
  1768. goto ParseDnsResponseElementEnd;
  1769. }
  1770. //
  1771. // Responses start with a name.
  1772. //
  1773. Status = ClpDecompressDnsName(Response,
  1774. ResponseSize,
  1775. &Buffer,
  1776. &(Result->Name));
  1777. if (Status != 0) {
  1778. goto ParseDnsResponseElementEnd;
  1779. }
  1780. //
  1781. // Then comes the type (16 bits), class (16-bits), time-to-live (32-bits),
  1782. // and data length (16 bits).
  1783. //
  1784. if ((UINTN)Buffer + 10 - (UINTN)Response >= ResponseSize) {
  1785. Status = EAI_OVERFLOW;
  1786. goto ParseDnsResponseElementEnd;
  1787. }
  1788. Result->Type = ((USHORT)*Buffer << BITS_PER_BYTE) | *(Buffer + 1);
  1789. Buffer += 2;
  1790. Result->Class = ((USHORT)*Buffer << BITS_PER_BYTE) | *(Buffer + 1);
  1791. Buffer += 2;
  1792. TimeToLive = ((ULONG)*Buffer << (3 * BITS_PER_BYTE)) |
  1793. ((ULONG)*(Buffer + 1) << (2 * BITS_PER_BYTE)) |
  1794. ((ULONG)*(Buffer + 2) << BITS_PER_BYTE) |
  1795. (ULONG)*(Buffer + 3);
  1796. Result->ExpirationTime = time(NULL) + TimeToLive;
  1797. Buffer += 4;
  1798. DataLength = ((USHORT)*Buffer << BITS_PER_BYTE) | *(Buffer + 1);
  1799. Buffer += 2;
  1800. if ((UINTN)Buffer + DataLength <= ResponseSize) {
  1801. Status = EAI_OVERFLOW;
  1802. goto ParseDnsResponseElementEnd;
  1803. }
  1804. //
  1805. // Parse the data into the appropriate value.
  1806. //
  1807. if (Result->Class != DNS_CLASS_INTERNET) {
  1808. Buffer += DataLength;
  1809. Status = EAI_FAIL;
  1810. goto ParseDnsResponseElementEnd;
  1811. }
  1812. switch (Result->Type) {
  1813. case DNS_RECORD_TYPE_A:
  1814. if (DataLength != 4) {
  1815. Status = EAI_FAIL;
  1816. goto ParseDnsResponseElementEnd;
  1817. }
  1818. Ip4Address = (struct sockaddr_in *)&(Result->Address);
  1819. Ip4Address->sin_family = AF_INET;
  1820. assert(sizeof(in_addr_t) == 4);
  1821. memcpy(&(Ip4Address->sin_addr.s_addr), Buffer, 4);
  1822. Buffer += DataLength;
  1823. break;
  1824. case DNS_RECORD_TYPE_AAAA:
  1825. if (DataLength != 16) {
  1826. Status = EAI_FAIL;
  1827. goto ParseDnsResponseElementEnd;
  1828. }
  1829. Ip6Address = (struct sockaddr_in6 *)&(Result->Address);
  1830. Ip6Address->sin6_family = AF_INET6;
  1831. memcpy(&(Ip6Address->sin6_addr.s6_addr), Buffer, 16);
  1832. Buffer += DataLength;
  1833. break;
  1834. case DNS_RECORD_TYPE_NS:
  1835. case DNS_RECORD_TYPE_CNAME:
  1836. case DNS_RECORD_TYPE_SOA:
  1837. case DNS_RECORD_TYPE_PTR:
  1838. Status = ClpDecompressDnsName(Response,
  1839. ResponseSize,
  1840. &Buffer,
  1841. &(Result->Value));
  1842. if (Status != 0) {
  1843. goto ParseDnsResponseElementEnd;
  1844. }
  1845. break;
  1846. default:
  1847. Buffer += DataLength;
  1848. break;
  1849. }
  1850. INSERT_BEFORE(&(Result->ListEntry), ListHead);
  1851. Status = 0;
  1852. ParseDnsResponseElementEnd:
  1853. if (Status != 0) {
  1854. if (Result != NULL) {
  1855. ClpDestroyDnsResult(Result);
  1856. }
  1857. }
  1858. *ResponseEntry = Buffer;
  1859. return Status;
  1860. }
  1861. INT
  1862. ClpDecompressDnsName (
  1863. PDNS_HEADER Response,
  1864. ULONG ResponseSize,
  1865. PUCHAR *DnsName,
  1866. PSTR *OutputName
  1867. )
  1868. /*++
  1869. Routine Description:
  1870. This routine parses a DNS compressed name back into a regular string.
  1871. Arguments:
  1872. Response - Supplies a pointer to the DNS response packet.
  1873. ResponseSize - Supplies the size of the DNS response packet in bytes.
  1874. DnsName - Supplies a pointer that upon input contains a pointer within the
  1875. response where the name begins. On output, this value will be advanced
  1876. just beyond the name.
  1877. OutputName - Supplies an optional pointer where a pointer to the newly
  1878. allocated decompressed name will be returned. It is the caller's
  1879. responsibility to free this buffer. If this is not supplied, then the
  1880. name will be advanced past, but not parsed out into a new buffer.
  1881. Return Value:
  1882. 0 on success.
  1883. Returns an EAI_* error code on failure.
  1884. --*/
  1885. {
  1886. PUCHAR BufferEnd;
  1887. PSTR OutputNameBuffer;
  1888. ULONG OutputNameSize;
  1889. INT Status;
  1890. OutputNameBuffer = NULL;
  1891. //
  1892. // Scan to figure out where the name ends.
  1893. //
  1894. BufferEnd = *DnsName;
  1895. while (TRUE) {
  1896. if ((UINTN)BufferEnd - (UINTN)Response >= ResponseSize) {
  1897. Status = EAI_OVERFLOW;
  1898. goto DecompressDnsNameEnd;
  1899. }
  1900. if (*BufferEnd == 0) {
  1901. BufferEnd += 1;
  1902. break;
  1903. }
  1904. //
  1905. // If a link is found, then this is probably the end of the string.
  1906. // Links are not allowed to go forward.
  1907. //
  1908. if ((*BufferEnd & DNS_COMPRESSION_MASK) == DNS_COMPRESSION_VALUE) {
  1909. BufferEnd += 2;
  1910. break;
  1911. }
  1912. BufferEnd += *BufferEnd + 1;
  1913. }
  1914. //
  1915. // If no output is desired, then all the work is done.
  1916. //
  1917. if (OutputName == NULL) {
  1918. Status = 0;
  1919. goto DecompressDnsNameEnd;
  1920. }
  1921. //
  1922. // Scan through the string once to figure out how big it is.
  1923. //
  1924. OutputNameSize = 0;
  1925. Status = ClpScanDnsName((PUCHAR)Response,
  1926. ResponseSize,
  1927. *DnsName,
  1928. NULL,
  1929. &OutputNameSize);
  1930. if (Status != 0) {
  1931. goto DecompressDnsNameEnd;
  1932. }
  1933. assert(OutputNameSize != 0);
  1934. //
  1935. // Now allocate the string buffer and scan again to create the string.
  1936. //
  1937. OutputNameBuffer = malloc(OutputNameSize);
  1938. if (OutputNameBuffer == NULL) {
  1939. Status = EAI_MEMORY;
  1940. goto DecompressDnsNameEnd;
  1941. }
  1942. Status = ClpScanDnsName((PUCHAR)Response,
  1943. ResponseSize,
  1944. *DnsName,
  1945. OutputNameBuffer,
  1946. &OutputNameSize);
  1947. if (Status != 0) {
  1948. goto DecompressDnsNameEnd;
  1949. }
  1950. DecompressDnsNameEnd:
  1951. if (Status != 0) {
  1952. if (OutputNameBuffer != NULL) {
  1953. free(OutputNameBuffer);
  1954. }
  1955. }
  1956. *DnsName = BufferEnd;
  1957. if (OutputName != NULL) {
  1958. *OutputName = OutputNameBuffer;
  1959. }
  1960. return Status;
  1961. }
  1962. INT
  1963. ClpScanDnsName (
  1964. PUCHAR Response,
  1965. ULONG ResponseSize,
  1966. PUCHAR Name,
  1967. PSTR OutputName,
  1968. PULONG OutputNameSize
  1969. )
  1970. /*++
  1971. Routine Description:
  1972. This routine scans through a DNS name.
  1973. Arguments:
  1974. Response - Supplies a pointer to the DNS response packet.
  1975. ResponseSize - Supplies the size of the DNS response packet in bytes.
  1976. Name - Supplies a pointer to the compressed DNS name.
  1977. OutputName - Supplies an optional pointer where the decompressed name will
  1978. be returned.
  1979. OutputNameSize - Supplies a pointer that on input supplies the size of
  1980. the output name buffer. On output, contains the required size of the
  1981. output name buffer.
  1982. Return Value:
  1983. 0 on success.
  1984. Returns an EAI_* error code on failure.
  1985. --*/
  1986. {
  1987. UCHAR LegCount;
  1988. ULONG NeededSize;
  1989. USHORT Offset;
  1990. ULONG OutputSize;
  1991. INT Status;
  1992. NeededSize = 0;
  1993. OutputSize = *OutputNameSize;
  1994. assert((UINTN)Name - (UINTN)Response < ResponseSize);
  1995. LegCount = 0;
  1996. //
  1997. // Loop scanning legs (that's an unofficial term).
  1998. //
  1999. while (TRUE) {
  2000. //
  2001. // Detect infinite loops.
  2002. //
  2003. if (NeededSize > DNS_MAX_NAME) {
  2004. Status = EAI_OVERFLOW;
  2005. goto ScanDnsNameEnd;
  2006. }
  2007. while (LegCount != 0) {
  2008. if ((UINTN)Name - (UINTN)Response >= ResponseSize) {
  2009. Status = EAI_OVERFLOW;
  2010. goto ScanDnsNameEnd;
  2011. }
  2012. if (OutputName != NULL) {
  2013. assert(OutputSize != 0);
  2014. *OutputName = *Name;
  2015. OutputName += 1;
  2016. OutputSize -= 1;
  2017. }
  2018. NeededSize += 1;
  2019. Name += 1;
  2020. LegCount -= 1;
  2021. }
  2022. if ((UINTN)Name - (UINTN)Response >= ResponseSize) {
  2023. Status = EAI_OVERFLOW;
  2024. goto ScanDnsNameEnd;
  2025. }
  2026. //
  2027. // A zero-length leg signifies the end.
  2028. //
  2029. if (*Name == 0) {
  2030. break;
  2031. }
  2032. //
  2033. // If the top two bits are not set, this is just another regular leg.
  2034. //
  2035. if ((*Name & DNS_COMPRESSION_MASK) != DNS_COMPRESSION_VALUE) {
  2036. //
  2037. // Add a dot to the output string (except for the very first time).
  2038. //
  2039. if (NeededSize != 0) {
  2040. if (OutputName != NULL) {
  2041. assert(OutputSize != 0);
  2042. *OutputName = '.';
  2043. OutputName += 1;
  2044. OutputSize -= 1;
  2045. }
  2046. NeededSize += 1;
  2047. }
  2048. LegCount = *Name;
  2049. Name += 1;
  2050. continue;
  2051. }
  2052. //
  2053. // The top two bits are set, so this is a jump elsewhere in the packet.
  2054. //
  2055. if ((UINTN)Name + 1 - (UINTN)Response >= ResponseSize) {
  2056. Status = EAI_OVERFLOW;
  2057. goto ScanDnsNameEnd;
  2058. }
  2059. Offset = ((USHORT)(*Name & (~DNS_COMPRESSION_MASK)) << BITS_PER_BYTE) |
  2060. *(Name + 1);
  2061. //
  2062. // Watch out for infinite loops (a link to this link).
  2063. //
  2064. if (Offset == (UINTN)Name - (UINTN)Response) {
  2065. Status = EAI_OVERFLOW;
  2066. goto ScanDnsNameEnd;
  2067. }
  2068. Name = Response + Offset;
  2069. if ((UINTN)Name - (UINTN)Response >= ResponseSize) {
  2070. Status = EAI_OVERFLOW;
  2071. goto ScanDnsNameEnd;
  2072. }
  2073. //
  2074. // Loop. Notice that the leg count is still zero, meaning another
  2075. // iteration is required to get the leg count (or immediately follow
  2076. // another link, etc).
  2077. //
  2078. }
  2079. //
  2080. // Null terminate the string.
  2081. //
  2082. if (OutputName != NULL) {
  2083. assert(OutputSize != 0);
  2084. *OutputName = '\0';
  2085. OutputName += 1;
  2086. OutputSize -= 1;
  2087. }
  2088. NeededSize += 1;
  2089. Status = 0;
  2090. ScanDnsNameEnd:
  2091. *OutputNameSize = NeededSize;
  2092. return Status;
  2093. }
  2094. VOID
  2095. ClpDestroyDnsResultList (
  2096. PLIST_ENTRY ListHead
  2097. )
  2098. /*++
  2099. Routine Description:
  2100. This routine destroys a list of DNS result structures.
  2101. Arguments:
  2102. ListHead - Supplies a pointer to the head of the list.
  2103. Return Value:
  2104. None.
  2105. --*/
  2106. {
  2107. PDNS_RESULT Result;
  2108. while (LIST_EMPTY(ListHead) == FALSE) {
  2109. Result = LIST_VALUE(ListHead->Next, DNS_RESULT, ListEntry);
  2110. LIST_REMOVE(&(Result->ListEntry));
  2111. ClpDestroyDnsResult(Result);
  2112. }
  2113. return;
  2114. }
  2115. VOID
  2116. ClpDestroyDnsResult (
  2117. PDNS_RESULT Result
  2118. )
  2119. /*++
  2120. Routine Description:
  2121. This routine destroys a DNS result structure. It is assumed that this
  2122. has already been pulled off of any list it may have been on.
  2123. Arguments:
  2124. Result - Supplies a pointer to the result to destroy.
  2125. Return Value:
  2126. None.
  2127. --*/
  2128. {
  2129. if (Result == NULL) {
  2130. return;
  2131. }
  2132. if (Result->Name != NULL) {
  2133. free(Result->Name);
  2134. }
  2135. if (Result->Value != NULL) {
  2136. free(Result->Value);
  2137. }
  2138. free(Result);
  2139. return;
  2140. }
  2141. VOID
  2142. ClpDebugPrintDnsResult (
  2143. PDNS_RESULT Result
  2144. )
  2145. /*++
  2146. Routine Description:
  2147. This routine prints a DNS result structure to standard error.
  2148. Arguments:
  2149. Result - Supplies a pointer to the result to print.
  2150. Return Value:
  2151. None.
  2152. --*/
  2153. {
  2154. struct sockaddr_in *Ip4Address;
  2155. struct sockaddr_in6 *Ip6Address;
  2156. CHAR PrintBuffer[60];
  2157. struct tm TimeStructure;
  2158. PSTR TypeString;
  2159. if (Result->Class != DNS_CLASS_INTERNET) {
  2160. fprintf(stderr, "Class %x ", Result->Class);
  2161. }
  2162. switch (Result->Type) {
  2163. case DNS_RECORD_TYPE_A:
  2164. TypeString = "A";
  2165. break;
  2166. case DNS_RECORD_TYPE_AAAA:
  2167. TypeString = "AAAA";
  2168. break;
  2169. case DNS_RECORD_TYPE_NS:
  2170. TypeString = "NS";
  2171. break;
  2172. case DNS_RECORD_TYPE_CNAME:
  2173. TypeString = "CNAME";
  2174. break;
  2175. case DNS_RECORD_TYPE_SOA:
  2176. TypeString = "SOA";
  2177. break;
  2178. case DNS_RECORD_TYPE_MX:
  2179. TypeString = "MX";
  2180. break;
  2181. case DNS_RECORD_TYPE_TXT:
  2182. TypeString = "TXT";
  2183. break;
  2184. default:
  2185. TypeString = NULL;
  2186. break;
  2187. }
  2188. if (TypeString != NULL) {
  2189. fprintf(stderr, "%s %s ", TypeString, Result->Name);
  2190. } else {
  2191. fprintf(stderr, "Unknown (%u) %s ", Result->Type, Result->Name);
  2192. }
  2193. switch (Result->Type) {
  2194. case DNS_RECORD_TYPE_A:
  2195. Ip4Address = (struct sockaddr_in *)&(Result->Address);
  2196. assert(Ip4Address->sin_family == AF_INET);
  2197. inet_ntop(Ip4Address->sin_family,
  2198. &(Ip4Address->sin_addr.s_addr),
  2199. PrintBuffer,
  2200. sizeof(PrintBuffer));
  2201. fprintf(stderr, "%s", PrintBuffer);
  2202. break;
  2203. case DNS_RECORD_TYPE_AAAA:
  2204. Ip6Address = (struct sockaddr_in6 *)&(Result->Address);
  2205. assert(Ip6Address->sin6_family == AF_INET6);
  2206. inet_ntop(Ip6Address->sin6_family,
  2207. &(Ip6Address->sin6_addr.s6_addr),
  2208. PrintBuffer,
  2209. sizeof(PrintBuffer));
  2210. fprintf(stderr, "%s", PrintBuffer);
  2211. break;
  2212. case DNS_RECORD_TYPE_NS:
  2213. case DNS_RECORD_TYPE_CNAME:
  2214. case DNS_RECORD_TYPE_SOA:
  2215. fprintf(stderr, "%s", Result->Value);
  2216. break;
  2217. default:
  2218. break;
  2219. }
  2220. localtime_r(&(Result->ExpirationTime), &TimeStructure);
  2221. asctime_r(&TimeStructure, PrintBuffer);
  2222. fprintf(stderr, " Expires %s", PrintBuffer);
  2223. return;
  2224. }
  2225. INT
  2226. ClpGetNameServerAddress (
  2227. PDNS_RESULT NameServer,
  2228. UCHAR RecordType,
  2229. PLIST_ENTRY TranslationList,
  2230. struct sockaddr *NameServerAddress,
  2231. ULONG RecursionDepth
  2232. )
  2233. /*++
  2234. Routine Description:
  2235. This routine attempts to find the address of a name server.
  2236. Arguments:
  2237. NameServer - Supplies the DNS name server or start of authority result.
  2238. RecordType - Supplies the type of record to search for.
  2239. TranslationList - Supplies the list of possible translations to the name
  2240. server address. More results may be added to this list.
  2241. NameServerAddress - Supplies a pointer where the address of the name server
  2242. will be returned, including having its port set to the DNS port number.
  2243. RecursionDepth - Supplies the current recursion depth.
  2244. Return Value:
  2245. 0 on success.
  2246. Returns an error code on failure.
  2247. --*/
  2248. {
  2249. NET_DOMAIN_TYPE Domain;
  2250. INT Status;
  2251. //
  2252. // If the record type is not nameserver, then assume the address
  2253. // is there directly. It's probably an original name server address
  2254. // from the top of the function.
  2255. //
  2256. if ((NameServer->Type != DNS_RECORD_TYPE_NS) &&
  2257. (NameServer->Type != DNS_RECORD_TYPE_SOA)) {
  2258. assert((NameServer->Type == DNS_RECORD_TYPE_A) ||
  2259. (NameServer->Type == DNS_RECORD_TYPE_AAAA));
  2260. memcpy(&NameServerAddress,
  2261. &(NameServer->Address),
  2262. sizeof(struct sockaddr));
  2263. return 0;
  2264. }
  2265. //
  2266. // Maybe the name server address was already returned in the list of
  2267. // translations.
  2268. //
  2269. Status = ClpFindNameServerAddress(NameServer,
  2270. RecordType,
  2271. TranslationList,
  2272. NameServerAddress);
  2273. if (Status == 0) {
  2274. return Status;
  2275. }
  2276. if (RecordType == DNS_RECORD_TYPE_AAAA) {
  2277. Domain = NetDomainIp6;
  2278. } else {
  2279. Domain = NetDomainIp4;
  2280. }
  2281. //
  2282. // Go start a whole new query to figure out the name server address.
  2283. //
  2284. Status = ClpPerformDnsTranslation(NameServer->Value,
  2285. RecordType,
  2286. Domain,
  2287. TranslationList,
  2288. RecursionDepth + 1);
  2289. if (Status != 0) {
  2290. if (ClDebugDns != FALSE) {
  2291. fprintf(stderr,
  2292. "Error: Failed to get address of DNS server %s\n",
  2293. NameServer->Value);
  2294. }
  2295. return Status;
  2296. }
  2297. Status = ClpFindNameServerAddress(NameServer,
  2298. RecordType,
  2299. TranslationList,
  2300. NameServerAddress);
  2301. if (Status == 0) {
  2302. return Status;
  2303. }
  2304. if (ClDebugDns != FALSE) {
  2305. fprintf(stderr,
  2306. "Error: Failed to get address of DNS server %s\n",
  2307. NameServer->Value);
  2308. }
  2309. return Status;
  2310. }
  2311. INT
  2312. ClpFindNameServerAddress (
  2313. PDNS_RESULT NameServer,
  2314. UCHAR RecordType,
  2315. PLIST_ENTRY TranslationList,
  2316. struct sockaddr *NameServerAddress
  2317. )
  2318. /*++
  2319. Routine Description:
  2320. This routine attempts to find the address of a name server in the list of
  2321. translations.
  2322. Arguments:
  2323. NameServer - Supplies the DNS name server or start of authority result.
  2324. RecordType - Supplies the type of record to search for.
  2325. TranslationList - Supplies the list of possible translations to the name
  2326. server address. More results may be added to this list.
  2327. NameServerAddress - Supplies a pointer where the address of the name server
  2328. will be returned, including having its port set to the DNS port number.
  2329. Return Value:
  2330. 0 on success.
  2331. Returns an error code on failure.
  2332. --*/
  2333. {
  2334. ULONG MatchCount;
  2335. struct sockaddr_in *NameServerAddressIp4;
  2336. struct sockaddr_in6 *NameServerAddressIp6;
  2337. LIST_ENTRY NameServerAddressList;
  2338. INT Status;
  2339. time_t Time;
  2340. PDNS_RESULT Translation;
  2341. MatchCount = 0;
  2342. INITIALIZE_LIST_HEAD(&NameServerAddressList);
  2343. Status = 0;
  2344. Time = time(NULL);
  2345. //
  2346. // Look for IPv6 translations if the caller wants IPv6 translations.
  2347. //
  2348. if (RecordType == DNS_RECORD_TYPE_AAAA) {
  2349. MatchCount = ClpSearchDnsResultList(NameServer->Value,
  2350. DNS_RECORD_TYPE_AAAA,
  2351. Time,
  2352. TranslationList,
  2353. &NameServerAddressList);
  2354. if (MatchCount != 0) {
  2355. Translation = LIST_VALUE(NameServerAddressList.Previous,
  2356. DNS_RESULT,
  2357. ListEntry);
  2358. memcpy(NameServerAddress,
  2359. &(Translation->Address),
  2360. sizeof(struct sockaddr));
  2361. NameServerAddressIp6 = (struct sockaddr_in6 *)NameServerAddress;
  2362. NameServerAddressIp6->sin6_port = htons(DNS_PORT_NUMBER);
  2363. goto FindNameServerAddressEnd;
  2364. }
  2365. }
  2366. //
  2367. // If no matches were found or weren't tried, try for IPv4
  2368. // translations.
  2369. //
  2370. MatchCount = ClpSearchDnsResultList(NameServer->Value,
  2371. DNS_RECORD_TYPE_A,
  2372. Time,
  2373. TranslationList,
  2374. &NameServerAddressList);
  2375. if (MatchCount != 0) {
  2376. Translation = LIST_VALUE(NameServerAddressList.Previous,
  2377. DNS_RESULT,
  2378. ListEntry);
  2379. memcpy(NameServerAddress,
  2380. &(Translation->Address),
  2381. sizeof(struct sockaddr));
  2382. NameServerAddressIp4 = (struct sockaddr_in *)NameServerAddress;
  2383. NameServerAddressIp4->sin_port = htons(DNS_PORT_NUMBER);
  2384. goto FindNameServerAddressEnd;
  2385. }
  2386. Status = EAI_AGAIN;
  2387. FindNameServerAddressEnd:
  2388. ClpDestroyDnsResultList(&NameServerAddressList);
  2389. return Status;
  2390. }
  2391. INT
  2392. ClpSearchDnsResultList (
  2393. PSTR Name,
  2394. UCHAR RecordType,
  2395. time_t CurrentTime,
  2396. PLIST_ENTRY ListHead,
  2397. PLIST_ENTRY DestinationListHead
  2398. )
  2399. /*++
  2400. Routine Description:
  2401. This routine searches through a DNS result list for a record with the
  2402. given name and record type. Results that qualify will be moved onto the
  2403. destination list.
  2404. Arguments:
  2405. Name - Supplies the name of the record to match against. This is optional.
  2406. RecordType - Supplies the type of record to search for.
  2407. CurrentTime - Supplies the start time of the query. Expiration times
  2408. greater than this will not qualify and be removed and destroyed.
  2409. ListHead - Supplies a pointer to the head of the list to search through.
  2410. DestinationListHead - Supplies a pointer to the list to move qualifying
  2411. results over to.
  2412. Return Value:
  2413. Returns the number of matching results.
  2414. --*/
  2415. {
  2416. PLIST_ENTRY CurrentEntry;
  2417. INT Matches;
  2418. PDNS_RESULT Result;
  2419. Matches = 0;
  2420. CurrentEntry = ListHead->Next;
  2421. while (CurrentEntry != ListHead) {
  2422. Result = LIST_VALUE(CurrentEntry, DNS_RESULT, ListEntry);
  2423. CurrentEntry = CurrentEntry->Next;
  2424. if (Result->Class != DNS_CLASS_INTERNET) {
  2425. continue;
  2426. }
  2427. //
  2428. // Kill expired results.
  2429. //
  2430. if ((CurrentTime > Result->ExpirationTime) &&
  2431. (Result->ExpirationTime != 0)) {
  2432. LIST_REMOVE(&(Result->ListEntry));
  2433. ClpDestroyDnsResult(Result);
  2434. continue;
  2435. }
  2436. if ((Result->Type == RecordType) &&
  2437. ((Name == NULL) || (strcmp(Name, Result->Name) == 0))) {
  2438. Matches += 1;
  2439. LIST_REMOVE(&(Result->ListEntry));
  2440. //
  2441. // Name servers go at the front of the list.
  2442. //
  2443. if ((Result->Type == DNS_RECORD_TYPE_NS) ||
  2444. (Result->Type == DNS_RECORD_TYPE_SOA)) {
  2445. INSERT_AFTER(&(Result->ListEntry), DestinationListHead);
  2446. } else {
  2447. INSERT_BEFORE(&(Result->ListEntry), DestinationListHead);
  2448. }
  2449. }
  2450. }
  2451. return Matches;
  2452. }
  2453. INT
  2454. ClpConvertDnsResultListToAddressInformation (
  2455. PLIST_ENTRY ListHead,
  2456. const struct addrinfo *Hints,
  2457. ULONG Port,
  2458. BOOL MapV4Addresses,
  2459. struct addrinfo **AddressInformation
  2460. )
  2461. /*++
  2462. Routine Description:
  2463. This routine converts a DNS result list into an address information list.
  2464. Arguments:
  2465. ListHead - Supplies a pointer to the head of the list of DNS_RESULT
  2466. structures.
  2467. Hints - Supplies an optional pointer to the hints structure, which governs
  2468. the behavior of the conversion.
  2469. Port - Supplies the service number to fill in.
  2470. MapV4Addresses - Supplies a boolean indicating if IPv4 addresses should be
  2471. mapped to IPv6.
  2472. AddressInformation - Supplies a pointer where a pointer to the address
  2473. information list may be returned. If returned, the caller is
  2474. responsible for freeing this list using the freeaddrinfo function. If
  2475. the hints structure disqualifies this result, then NULL may be returned
  2476. on output as this result is not a candidate for conversion.
  2477. Return Value:
  2478. 0 on success, which may or may not result in a valid address information
  2479. list being returned.
  2480. Returns an EAI_* error code on failure.
  2481. --*/
  2482. {
  2483. struct addrinfo *Base;
  2484. PLIST_ENTRY CurrentEntry;
  2485. struct addrinfo *End;
  2486. BOOL Ip4Ok;
  2487. BOOL Ip6Ok;
  2488. struct addrinfo *NewInformation;
  2489. INT Protocol;
  2490. PDNS_RESULT Result;
  2491. INT SocketType;
  2492. INT Status;
  2493. BOOL WantCanonicalName;
  2494. Base = NULL;
  2495. End = NULL;
  2496. //
  2497. // Convert the optional hints into parameters.
  2498. //
  2499. WantCanonicalName = FALSE;
  2500. if ((Hints != NULL) && ((Hints->ai_flags & AI_CANONNAME) != 0)) {
  2501. WantCanonicalName = TRUE;
  2502. }
  2503. Ip4Ok = TRUE;
  2504. Ip6Ok = TRUE;
  2505. if ((Hints != NULL) && (Hints->ai_family != AF_UNSPEC)) {
  2506. if (Hints->ai_family == AF_INET) {
  2507. Ip6Ok = FALSE;
  2508. } else if (Hints->ai_family == AF_INET6) {
  2509. Ip4Ok = FALSE;
  2510. } else {
  2511. Status = EAI_FAMILY;
  2512. goto ConvertDnsResultListToAddressInformationEnd;
  2513. }
  2514. }
  2515. Protocol = 0;
  2516. if (Hints != NULL) {
  2517. Protocol = Hints->ai_protocol;
  2518. }
  2519. SocketType = 0;
  2520. if (Hints != NULL) {
  2521. SocketType = Hints->ai_socktype;
  2522. }
  2523. CurrentEntry = ListHead->Next;
  2524. while (CurrentEntry != ListHead) {
  2525. Result = LIST_VALUE(CurrentEntry, DNS_RESULT, ListEntry);
  2526. CurrentEntry = CurrentEntry->Next;
  2527. //
  2528. // Skip the entry if it is not an A or AAAA record.
  2529. //
  2530. if ((Result->Class != DNS_CLASS_INTERNET) ||
  2531. ((Result->Type != 0) && (Result->Type != DNS_RECORD_TYPE_A) &&
  2532. (Result->Type != DNS_RECORD_TYPE_AAAA))) {
  2533. continue;
  2534. }
  2535. //
  2536. // Skip the entry if a family was provided.
  2537. //
  2538. if ((Result->Type == DNS_RECORD_TYPE_A) && (Ip4Ok == FALSE)) {
  2539. continue;
  2540. }
  2541. if ((Result->Type == DNS_RECORD_TYPE_AAAA) && (Ip6Ok == FALSE)) {
  2542. continue;
  2543. }
  2544. //
  2545. // Do a translation for the stream socket type.
  2546. //
  2547. if (((SocketType == 0) || (SocketType == SOCK_STREAM)) &&
  2548. ((Protocol == 0) || (Protocol == IPPROTO_TCP))) {
  2549. Status = ClpConvertDnsResultToAddressInformation(Result,
  2550. WantCanonicalName,
  2551. Port,
  2552. &NewInformation);
  2553. if (Status != 0) {
  2554. goto ConvertDnsResultListToAddressInformationEnd;
  2555. }
  2556. NewInformation->ai_socktype = SOCK_STREAM;
  2557. NewInformation->ai_protocol = IPPROTO_TCP;
  2558. if (Base == NULL) {
  2559. Base = NewInformation;
  2560. End = Base;
  2561. } else {
  2562. End->ai_next = NewInformation;
  2563. End = NewInformation;
  2564. }
  2565. }
  2566. //
  2567. // Do another translation for the datagram socket type.
  2568. //
  2569. if (((SocketType == 0) || (SocketType == SOCK_DGRAM)) &&
  2570. ((Protocol == 0) || (Protocol == IPPROTO_UDP))) {
  2571. Status = ClpConvertDnsResultToAddressInformation(Result,
  2572. WantCanonicalName,
  2573. Port,
  2574. &NewInformation);
  2575. if (Status != 0) {
  2576. goto ConvertDnsResultListToAddressInformationEnd;
  2577. }
  2578. NewInformation->ai_socktype = SOCK_DGRAM;
  2579. NewInformation->ai_protocol = IPPROTO_UDP;
  2580. if (Base == NULL) {
  2581. Base = NewInformation;
  2582. End = Base;
  2583. } else {
  2584. End->ai_next = NewInformation;
  2585. End = NewInformation;
  2586. }
  2587. }
  2588. }
  2589. Status = 0;
  2590. if (Base == NULL) {
  2591. Status = EAI_SERVICE;
  2592. }
  2593. ConvertDnsResultListToAddressInformationEnd:
  2594. if (Status != 0) {
  2595. if (Base != NULL) {
  2596. freeaddrinfo(Base);
  2597. }
  2598. }
  2599. *AddressInformation = Base;
  2600. return Status;
  2601. }
  2602. INT
  2603. ClpConvertDnsResultToAddressInformation (
  2604. PDNS_RESULT Result,
  2605. BOOL CopyCanonicalName,
  2606. ULONG Port,
  2607. struct addrinfo **AddressInformation
  2608. )
  2609. /*++
  2610. Routine Description:
  2611. This routine converts a DNS result into an address information structure.
  2612. Arguments:
  2613. Result - Supplies a pointer to the DNS result structure.
  2614. CopyCanonicalName - Supplies a boolean indicating if the caller wants the
  2615. canonical name.
  2616. Port - Supplies the port number to use.
  2617. AddressInformation - Supplies a pointer where a pointer to the address
  2618. information may be returned. If returned, the caller is responsible for
  2619. freeing this memory using the freeaddrinfo function.
  2620. Return Value:
  2621. 0 on success, which may or may not result in a valid address information
  2622. structure being returned.
  2623. Returns an EAI_* error code on failure.
  2624. --*/
  2625. {
  2626. ULONG AllocationSize;
  2627. struct addrinfo *Information;
  2628. struct sockaddr_in *Ip4Address;
  2629. struct sockaddr_in6 *Ip6Address;
  2630. INT Status;
  2631. AllocationSize = sizeof(struct addrinfo) + sizeof(struct sockaddr);
  2632. Information = malloc(AllocationSize);
  2633. if (Information == NULL) {
  2634. Status = EAI_MEMORY;
  2635. goto ConvertDnsResultToAddressInformationEnd;
  2636. }
  2637. memset(Information, 0, AllocationSize);
  2638. Information->ai_family = Result->Address.sa_family;
  2639. if (Information->ai_family == AF_INET) {
  2640. Information->ai_addrlen = sizeof(struct sockaddr_in);
  2641. } else if (Information->ai_family == AF_INET6) {
  2642. Information->ai_addrlen = sizeof(struct sockaddr_in6);
  2643. } else {
  2644. assert(FALSE);
  2645. Status = EAI_FAMILY;
  2646. goto ConvertDnsResultToAddressInformationEnd;
  2647. }
  2648. Information->ai_addr = (struct sockaddr *)(Information + 1);
  2649. memcpy(Information->ai_addr, &(Result->Address), Information->ai_addrlen);
  2650. if (Information->ai_family == AF_INET) {
  2651. Ip4Address = (struct sockaddr_in *)(Information->ai_addr);
  2652. Ip4Address->sin_port = htons(Port);
  2653. } else if (Information->ai_family == AF_INET6) {
  2654. Ip6Address = (struct sockaddr_in6 *)(Information->ai_addr);
  2655. Ip6Address->sin6_port = htons(Port);
  2656. } else {
  2657. assert(FALSE);
  2658. Status = EAI_FAMILY;
  2659. goto ConvertDnsResultToAddressInformationEnd;
  2660. }
  2661. if (CopyCanonicalName != FALSE) {
  2662. assert(Result->Name != NULL);
  2663. Information->ai_canonname = strdup(Result->Name);
  2664. if (Information->ai_canonname == NULL) {
  2665. Status = EAI_MEMORY;
  2666. goto ConvertDnsResultToAddressInformationEnd;
  2667. }
  2668. }
  2669. Status = 0;
  2670. ConvertDnsResultToAddressInformationEnd:
  2671. if (Status != 0) {
  2672. if (Information != NULL) {
  2673. free(Information);
  2674. Information = NULL;
  2675. }
  2676. }
  2677. *AddressInformation = Information;
  2678. return Status;
  2679. }
  2680. INT
  2681. ClpGetAddressInformationPort (
  2682. PSTR ServiceName,
  2683. const struct addrinfo *Hints,
  2684. PULONG Port
  2685. )
  2686. /*++
  2687. Routine Description:
  2688. This routine converts the optional service string into a port number.
  2689. Arguments:
  2690. ServiceName - Supplies the string version of the service. This may be a
  2691. number or a name.
  2692. Hints - Supplies an optional pointer to the hints structure passed into the
  2693. address information request.
  2694. Port - Supplies a pointer where the port will be returned (in host order).
  2695. Return Value:
  2696. 0 on success, which may or may not result in a valid address information
  2697. structure being returned.
  2698. Returns an EAI_* error code on failure.
  2699. --*/
  2700. {
  2701. PSTR AfterScan;
  2702. struct servent *ServiceEntry;
  2703. ULONG Value;
  2704. *Port = 0;
  2705. if (ServiceName == NULL) {
  2706. return 0;
  2707. }
  2708. Value = strtoul(ServiceName, &AfterScan, 0);
  2709. if ((AfterScan != ServiceName) && (Value <= 0xFFFF)) {
  2710. *Port = Value;
  2711. return 0;
  2712. }
  2713. if ((Hints != NULL) && ((Hints->ai_flags & AI_NUMERICSERV) != 0)) {
  2714. return EAI_NONAME;
  2715. }
  2716. ServiceEntry = getservbyname(ServiceName, NULL);
  2717. if (ServiceEntry == NULL) {
  2718. return EAI_SERVICE;
  2719. }
  2720. *Port = ntohs(ServiceEntry->s_port);
  2721. return 0;
  2722. }
  2723. VOID
  2724. ClpDebugPrintAddressInformation (
  2725. struct addrinfo *AddressInformation
  2726. )
  2727. /*++
  2728. Routine Description:
  2729. This routine prints an address information list.
  2730. Arguments:
  2731. AddressInformation - Supplies the address information to print. The next
  2732. pointer will also be followed and printed iteratively.
  2733. Return Value:
  2734. None.
  2735. --*/
  2736. {
  2737. struct sockaddr_in *Ip4Address;
  2738. struct sockaddr_in6 *Ip6Address;
  2739. CHAR PrintBuffer[60];
  2740. while (AddressInformation != NULL) {
  2741. switch (AddressInformation->ai_family) {
  2742. case AF_INET:
  2743. Ip4Address = (struct sockaddr_in *)(AddressInformation->ai_addr);
  2744. assert(Ip4Address->sin_family == AF_INET);
  2745. inet_ntop(Ip4Address->sin_family,
  2746. &(Ip4Address->sin_addr.s_addr),
  2747. PrintBuffer,
  2748. sizeof(PrintBuffer));
  2749. fprintf(stderr, "%s", PrintBuffer);
  2750. break;
  2751. case AF_INET6:
  2752. Ip6Address = (struct sockaddr_in6 *)(AddressInformation->ai_addr);
  2753. assert(Ip6Address->sin6_family == AF_INET6);
  2754. inet_ntop(Ip6Address->sin6_family,
  2755. &(Ip6Address->sin6_addr.s6_addr),
  2756. PrintBuffer,
  2757. sizeof(PrintBuffer));
  2758. fprintf(stderr, "%s", PrintBuffer);
  2759. break;
  2760. default:
  2761. fprintf(stderr,
  2762. "Unknown family %d.\n",
  2763. AddressInformation->ai_family);
  2764. break;
  2765. }
  2766. if (AddressInformation->ai_canonname != NULL) {
  2767. fprintf(stderr, " %s", AddressInformation->ai_canonname);
  2768. }
  2769. fprintf(stderr,
  2770. " Flags %x SockType %d Protocol %d Addrlen %d.\n",
  2771. AddressInformation->ai_flags,
  2772. AddressInformation->ai_socktype,
  2773. AddressInformation->ai_protocol,
  2774. AddressInformation->ai_addrlen);
  2775. AddressInformation = AddressInformation->ai_next;
  2776. }
  2777. return;
  2778. }
  2779. VOID
  2780. ClpFillInLoopbackAddress (
  2781. int AddressFamily,
  2782. struct sockaddr *Address
  2783. )
  2784. /*++
  2785. Routine Description:
  2786. This routine fills in the loopback address.
  2787. Arguments:
  2788. AddressFamily - Supplies the address family.
  2789. Address - Supplies a pointer where the loopback address will be returned.
  2790. Return Value:
  2791. None.
  2792. --*/
  2793. {
  2794. struct sockaddr_in *Ip4Address;
  2795. struct sockaddr_in6 *Ip6Address;
  2796. switch (AddressFamily) {
  2797. case AF_INET:
  2798. Ip4Address = (struct sockaddr_in *)Address;
  2799. Ip4Address->sin_family = AF_INET;
  2800. Ip4Address->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  2801. break;
  2802. case AF_INET6:
  2803. Ip6Address = (struct sockaddr_in6 *)Address;
  2804. Ip6Address->sin6_family = AF_INET6;
  2805. memcpy(&(Ip6Address->sin6_addr),
  2806. &in6addr_loopback,
  2807. sizeof(struct in6_addr));
  2808. break;
  2809. default:
  2810. assert(FALSE);
  2811. break;
  2812. }
  2813. return;
  2814. }
  2815. INT
  2816. ClpGetDnsServers (
  2817. NET_DOMAIN_TYPE Domain,
  2818. struct sockaddr *PrimaryServer,
  2819. PLIST_ENTRY AlternateList
  2820. )
  2821. /*++
  2822. Routine Description:
  2823. This routine gets the known DNS server addresses from the system.
  2824. Arguments:
  2825. Domain - Supplies the network domain to get DNS servers for.
  2826. PrimaryServer - Supplies a pointer where the primary DNS server address
  2827. will be returned on success.
  2828. AlternateList - Supplies a pointer to the head of the list where additional
  2829. name servers will be returned in the form of DNS_RESULT structures
  2830. set to the A or AAAA type.
  2831. Return Value:
  2832. 0 on success.
  2833. Returns an error code on failure.
  2834. --*/
  2835. {
  2836. BOOL AddedOne;
  2837. socklen_t AddressLength;
  2838. PDNS_RESULT Alternate;
  2839. ULONG DeviceCount;
  2840. ULONG DeviceIndex;
  2841. DEVICE_INFORMATION_RESULT *Devices;
  2842. NETWORK_DEVICE_INFORMATION Information;
  2843. PVOID NewBuffer;
  2844. INT Result;
  2845. ULONG ServerIndex;
  2846. UINTN Size;
  2847. KSTATUS Status;
  2848. //
  2849. // Get the array of devices that return network device information.
  2850. //
  2851. DeviceCount = NETWORK_DEVICE_COUNT_ESTIMATE;
  2852. Devices = malloc(sizeof(DEVICE_INFORMATION_RESULT) * DeviceCount);
  2853. if (Devices == NULL) {
  2854. Status = STATUS_INSUFFICIENT_RESOURCES;
  2855. goto GetDnsServersEnd;
  2856. }
  2857. Status = OsLocateDeviceInformation(&ClNetworkDeviceInformationUuid,
  2858. NULL,
  2859. Devices,
  2860. &DeviceCount);
  2861. if (!KSUCCESS(Status)) {
  2862. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2863. DeviceCount += NETWORK_DEVICE_COUNT_ESTIMATE;
  2864. NewBuffer = realloc(
  2865. Devices,
  2866. sizeof(DEVICE_INFORMATION_RESULT) * DeviceCount);
  2867. if (NewBuffer == NULL) {
  2868. Status = STATUS_INSUFFICIENT_RESOURCES;
  2869. goto GetDnsServersEnd;
  2870. }
  2871. NewBuffer = Devices;
  2872. Status = OsLocateDeviceInformation(&ClNetworkDeviceInformationUuid,
  2873. NULL,
  2874. Devices,
  2875. &DeviceCount);
  2876. if (!KSUCCESS(Status)) {
  2877. goto GetDnsServersEnd;
  2878. }
  2879. } else {
  2880. goto GetDnsServersEnd;
  2881. }
  2882. }
  2883. if (DeviceCount == 0) {
  2884. Status = STATUS_NO_NETWORK_CONNECTION;
  2885. goto GetDnsServersEnd;
  2886. }
  2887. //
  2888. // Loop through all the network devices.
  2889. //
  2890. AddedOne = FALSE;
  2891. memset(&Information, 0, sizeof(NETWORK_DEVICE_INFORMATION));
  2892. Information.Version = NETWORK_DEVICE_INFORMATION_VERSION;
  2893. Information.Domain = Domain;
  2894. for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex += 1) {
  2895. Size = sizeof(NETWORK_DEVICE_INFORMATION);
  2896. Status = OsGetSetDeviceInformation(Devices[DeviceIndex].DeviceId,
  2897. &ClNetworkDeviceInformationUuid,
  2898. &Information,
  2899. &Size,
  2900. FALSE);
  2901. if (!KSUCCESS(Status)) {
  2902. continue;
  2903. }
  2904. if (((Information.Flags & NETWORK_DEVICE_FLAG_MEDIA_CONNECTED) == 0) ||
  2905. ((Information.Flags & NETWORK_DEVICE_FLAG_CONFIGURED) == 0)) {
  2906. continue;
  2907. }
  2908. //
  2909. // Loop through every listed server.
  2910. //
  2911. for (ServerIndex = 0;
  2912. ServerIndex < Information.DnsServerCount;
  2913. ServerIndex += 1) {
  2914. Information.DnsServers[ServerIndex].Port = DNS_PORT_NUMBER;
  2915. if (PrimaryServer != NULL) {
  2916. AddressLength = sizeof(struct sockaddr);
  2917. Status = ClConvertFromNetworkAddress(
  2918. &(Information.DnsServers[ServerIndex]),
  2919. PrimaryServer,
  2920. &AddressLength,
  2921. NULL,
  2922. 0);
  2923. if (KSUCCESS(Status)) {
  2924. AddedOne = TRUE;
  2925. PrimaryServer = NULL;
  2926. }
  2927. continue;
  2928. }
  2929. //
  2930. // Add this as an alternate entry.
  2931. //
  2932. Alternate = malloc(sizeof(DNS_RESULT));
  2933. if (Alternate == NULL) {
  2934. continue;
  2935. }
  2936. memset(Alternate, 0, sizeof(DNS_RESULT));
  2937. AddressLength = sizeof(Alternate->Address);
  2938. Status = ClConvertFromNetworkAddress(
  2939. &(Information.DnsServers[ServerIndex]),
  2940. &(Alternate->Address),
  2941. &AddressLength,
  2942. NULL,
  2943. 0);
  2944. if (!KSUCCESS(Status)) {
  2945. free(Alternate);
  2946. continue;
  2947. }
  2948. if (Alternate->Address.sa_family == AF_INET) {
  2949. Alternate->Type = DNS_RECORD_TYPE_A;
  2950. } else if (Alternate->Address.sa_family == AF_INET6) {
  2951. Alternate->Type = DNS_RECORD_TYPE_AAAA;
  2952. } else {
  2953. free(Alternate);
  2954. continue;
  2955. }
  2956. INSERT_BEFORE(&(Alternate->ListEntry), AlternateList);
  2957. AddedOne = TRUE;
  2958. }
  2959. }
  2960. if (AddedOne == FALSE) {
  2961. Status = STATUS_NOT_FOUND;
  2962. goto GetDnsServersEnd;
  2963. }
  2964. Status = STATUS_SUCCESS;
  2965. GetDnsServersEnd:
  2966. if (Devices != NULL) {
  2967. free(Devices);
  2968. }
  2969. Result = 0;
  2970. if (!KSUCCESS(Status)) {
  2971. Result = ClConvertKstatusToErrorNumber(Status);
  2972. }
  2973. return Result;
  2974. }
  2975. INT
  2976. ClpGetNetworkStatus (
  2977. PBOOL Ip4Configured,
  2978. PBOOL Ip6Configured
  2979. )
  2980. /*++
  2981. Routine Description:
  2982. This routine determines whether or not IPv4 and/or IPv6 networks are
  2983. currently configured on the system.
  2984. Arguments:
  2985. Ip4Configured - Supplies a pointer that receives a boolean indicating
  2986. whether or not an IPv4 network is configured on the system.
  2987. Ip6Configured - Supplies a pointer that receives a boolean indicating
  2988. whether or not an IPv6 network is configured on the system.
  2989. Return Value:
  2990. 0 on success.
  2991. Returns an EAI_* error code on failure.
  2992. --*/
  2993. {
  2994. ULONG DeviceCount;
  2995. ULONG DeviceIndex;
  2996. DEVICE_INFORMATION_RESULT *Devices;
  2997. NETWORK_DEVICE_INFORMATION Information;
  2998. PVOID NewBuffer;
  2999. INT Result;
  3000. UINTN Size;
  3001. KSTATUS Status;
  3002. *Ip4Configured = FALSE;
  3003. *Ip6Configured = FALSE;
  3004. //
  3005. // Get the array of devices that return network device information.
  3006. //
  3007. DeviceCount = NETWORK_DEVICE_COUNT_ESTIMATE;
  3008. Devices = malloc(sizeof(DEVICE_INFORMATION_RESULT) * DeviceCount);
  3009. if (Devices == NULL) {
  3010. Status = STATUS_INSUFFICIENT_RESOURCES;
  3011. goto GetNetworkStatusEnd;
  3012. }
  3013. Status = OsLocateDeviceInformation(&ClNetworkDeviceInformationUuid,
  3014. NULL,
  3015. Devices,
  3016. &DeviceCount);
  3017. if (!KSUCCESS(Status)) {
  3018. if (Status == STATUS_BUFFER_TOO_SMALL) {
  3019. DeviceCount += NETWORK_DEVICE_COUNT_ESTIMATE;
  3020. NewBuffer = realloc(
  3021. Devices,
  3022. sizeof(DEVICE_INFORMATION_RESULT) * DeviceCount);
  3023. if (NewBuffer == NULL) {
  3024. Status = STATUS_INSUFFICIENT_RESOURCES;
  3025. goto GetNetworkStatusEnd;
  3026. }
  3027. NewBuffer = Devices;
  3028. Status = OsLocateDeviceInformation(&ClNetworkDeviceInformationUuid,
  3029. NULL,
  3030. Devices,
  3031. &DeviceCount);
  3032. if (!KSUCCESS(Status)) {
  3033. goto GetNetworkStatusEnd;
  3034. }
  3035. } else {
  3036. goto GetNetworkStatusEnd;
  3037. }
  3038. }
  3039. if (DeviceCount == 0) {
  3040. Status = STATUS_NO_NETWORK_CONNECTION;
  3041. goto GetNetworkStatusEnd;
  3042. }
  3043. //
  3044. // Loop through all the network devices and determine if they have IPv4
  3045. // and/or IPv6 networks configured.
  3046. //
  3047. memset(&Information, 0, sizeof(NETWORK_DEVICE_INFORMATION));
  3048. Information.Version = NETWORK_DEVICE_INFORMATION_VERSION;
  3049. Size = sizeof(NETWORK_DEVICE_INFORMATION);
  3050. for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex += 1) {
  3051. Information.Domain = NetDomainIp4;
  3052. Status = OsGetSetDeviceInformation(Devices[DeviceIndex].DeviceId,
  3053. &ClNetworkDeviceInformationUuid,
  3054. &Information,
  3055. &Size,
  3056. FALSE);
  3057. if (KSUCCESS(Status) &&
  3058. ((Information.Flags & NETWORK_DEVICE_FLAG_MEDIA_CONNECTED) != 0) &&
  3059. ((Information.Flags & NETWORK_DEVICE_FLAG_CONFIGURED) != 0)) {
  3060. *Ip4Configured = TRUE;
  3061. }
  3062. Information.Domain = NetDomainIp6;
  3063. Status = OsGetSetDeviceInformation(Devices[DeviceIndex].DeviceId,
  3064. &ClNetworkDeviceInformationUuid,
  3065. &Information,
  3066. &Size,
  3067. FALSE);
  3068. if (KSUCCESS(Status) &&
  3069. ((Information.Flags & NETWORK_DEVICE_FLAG_MEDIA_CONNECTED) != 0) &&
  3070. ((Information.Flags & NETWORK_DEVICE_FLAG_CONFIGURED) != 0)) {
  3071. *Ip6Configured = TRUE;
  3072. }
  3073. if ((*Ip4Configured != FALSE) && (*Ip6Configured != FALSE)) {
  3074. break;
  3075. }
  3076. }
  3077. Status = STATUS_SUCCESS;
  3078. GetNetworkStatusEnd:
  3079. if (Devices != NULL) {
  3080. free(Devices);
  3081. }
  3082. Result = 0;
  3083. if (!KSUCCESS(Status)) {
  3084. Result = ClConvertKstatusToErrorNumber(Status);
  3085. if ((Result == ENOENT) || (Result == ENETDOWN)) {
  3086. Result = EAI_AGAIN;
  3087. } else {
  3088. errno = Result;
  3089. Result = EAI_SYSTEM;
  3090. }
  3091. }
  3092. return Result;
  3093. }
  3094. INT
  3095. ClpGetLocalAddressInformation (
  3096. int AddressFamily,
  3097. PLIST_ENTRY ListHead
  3098. )
  3099. /*++
  3100. Routine Description:
  3101. This routine queries the local host for its address information returning
  3102. them as a set of DNS results.
  3103. Arguments:
  3104. AddressFamily - Supplies the family of addresses to return.
  3105. ListHead - Supplies a pointer to the initialized list head where the local
  3106. address entries will be returned in the form of DNS_RESULT structures
  3107. set to the A or AAAA type.
  3108. Return Value:
  3109. 0 on success.
  3110. Returns an EAI_* error code on failure.
  3111. --*/
  3112. {
  3113. socklen_t AddressLength;
  3114. ULONG DeviceCount;
  3115. ULONG DeviceIndex;
  3116. DEVICE_INFORMATION_RESULT *Devices;
  3117. PDNS_RESULT DnsResult;
  3118. ULONG Flags;
  3119. PSTR FullName;
  3120. NETWORK_DEVICE_INFORMATION Information;
  3121. PVOID NewBuffer;
  3122. INT Result;
  3123. UINTN Size;
  3124. KSTATUS Status;
  3125. DnsResult = NULL;
  3126. FullName = NULL;
  3127. //
  3128. // Get the array of devices that return network device information.
  3129. //
  3130. DeviceCount = NETWORK_DEVICE_COUNT_ESTIMATE;
  3131. Devices = malloc(sizeof(DEVICE_INFORMATION_RESULT) * DeviceCount);
  3132. if (Devices == NULL) {
  3133. Status = STATUS_INSUFFICIENT_RESOURCES;
  3134. goto GetLocalAddressInformationEnd;
  3135. }
  3136. Status = OsLocateDeviceInformation(&ClNetworkDeviceInformationUuid,
  3137. NULL,
  3138. Devices,
  3139. &DeviceCount);
  3140. if (!KSUCCESS(Status)) {
  3141. if (Status == STATUS_BUFFER_TOO_SMALL) {
  3142. DeviceCount += NETWORK_DEVICE_COUNT_ESTIMATE;
  3143. NewBuffer = realloc(
  3144. Devices,
  3145. sizeof(DEVICE_INFORMATION_RESULT) * DeviceCount);
  3146. if (NewBuffer == NULL) {
  3147. Status = STATUS_INSUFFICIENT_RESOURCES;
  3148. goto GetLocalAddressInformationEnd;
  3149. }
  3150. NewBuffer = Devices;
  3151. Status = OsLocateDeviceInformation(&ClNetworkDeviceInformationUuid,
  3152. NULL,
  3153. Devices,
  3154. &DeviceCount);
  3155. if (!KSUCCESS(Status)) {
  3156. goto GetLocalAddressInformationEnd;
  3157. }
  3158. } else {
  3159. goto GetLocalAddressInformationEnd;
  3160. }
  3161. }
  3162. if (DeviceCount == 0) {
  3163. Status = STATUS_NO_NETWORK_CONNECTION;
  3164. goto GetLocalAddressInformationEnd;
  3165. }
  3166. FullName = ClpGetFqdn();
  3167. if (FullName == NULL) {
  3168. Status = STATUS_INSUFFICIENT_RESOURCES;
  3169. goto GetLocalAddressInformationEnd;
  3170. }
  3171. //
  3172. // Loop through all the network devices and get the address information for
  3173. // the request address families.
  3174. //
  3175. memset(&Information, 0, sizeof(NETWORK_DEVICE_INFORMATION));
  3176. Information.Version = NETWORK_DEVICE_INFORMATION_VERSION;
  3177. Size = sizeof(NETWORK_DEVICE_INFORMATION);
  3178. for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex += 1) {
  3179. if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) {
  3180. Information.Domain = NetDomainIp4;
  3181. Status = OsGetSetDeviceInformation(Devices[DeviceIndex].DeviceId,
  3182. &ClNetworkDeviceInformationUuid,
  3183. &Information,
  3184. &Size,
  3185. FALSE);
  3186. Flags = Information.Flags;
  3187. if (KSUCCESS(Status) &&
  3188. ((Flags & NETWORK_DEVICE_FLAG_MEDIA_CONNECTED) != 0) &&
  3189. ((Flags & NETWORK_DEVICE_FLAG_CONFIGURED) != 0)) {
  3190. DnsResult = malloc(sizeof(DNS_RESULT));
  3191. if (DnsResult == NULL) {
  3192. Status = STATUS_INSUFFICIENT_RESOURCES;
  3193. goto GetLocalAddressInformationEnd;
  3194. }
  3195. memset(DnsResult, 0, sizeof(DNS_RESULT));
  3196. AddressLength = sizeof(DnsResult->Address);
  3197. Status = ClConvertFromNetworkAddress(&(Information.Address),
  3198. &(DnsResult->Address),
  3199. &AddressLength,
  3200. NULL,
  3201. 0);
  3202. if (!KSUCCESS(Status)) {
  3203. free(DnsResult);
  3204. } else {
  3205. DnsResult->Type = DNS_RECORD_TYPE_A;
  3206. DnsResult->Class = DNS_CLASS_INTERNET;
  3207. DnsResult->Name = strdup(FullName);
  3208. if (DnsResult->Name == NULL) {
  3209. Status = STATUS_INSUFFICIENT_RESOURCES;
  3210. goto GetLocalAddressInformationEnd;
  3211. }
  3212. INSERT_BEFORE(&(DnsResult->ListEntry), ListHead);
  3213. }
  3214. DnsResult = NULL;
  3215. }
  3216. }
  3217. if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) {
  3218. Information.Domain = NetDomainIp6;
  3219. Status = OsGetSetDeviceInformation(Devices[DeviceIndex].DeviceId,
  3220. &ClNetworkDeviceInformationUuid,
  3221. &Information,
  3222. &Size,
  3223. FALSE);
  3224. Flags = Information.Flags;
  3225. if (KSUCCESS(Status) &&
  3226. ((Flags & NETWORK_DEVICE_FLAG_MEDIA_CONNECTED) != 0) &&
  3227. ((Flags & NETWORK_DEVICE_FLAG_CONFIGURED) != 0)) {
  3228. DnsResult = malloc(sizeof(DNS_RESULT));
  3229. if (DnsResult == NULL) {
  3230. Status = STATUS_INSUFFICIENT_RESOURCES;
  3231. goto GetLocalAddressInformationEnd;
  3232. }
  3233. memset(DnsResult, 0, sizeof(DNS_RESULT));
  3234. AddressLength = sizeof(DnsResult->Address);
  3235. Status = ClConvertFromNetworkAddress(&(Information.Address),
  3236. &(DnsResult->Address),
  3237. &AddressLength,
  3238. NULL,
  3239. 0);
  3240. if (!KSUCCESS(Status)) {
  3241. free(DnsResult);
  3242. } else {
  3243. DnsResult->Type = DNS_RECORD_TYPE_AAAA;
  3244. DnsResult->Class = DNS_CLASS_INTERNET;
  3245. DnsResult->Name = strdup(FullName);
  3246. if (DnsResult->Name == NULL) {
  3247. Status = STATUS_INSUFFICIENT_RESOURCES;
  3248. goto GetLocalAddressInformationEnd;
  3249. }
  3250. INSERT_BEFORE(&(DnsResult->ListEntry), ListHead);
  3251. }
  3252. DnsResult = NULL;
  3253. }
  3254. }
  3255. }
  3256. Status = STATUS_SUCCESS;
  3257. GetLocalAddressInformationEnd:
  3258. if (Devices != NULL) {
  3259. free(Devices);
  3260. }
  3261. if (DnsResult != NULL) {
  3262. free(DnsResult);
  3263. }
  3264. if (FullName != NULL) {
  3265. free(FullName);
  3266. }
  3267. Result = 0;
  3268. if (!KSUCCESS(Status)) {
  3269. ClpDestroyDnsResultList(ListHead);
  3270. Result = ClConvertKstatusToErrorNumber(Status);
  3271. if ((Result == ENOENT) || (Result == ENETDOWN)) {
  3272. Result = EAI_AGAIN;
  3273. } else {
  3274. errno = Result;
  3275. Result = EAI_SYSTEM;
  3276. }
  3277. }
  3278. return Result;
  3279. }
  3280. INT
  3281. ClpIsLocalAddress (
  3282. const struct sockaddr *SocketAddress,
  3283. socklen_t SocketAddressLength,
  3284. PBOOL LocalAddress,
  3285. PBOOL UnspecifiedAddress
  3286. )
  3287. /*++
  3288. Routine Description:
  3289. This routine determines whether or not the given socket address is a local
  3290. address. The unspecified "any address" is included as a local address.
  3291. Arguments:
  3292. SocketAddress - Supplies a pointer to the socket address to be translated.
  3293. This routine does not handle IPv4-mapped IPv6 addresses.
  3294. SocketAddressLength - Supplies the size of the socket address data.
  3295. LocalAddress - Supplies a pointer that receives a boolean indicating
  3296. whether or not the given address is a local address.
  3297. UnspecifiedAddress - Supplies a pointer that receives a boolean indicating
  3298. whether or not the given address is the "local" unspecified address.
  3299. Return Value:
  3300. 0 on success.
  3301. Returns an EAI_* error code on failure.
  3302. --*/
  3303. {
  3304. PLIST_ENTRY CurrentEntry;
  3305. PDNS_RESULT DnsResult;
  3306. struct sockaddr_in *Ip4Address;
  3307. struct sockaddr_in6 *Ip6Address;
  3308. LIST_ENTRY ListHead;
  3309. struct sockaddr_in *ResultIp4Address;
  3310. struct sockaddr_in6 *ResultIp6Address;
  3311. INT Status;
  3312. INITIALIZE_LIST_HEAD(&ListHead);
  3313. *LocalAddress = FALSE;
  3314. *UnspecifiedAddress = FALSE;
  3315. if (SocketAddressLength < sizeof(struct sockaddr_in)) {
  3316. Status = EAI_FAIL;
  3317. goto IsLocalAddressEnd;
  3318. }
  3319. //
  3320. // Check for the unspecified address, loopback address, and node local
  3321. // addresses based on the supplied family.
  3322. //
  3323. switch (SocketAddress->sa_family) {
  3324. case AF_INET:
  3325. Ip4Address = (struct sockaddr_in *)SocketAddress;
  3326. if (Ip4Address->sin_addr.s_addr == htonl(INADDR_ANY)) {
  3327. *UnspecifiedAddress = TRUE;
  3328. *LocalAddress = TRUE;
  3329. } else if (Ip4Address->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
  3330. *LocalAddress = TRUE;
  3331. } else {
  3332. INITIALIZE_LIST_HEAD(&ListHead);
  3333. Status = ClpGetLocalAddressInformation(AF_INET, &ListHead);
  3334. if (Status != 0) {
  3335. goto IsLocalAddressEnd;
  3336. }
  3337. CurrentEntry = ListHead.Next;
  3338. while (CurrentEntry != &ListHead) {
  3339. DnsResult = LIST_VALUE(CurrentEntry, DNS_RESULT, ListEntry);
  3340. CurrentEntry = CurrentEntry->Next;
  3341. ResultIp4Address = (struct sockaddr_in *)&(DnsResult->Address);
  3342. if (ResultIp4Address->sin_addr.s_addr ==
  3343. Ip4Address->sin_addr.s_addr) {
  3344. *LocalAddress = TRUE;
  3345. break;
  3346. }
  3347. }
  3348. }
  3349. break;
  3350. case AF_INET6:
  3351. Ip6Address = (struct sockaddr_in6 *)SocketAddress;
  3352. if (IN6_IS_ADDR_UNSPECIFIED(&(Ip6Address->sin6_addr)) != FALSE) {
  3353. *UnspecifiedAddress = TRUE;
  3354. *LocalAddress = TRUE;
  3355. } else if (IN6_IS_ADDR_LOOPBACK(&(Ip6Address->sin6_addr)) != FALSE) {
  3356. *LocalAddress = TRUE;
  3357. } else {
  3358. Status = ClpGetLocalAddressInformation(AF_INET6, &ListHead);
  3359. if (Status != 0) {
  3360. goto IsLocalAddressEnd;
  3361. }
  3362. CurrentEntry = ListHead.Next;
  3363. while (CurrentEntry != &ListHead) {
  3364. DnsResult = LIST_VALUE(CurrentEntry, DNS_RESULT, ListEntry);
  3365. CurrentEntry = CurrentEntry->Next;
  3366. ResultIp6Address = (struct sockaddr_in6 *)&(DnsResult->Address);
  3367. if (memcmp(&(ResultIp6Address->sin6_addr.s6_addr),
  3368. &(Ip6Address->sin6_addr.s6_addr),
  3369. sizeof(struct in6_addr)) == 0) {
  3370. *LocalAddress = TRUE;
  3371. break;
  3372. }
  3373. }
  3374. }
  3375. break;
  3376. default:
  3377. Status = EAI_ADDRFAMILY;
  3378. goto IsLocalAddressEnd;
  3379. }
  3380. Status = 0;
  3381. IsLocalAddressEnd:
  3382. ClpDestroyDnsResultList(&ListHead);
  3383. return Status;
  3384. }
  3385. BOOL
  3386. ClpIsNameSubdomain (
  3387. PCSTR Query,
  3388. PCSTR Domain
  3389. )
  3390. /*++
  3391. Routine Description:
  3392. This routine determines if the given name is a subdomain of the given
  3393. domain.
  3394. Arguments:
  3395. Query - Supplies the name in question.
  3396. Domain - Supplies the domain to match against.
  3397. Return Value:
  3398. TRUE if the query is a subdomain of the given domain.
  3399. FALSE if it is not.
  3400. --*/
  3401. {
  3402. size_t DomainLength;
  3403. size_t QueryLength;
  3404. QueryLength = strlen(Query);
  3405. DomainLength = strlen(Domain);
  3406. if (QueryLength < DomainLength) {
  3407. return FALSE;
  3408. }
  3409. if (strcmp(Query + QueryLength - DomainLength, Domain) == 0) {
  3410. return TRUE;
  3411. }
  3412. return FALSE;
  3413. }