netdb.pp 20 KB

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