netdb.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. {$mode objfpc}
  2. {$h+}
  3. unit netdb;
  4. Interface
  5. {$i hsh.inc} // disappears if part of resolve.pp !!
  6. Const
  7. DNSPort = 53;
  8. MaxServers = 4;
  9. MaxResolveAddr = 10;
  10. SResolveFile = '/etc/resolv.conf';
  11. SServicesFile = '/etc/services';
  12. SHostsFile = '/etc/hosts';
  13. SNetworksFile = '/etc/networks';
  14. Type
  15. TDNSServerArray = Array[1..MaxServers] of THostAddr;
  16. TServiceEntry = record
  17. Name : String;
  18. Protocol : String;
  19. Port : Word;
  20. Aliases : String;
  21. end;
  22. THostEntry = record
  23. Name : String;
  24. Addr : THostAddr;
  25. Aliases : String;
  26. end;
  27. TNetworkEntry = Record
  28. Name : String;
  29. Addr : TNetAddr;
  30. Aliases : String;
  31. end;
  32. Var
  33. DNSServers : TDNSServerArray;
  34. DNSServerCount : Integer;
  35. DefaultDomainList : String;
  36. CheckResolveFileAge : Boolean;
  37. TimeOutS,TimeOutMS : Longint;
  38. Function GetDNSServers(FN : String) : Integer;
  39. Function ResolveName(HostName : String; Var Addresses : Array of THostAddr) : Integer;
  40. Function ResolveAddress(HostAddr : THostAddr; Var Addresses : Array of String) : Integer;
  41. Function ResolveHostByName(HostName : String; Var H : THostEntry) : Boolean;
  42. Function ResolveHostByAddr(HostAddr : THostAddr; Var H : THostEntry) : Boolean;
  43. Function GetHostByName(HostName: String; Var H : THostEntry) : boolean;
  44. Function GetHostByAddr(Addr: THostAddr; Var H : THostEntry) : boolean;
  45. Function GetNetworkByName(NetName: String; Var N : TNetworkEntry) : boolean;
  46. Function GetNetworkByAddr(Addr: THostAddr; Var N : TNetworkEntry) : boolean;
  47. Function GetServiceByName(Const Name,Proto : String; Var E : TServiceEntry) : Boolean;
  48. Function GetServiceByPort(Port : Word;Const Proto : String; Var E : TServiceEntry) : Boolean;
  49. Implementation
  50. uses
  51. {$ifdef VER1_0}
  52. Linux,
  53. {$else}
  54. Unix,
  55. {$endif}
  56. sockets,sysutils;
  57. {$i hs.inc}
  58. const
  59. DNSQRY_A = 1; // name to IP address
  60. DNSQRY_AAAA = 28; // name to IP6 address
  61. DNSQRY_PTR = 12; // IP address to name
  62. DNSQRY_MX = 15; // name to MX
  63. DNSQRY_TXT = 16; // name to TXT
  64. // Flags 1
  65. QF_QR = $80;
  66. QF_OPCODE = $78;
  67. QF_AA = $04;
  68. QF_TC = $02; // Truncated.
  69. QF_RD = $01;
  70. // Flags 2
  71. QF_RA = $80;
  72. QF_Z = $70;
  73. QF_RCODE = $0F;
  74. Type
  75. TPayLoad = Array[0..511] of char;
  76. TQueryData = packed Record
  77. id : Array[0..1] of Byte;
  78. flags1 : Byte;
  79. flags2 : Byte;
  80. qdcount : word;
  81. ancount : word;
  82. nscount : word;
  83. arcount : word;
  84. Payload : TPayLoad;
  85. end;
  86. TRRData = Packed record // RR record
  87. Atype : Word; // Answer type
  88. AClass : Word;
  89. TTL : Cardinal;
  90. RDLength : Word;
  91. end;
  92. Var
  93. ResolveFileAge : Longint;
  94. ResolveFileName : String;
  95. { ---------------------------------------------------------------------
  96. Auxiliary functions.
  97. ---------------------------------------------------------------------}
  98. Function htons(var W : Word) : word;
  99. begin
  100. w:=Swap(w);
  101. Result:=W;
  102. end;
  103. Function ntohs(var W : Word) : Word;
  104. begin
  105. w:=Swap(w);
  106. Result:=W;
  107. end;
  108. { ---------------------------------------------------------------------
  109. Resolve.conf handling
  110. ---------------------------------------------------------------------}
  111. Function GetDNSServers(Fn : String) : Integer;
  112. Var
  113. R : Text;
  114. L : String;
  115. I : Integer;
  116. H : THostAddr;
  117. Function CheckDirective(Dir : String) : Boolean;
  118. Var
  119. P : Integer;
  120. begin
  121. P:=Pos(Dir,L);
  122. Result:=(P<>0);
  123. If Result then
  124. begin
  125. Delete(L,1,P+Length(Dir));
  126. Trim(L);
  127. end;
  128. end;
  129. begin
  130. Result:=0;
  131. ResolveFileName:=Fn;
  132. ResolveFileAge:=FileAge(FN);
  133. {$i-}
  134. Assign(R,FN);
  135. Reset(R);
  136. {$i+}
  137. If (IOResult<>0) then
  138. exit;
  139. Try
  140. While not EOF(R) do
  141. begin
  142. Readln(R,L);
  143. I:=Pos('#',L);
  144. If (I<>0) then
  145. L:=Copy(L,1,I-1);
  146. If CheckDirective('nameserver') then
  147. begin
  148. H:=HostToNet(StrToHostAddr(L));
  149. If (H[1]<>0) then
  150. begin
  151. Inc(Result);
  152. DNSServers[Result]:=H;
  153. end;
  154. end
  155. else if CheckDirective('domain') then
  156. DefaultDomainList:=L
  157. else if CheckDirective('search') then
  158. DefaultDomainList:=L;
  159. end;
  160. Finally
  161. Close(R);
  162. end;
  163. DNSServerCount:=Result;
  164. end;
  165. Procedure CheckResolveFile;
  166. Var
  167. F : Integer;
  168. begin
  169. If CheckResolveFileAge then
  170. begin
  171. F:=FileAge(ResolveFileName);
  172. If ResolveFileAge<F then
  173. GetDnsServers(ResolveFileName);
  174. end;
  175. end;
  176. { ---------------------------------------------------------------------
  177. Payload handling functions.
  178. ---------------------------------------------------------------------}
  179. Procedure DumpPayLoad(Q : TQueryData; L : Integer);
  180. Var
  181. i : Integer;
  182. begin
  183. Writeln('Payload : ',l);
  184. For I:=0 to L-1 do
  185. Write(Byte(Q.Payload[i]),' ');
  186. Writeln;
  187. end;
  188. Function BuildPayLoad(Var Q : TQueryData; Name : String; RR : Word; QClass : Word) : Integer;
  189. Var
  190. P : PByte;
  191. l,S : Integer;
  192. begin
  193. Result:=-1;
  194. If length(Name)>506 then
  195. Exit;
  196. Result:=0;
  197. P:[email protected];
  198. Repeat
  199. L:=Pos('.',Name);
  200. If (L=0) then
  201. S:=Length(Name)
  202. else
  203. S:=L-1;
  204. P[Result]:=S;
  205. Move(Name[1],P[Result+1],S);
  206. Inc(Result,S+1);
  207. If (L>0) then
  208. Delete(Name,1,L);
  209. Until (L=0);
  210. P[Result]:=0;
  211. htons(rr);
  212. Move(rr,P[Result+1],2);
  213. Inc(Result,3);
  214. htons(QClass);
  215. Move(qclass,P[Result],2);
  216. Inc(Result,2);
  217. end;
  218. Function NextRR(Const PayLoad : TPayLoad;Var Start : LongInt; AnsLen : LongInt; Var RR : TRRData) : Boolean;
  219. Var
  220. I : Integer;
  221. HaveName : Boolean;
  222. PA : ^TRRData;
  223. RClass,RType : Word;
  224. begin
  225. Result:=False;
  226. I:=Start;
  227. // Skip labels and pointers. At least 1 label or pointer is present.
  228. Repeat
  229. HaveName:=True;
  230. If (Payload[i]>#63) then // Pointer, skip
  231. Inc(I,2)
  232. else If Payload[i]=#0 then // Null termination of label, skip.
  233. Inc(i)
  234. else
  235. begin
  236. Inc(I,Ord(Payload[i])+1); // Label, continue scan.
  237. HaveName:=False;
  238. end;
  239. Until HaveName or (I>(AnsLen-SizeOf(TRRData)));
  240. Result:=(I<=(AnsLen-SizeOf(TRRData)));
  241. // Check RR record.
  242. PA:=@Payload[i];
  243. RR:=PA^;
  244. Start:=I+SizeOf(TRRData);
  245. end;
  246. Function BuildName (Const PayLoad : TPayLoad; Start,len : Integer) : String;
  247. Const
  248. FIREDNS_POINTER_VALUE = $C000;
  249. Var
  250. I,O : Integer;
  251. P : Word;
  252. begin
  253. SetLength(Result,512);
  254. I:=Start;
  255. O:=1;
  256. // Copy labels and pointers. At least 1 label or pointer is present.
  257. Repeat
  258. If (Payload[i]>#63) then // Pointer, move.
  259. begin
  260. Move(Payload[i],P,2);
  261. I:=ntohs(p)-FIREDNS_POINTER_VALUE-12;
  262. end
  263. else if Payload[i]<>#0 then // Label, copy
  264. begin
  265. If O<>1 then
  266. begin
  267. Result[O]:='.';
  268. Inc(O);
  269. end;
  270. P:=Ord(Payload[i]);
  271. Move(Payload[i+1],Result[o],P);
  272. Inc(I,P+1);
  273. Inc(O,P);
  274. end;
  275. Until (Payload[I]=#0);
  276. end;
  277. { ---------------------------------------------------------------------
  278. QueryData handling functions
  279. ---------------------------------------------------------------------}
  280. Function CheckAnswer(Const Qry : TQueryData; Var Ans : TQueryData) : Boolean;
  281. begin
  282. Result:=False;
  283. With Ans do
  284. begin
  285. // Check ID.
  286. If (ID[1]<>QRY.ID[1]) or (ID[0]<>Qry.ID[0]) then
  287. exit;
  288. // Flags ?
  289. If (Flags1 and QF_QR)=0 then
  290. exit;
  291. if (Flags1 and QF_OPCODE)<>0 then
  292. exit;
  293. if (Flags2 and QF_RCODE)<>0 then
  294. exit;
  295. // Number of answers ?
  296. htons(Ancount);
  297. If Ancount<1 then
  298. Exit;
  299. Result:=True;
  300. end;
  301. end;
  302. Function SkipAnsQueries(Var Ans : TQueryData; L : Integer) : integer;
  303. Var
  304. Q,I : Integer;
  305. begin
  306. Result:=0;
  307. With Ans do
  308. begin
  309. htons(qdcount);
  310. i:=0;
  311. q:=0;
  312. While (Q<qdcount) and (i<l) do
  313. begin
  314. If Ord(Payload[i])>63 then
  315. begin
  316. Inc(I,6);
  317. Inc(Q);
  318. end
  319. else
  320. begin
  321. If Payload[i]=#0 then
  322. begin
  323. inc(q);
  324. Inc(I,5);
  325. end
  326. else
  327. Inc(I,Ord(Payload[i])+1);
  328. end;
  329. end;
  330. Result:=I;
  331. end;
  332. end;
  333. { ---------------------------------------------------------------------
  334. DNS Query functions.
  335. ---------------------------------------------------------------------}
  336. Function Query(Resolver : Integer; Var Qry,Ans : TQueryData; QryLen : Integer; Var AnsLen : Integer) : Boolean;
  337. Var
  338. BA,SA : TInetSockAddr;
  339. Sock,L,I : Longint;
  340. Al,RTO : Longint;
  341. ReadFDS : FDSet;
  342. begin
  343. Result:=False;
  344. With Qry do
  345. begin
  346. ID[0]:=Random(256);
  347. ID[1]:=Random(256);
  348. Flags1:=QF_RD;
  349. Flags2:=0;
  350. qdcount:=1 shl 8;
  351. ancount:=0;
  352. nscount:=0;
  353. arcount:=0;
  354. end;
  355. Sock:=Socket(PF_INET,SOCK_DGRAM,0);
  356. If Sock=-1 then
  357. exit;
  358. With SA do
  359. begin
  360. family:=AF_INET;
  361. port:=DNSport;
  362. htons(port);
  363. addr:=cardinal(HostToNet(DNSServers[Resolver]));
  364. end;
  365. sendto(sock,qry,qrylen+12,0,SA,SizeOf(SA));
  366. // Wait for answer.
  367. RTO:=TimeOutS*1000+TimeOutMS;
  368. FD_ZERO(ReadFDS);
  369. FD_Set(Sock,readfds);
  370. if Select(Sock+1,@readfds,Nil,Nil,RTO)<=0 then
  371. begin
  372. fdclose(Sock);
  373. exit;
  374. end;
  375. AL:=SizeOf(SA);
  376. L:=recvfrom(Sock,ans,SizeOf(Ans),0,SA,AL);
  377. fdclose(Sock);
  378. // Check lenght answer and fields in header data.
  379. If (L<12) or not CheckAnswer(Qry,Ans) Then
  380. exit;
  381. // Return Payload length.
  382. Anslen:=L-12;
  383. Result:=True;
  384. end;
  385. Function ResolveNameAt(Resolver : Integer; HostName : String; Var Addresses : Array of THostAddr) : Integer;
  386. Var
  387. Qry, Ans : TQueryData;
  388. MaxAnswer,I,QryLen,
  389. AnsLen,AnsStart : Longint;
  390. RR : TRRData;
  391. begin
  392. Result:=0;
  393. QryLen:=BuildPayLoad(Qry,HostName,DNSQRY_A,1);
  394. If Not Query(Resolver,Qry,Ans,QryLen,AnsLen) then
  395. Result:=-1
  396. else
  397. begin
  398. AnsStart:=SkipAnsQueries(Ans,AnsLen);
  399. MaxAnswer:=Ans.AnCount-1;
  400. If MaxAnswer>High(Addresses) then
  401. MaxAnswer:=High(Addresses);
  402. I:=0;
  403. While (I<=MaxAnswer) and NextRR(Ans.Payload,AnsStart,AnsLen,RR) do
  404. begin
  405. if (Ntohs(RR.AType)=DNSQRY_A) and (1=NtoHS(RR.AClass)) then
  406. begin
  407. Move(Ans.PayLoad[AnsStart],Addresses[i],SizeOf(THostAddr));
  408. inc(Result);
  409. Inc(AnsStart,RR.RDLength);
  410. end;
  411. Inc(I);
  412. end;
  413. end;
  414. end;
  415. Function ResolveName(HostName : String; Var Addresses : Array of THostAddr) : Integer;
  416. Var
  417. I : Integer;
  418. begin
  419. CheckResolveFile;
  420. I:=1;
  421. Result:=0;
  422. While (Result=0) and (I<=DNSServerCount) do
  423. begin
  424. Result:=ResolveNameAt(I,HostName,Addresses);
  425. Inc(I);
  426. end;
  427. end;
  428. Function ResolveAddressAt(Resolver : Integer; Address : String; Var Names : Array of String) : Integer;
  429. Var
  430. Qry, Ans : TQueryData;
  431. MaxAnswer,I,QryLen,
  432. AnsLen,AnsStart : Longint;
  433. RR : TRRData;
  434. S : String;
  435. begin
  436. Result:=0;
  437. QryLen:=BuildPayLoad(Qry,Address,DNSQRY_PTR,1);
  438. If Not Query(Resolver,Qry,Ans,QryLen,AnsLen) then
  439. Result:=-1
  440. else
  441. begin
  442. AnsStart:=SkipAnsQueries(Ans,AnsLen);
  443. MaxAnswer:=Ans.AnCount-1;
  444. If MaxAnswer>High(Names) then
  445. MaxAnswer:=High(Names);
  446. I:=0;
  447. While (I<=MaxAnswer) and NextRR(Ans.Payload,AnsStart,AnsLen,RR) do
  448. begin
  449. if (Ntohs(RR.AType)=DNSQRY_PTR) and (1=NtoHS(RR.AClass)) then
  450. begin
  451. Names[i]:=BuildName(Ans.Payload,AnsStart,AnsLen);
  452. inc(Result);
  453. Inc(AnsStart,RR.RDLength);
  454. end;
  455. Inc(I);
  456. end;
  457. end;
  458. end;
  459. Function ResolveAddress(HostAddr : THostAddr; Var Addresses : Array of String) : Integer;
  460. Var
  461. I : Integer;
  462. S : String;
  463. begin
  464. CheckResolveFile;
  465. I:=1;
  466. Result:=0;
  467. S:=Format('%d.%d.%d.%d.in-addr.arpa',[HostAddr[4],HostAddr[3],HostAddr[2],HostAddr[1]]);
  468. While (Result=0) and (I<=DNSServerCount) do
  469. begin
  470. Result:=ResolveAddressAt(I,S,Addresses);
  471. Inc(I);
  472. end;
  473. end;
  474. Function ResolveHostByName(HostName : String; Var H : THostEntry) : Boolean;
  475. Var
  476. Address : Array[1..MaxResolveAddr] of THostAddr;
  477. L : Integer;
  478. begin
  479. L:=ResolveName(HostName,Address);
  480. Result:=(L>0);
  481. If Result then
  482. begin
  483. // We could add a reverse call here to get the real name and aliases.
  484. H.Name:=HostName;
  485. H.Addr:=Address[1];
  486. H.aliases:='';
  487. end;
  488. end;
  489. Function ResolveHostByAddr(HostAddr : THostAddr; Var H : THostEntry) : Boolean;
  490. Var
  491. Names : Array[1..MaxResolveAddr] of String;
  492. I,L : Integer;
  493. begin
  494. L:=ResolveAddress(HostAddr,Names);
  495. Result:=(L>0);
  496. If Result then
  497. begin
  498. H.Name:=Names[1];
  499. H.Addr:=HostAddr;
  500. H.Aliases:='';
  501. If (L>1) then
  502. For I:=2 to L do
  503. If (I=2) then
  504. H.Aliases:=Names[i]
  505. else
  506. H.Aliases:=H.Aliases+','+Names[i];
  507. end;
  508. end;
  509. { ---------------------------------------------------------------------
  510. Some Parsing routines
  511. ---------------------------------------------------------------------}
  512. Const
  513. Whitespace = [' ',#9];
  514. Function NextWord(Var Line : String) : String;
  515. Var
  516. I,J : Integer;
  517. begin
  518. I:=1;
  519. While (I<=Length(Line)) and (Line[i] in Whitespace) do
  520. inc(I);
  521. J:=I;
  522. While (J<=Length(Line)) and Not (Line[J] in WhiteSpace) do
  523. inc(j);
  524. Result:=Copy(Line,I,J-1);
  525. Delete(Line,1,J);
  526. end;
  527. Procedure StripComment(Var line : String);
  528. Var
  529. P : Integer;
  530. begin
  531. P:=Pos('#',Line);
  532. If (P<>0) then
  533. Line:=Trim(Copy(Line,1,P-1));
  534. end;
  535. Function MatchNameOrAlias(Const Entry,Name: String; Aliases : String) : Boolean;
  536. Var
  537. P : Integer;
  538. A : String;
  539. begin
  540. Result:=CompareText(Entry,Name)=0;
  541. If Not Result then
  542. While (Not Result) and (Length(Aliases)>0) do
  543. begin
  544. P:=Pos(',',Aliases);
  545. If (P=0) then
  546. P:=Length(Aliases)+1;
  547. A:=Copy(Aliases,1,P-1);
  548. Delete(Aliases,1,P);
  549. Result:=CompareText(A,Entry)=0;
  550. end;
  551. end;
  552. { ---------------------------------------------------------------------
  553. /etc/hosts handling.
  554. ---------------------------------------------------------------------}
  555. Function GetNextHostEntry(var F : Text; Var H : THostEntry): boolean;
  556. Var
  557. Line,S : String;
  558. P : Integer;
  559. begin
  560. Result:=False;
  561. Repeat
  562. ReadLn(F,Line);
  563. StripComment(Line);
  564. S:=NextWord(Line);
  565. If (S<>'') then
  566. begin
  567. H.Addr:=StrToHostAddr(S);
  568. if (H.Addr[1]<>0) then
  569. begin
  570. S:=NextWord(Line);
  571. If (S<>'') then
  572. begin
  573. H.Name:=S;
  574. Result:=True;
  575. H.Aliases:='';
  576. Repeat
  577. S:=NextWord(line);
  578. If (S<>'') then
  579. If (H.Aliases='') then
  580. H.Aliases:=S
  581. else
  582. H.Aliases:=H.Aliases+','+S;
  583. until (S='');
  584. end;
  585. end;
  586. end;
  587. until Result or EOF(F);
  588. end;
  589. Function FindHostEntryInHostsFile(N: String; Addr: THostAddr; Var H : THostEntry) : boolean;
  590. Var
  591. F : Text;
  592. HE : THostEntry;
  593. begin
  594. Result:=False;
  595. If FileExists(SHostsFile) then
  596. begin
  597. Assign(F,SHostsFile);
  598. {$i-}
  599. Reset(F);
  600. {$i+}
  601. If (IOResult=0) then
  602. begin
  603. While Not Result and GetNextHostEntry(F,HE) do
  604. begin
  605. If (N<>'') then
  606. Result:=MatchNameOrAlias(N,HE.Name,HE.Aliases)
  607. else
  608. Result:=Cardinal(Addr)=Cardinal(HE.Addr);
  609. end;
  610. Close(f);
  611. If Result then
  612. begin
  613. H.Name:=HE.Name;
  614. H.Addr:=HE.Addr;
  615. H.Aliases:=HE.Aliases;
  616. end;
  617. end;
  618. end;
  619. end;
  620. Function GetHostByName(HostName: String; Var H : THostEntry) : boolean;
  621. begin
  622. Result:=FindHostEntryInHostsFile(HostName,NoAddress,H);
  623. end;
  624. Function GetHostByAddr(Addr: THostAddr; Var H : THostEntry) : boolean;
  625. begin
  626. Result:=FindHostEntryInHostsFile('',Addr,H);
  627. end;
  628. { ---------------------------------------------------------------------
  629. /etc/networks handling
  630. ---------------------------------------------------------------------}
  631. Function GetNextNetworkEntry(var F : Text; Var N : TNetworkEntry): boolean;
  632. Var
  633. NN,Line,S : String;
  634. P : Integer;
  635. A : TNetAddr;
  636. begin
  637. Result:=False;
  638. Repeat
  639. ReadLn(F,Line);
  640. StripComment(Line);
  641. S:=NextWord(Line);
  642. If (S<>'') then
  643. begin
  644. NN:=S;
  645. A:=StrToHostAddr(NextWord(Line));
  646. Result:=(NN<>'') and (A[1]<>0); // Valid addr.
  647. If result then
  648. begin
  649. N.Addr:=A;
  650. N.Name:=NN;
  651. N.Aliases:='';
  652. end;
  653. end;
  654. until Result or EOF(F);
  655. end;
  656. Function FindNetworkEntryInNetworksFile(Net: String; Addr: TNetAddr; Var N : TNetworkEntry) : boolean;
  657. Var
  658. F : Text;
  659. NE : TNetworkEntry;
  660. begin
  661. Result:=False;
  662. If FileExists(SNetworksFile) then
  663. begin
  664. Assign(F,SNetworksFile);
  665. {$i-}
  666. Reset(F);
  667. {$i+}
  668. If (IOResult=0) then
  669. begin
  670. While Not Result and GetNextNetworkEntry(F,NE) do
  671. begin
  672. If (Net<>'') then
  673. Result:=MatchNameOrAlias(Net,NE.Name,NE.Aliases)
  674. else
  675. Result:=Cardinal(Addr)=Cardinal(NE.Addr);
  676. end;
  677. Close(f);
  678. If Result then
  679. begin
  680. N.Name:=NE.Name;
  681. N.Addr:=NE.Addr;
  682. N.Aliases:=NE.Aliases;
  683. end;
  684. end;
  685. end;
  686. end;
  687. Function GetNetworkByName(NetName: String; Var N : TNetworkEntry) : boolean;
  688. begin
  689. Result:=FindNetworkEntryInNetworksFile(NetName,NoNet,N);
  690. end;
  691. Function GetNetworkByAddr(Addr: THostAddr; Var N : TNetworkEntry) : boolean;
  692. begin
  693. Result:=FindNetworkEntryInNetworksFile('',Addr,N);
  694. end;
  695. { ---------------------------------------------------------------------
  696. /etc/services section
  697. ---------------------------------------------------------------------}
  698. Function GetNextServiceEntry(Var F : Text; Var E : TServiceEntry) : Boolean;
  699. Var
  700. Line,S : String;
  701. P : INteger;
  702. begin
  703. Result:=False;
  704. Repeat
  705. ReadLn(F,Line);
  706. StripComment(Line);
  707. S:=NextWord(Line);
  708. If (S<>'') then
  709. begin
  710. E.Name:=S;
  711. S:=NextWord(Line);
  712. P:=Pos('/',S);
  713. If (P<>0) then
  714. begin
  715. E.Port:=StrToIntDef(Copy(S,1,P-1),0);
  716. If (E.Port<>0) then
  717. begin
  718. E.Protocol:=Copy(S,P+1,Length(S)-P);
  719. Result:=length(E.Protocol)>0;
  720. E.Aliases:='';
  721. Repeat
  722. S:=NextWord(Line);
  723. If (S<>'') then
  724. If (Length(E.Aliases)=0) then
  725. E.aliases:=S
  726. else
  727. E.Aliases:=E.Aliases+','+S;
  728. until (S='');
  729. end;
  730. end;
  731. end;
  732. until Result or EOF(F);
  733. end;
  734. Function FindServiceEntryInFile(Const Name,Proto : String; Port : Integer; Var E : TServiceEntry) : Boolean;
  735. Var
  736. F : Text;
  737. TE : TServiceEntry;
  738. begin
  739. Result:=False;
  740. If FileExists(SServicesFile) then
  741. begin
  742. Assign(F,SServicesFile);
  743. {$i-}
  744. Reset(F);
  745. {$i+}
  746. If (IOResult=0) then
  747. begin
  748. While Not Result and GetNextServiceEntry(F,TE) do
  749. begin
  750. If (Port=-1) then
  751. Result:=MatchNameOrAlias(Name,TE.Name,TE.Aliases)
  752. else
  753. Result:=(Port=TE.Port);
  754. If Result and (Proto<>'') then
  755. Result:=(Proto=TE.Protocol);
  756. end;
  757. Close(f);
  758. If Result then
  759. begin
  760. E.Name:=TE.Name;
  761. E.Port:=TE.Port;
  762. E.Protocol:=TE.Protocol;
  763. E.Aliases:=TE.Aliases;
  764. end;
  765. end;
  766. end;
  767. end;
  768. Function GetServiceByName(Const Name,Proto : String; Var E : TServiceEntry) : Boolean;
  769. begin
  770. Result:=FindServiceEntryInFile(Name,Proto,-1,E);
  771. end;
  772. Function GetServiceByPort(Port : Word;Const Proto : String; Var E : TServiceEntry) : Boolean;
  773. begin
  774. Result:=FindServiceEntryInFile('',Proto,Port,E);
  775. end;
  776. { ---------------------------------------------------------------------
  777. Initialization section
  778. ---------------------------------------------------------------------}
  779. Procedure InitResolver;
  780. Var
  781. I : Integer;
  782. begin
  783. TimeOutS :=5;
  784. TimeOutMS:=0;
  785. CheckResolveFileAge:=False;
  786. If FileExists(SResolveFile) then
  787. GetDNsservers(SResolveFile);
  788. end;
  789. begin
  790. InitResolver;
  791. end.