Hi, Before I start working on bug 2861 I'd like you to take attached patch which cleans up netdb, adds ability to do ipv4/6 mapped address resolving and clears up some other issues.
johannes -- http://www.sipsolutions.de/ Key-ID: 9AB78CA5 Johannes Martin Berg <[EMAIL PROTECTED]>
Index: netdb.pp
===================================================================
RCS file: /FPC/CVS/fpc/packages/base/netdb/netdb.pp,v
retrieving revision 1.9
diff -u -r1.9 netdb.pp
--- netdb.pp 12 Dec 2003 20:50:18 -0000 1.9
+++ netdb.pp 24 Jan 2004 11:43:08 -0000
@@ -17,6 +17,14 @@
{$h+}
unit netdb;
+{
+ WARNING
+ This unit hardly does any error checking. For example, stringfromlabel
+ could easily be exploited by someone sending malicious UDP packets in
+ order to crash your program. So if you really want to depend on this
+ in critical programs then you'd better fix a lot of code in here.
+ Otherwise, it appears to work pretty well.
+}
Interface
@@ -32,6 +40,7 @@
SNetworksFile = '/etc/networks';
MaxRecursion = 10;
+ MaxIP4Mapped = 10;
Type
TDNSServerArray = Array[1..MaxServers] of THostAddr;
@@ -69,6 +78,9 @@
Function ResolveAddress(HostAddr : THostAddr; Var Addresses : Array of String) : Integer;
+Function ResolveAddress6(HostAddr: THostAddr6; var Addresses: Array of string) : Integer;
+
+function IN6_IS_ADDR_V4MAPPED(HostAddr: THostAddr6): boolean;
Function ResolveHostByName(HostName : String; Var H : THostEntry) : Boolean;
Function ResolveHostByAddr(HostAddr : THostAddr; Var H : THostEntry) : Boolean;
@@ -146,7 +158,7 @@
Auxiliary functions.
---------------------------------------------------------------------}
-function htonl(i:integer):integer;
+function htonl(const i:integer):integer;
begin
{$ifdef ENDIAN_LITTLE}
result := (i shr 24) or (i shr 8 and $ff00) or (i shl 8 and $ff0000) or (i shl 24 and $ff000000);
@@ -155,7 +167,7 @@
{$endif}
end;
-Function htons(var W : Word) : word;
+Function htons(const W : Word) : word;
begin
{$ifdef ENDIAN_LITTLE}
@@ -163,10 +175,9 @@
{$else}
result := w;
{$endif}
- w := result;
end;
-Function ntohs(var W : Word) : Word;
+Function ntohs(const W : Word) : Word;
begin
{$ifdef ENDIAN_LITTLE}
@@ -174,17 +185,15 @@
{$else}
result := w;
{$endif}
- w := result;
end;
-function ntohl(i:integer):integer;
+function ntohl(const i:integer):integer;
begin
{$ifdef ENDIAN_LITTLE}
result := (i shr 24) or (i shr 8 and $ff00) or (i shl 8 and $ff0000) or (i shl 24 and $ff000000);
{$else}
result := i;
{$endif}
- i := result;
end;
{ ---------------------------------------------------------------------
@@ -307,10 +316,10 @@
Delete(Name,1,L);
Until (L=0);
P[Result]:=0;
- htons(rr);
+ rr := htons(rr);
Move(rr,P[Result+1],2);
Inc(Result,3);
- htons(QClass);
+ QClass := htons(QClass);
Move(qclass,P[Result],2);
Inc(Result,2);
end;
@@ -406,7 +415,7 @@
if (Flags2 and QF_RCODE)<>0 then
exit;
// Number of answers ?
- htons(Ancount);
+ AnCount := htons(Ancount);
If Ancount<1 then
Exit;
Result:=True;
@@ -422,7 +431,7 @@
Result:=0;
With Ans do
begin
- htons(qdcount);
+ qdcount := htons(qdcount);
i:=0;
q:=0;
While (Q<qdcount) and (i<l) do
@@ -479,8 +488,7 @@
With SA do
begin
family:=AF_INET;
- port:=DNSport;
- htons(port);
+ port:=htons(DNSport);
addr:=cardinal(HostToNet(DNSServers[Resolver]));
end;
sendto(sock,qry,qrylen+12,0,SA,SizeOf(SA));
@@ -508,14 +516,34 @@
Result:=True;
end;
-Function ResolveNameAt(Resolver : Integer; HostName : String; Var Addresses : Array of THostAddr) : Integer;
+function stringfromlabel(pl: TPayLoad; start: integer): string;
+var
+ l,i: integer;
+begin
+ result := '';
+ l := 0;
+ i := 0;
+ repeat
+ l := ord(pl[start]);
+ if l <> 0 then begin
+ setlength(result,length(result)+l);
+ move(pl[start+1],result[i+1],l);
+ result := result + '.';
+ inc(start,l); inc(start);
+ inc(i,l); inc(i);
+ end;
+ until l = 0;
+ if result[length(result)] = '.' then setlength(result,length(result)-1);
+end;
+
+Function ResolveNameAt(Resolver : Integer; HostName : String; Var Addresses : Array of THostAddr; Recurse: Integer) : Integer;
Var
Qry, Ans : TQueryData;
MaxAnswer,I,QryLen,
AnsLen,AnsStart : Longint;
RR : TRRData;
-
+ cname : string;
begin
Result:=0;
QryLen:=BuildPayLoad(Qry,HostName,DNSQRY_A,1);
@@ -530,13 +558,26 @@
I:=0;
While (I<=MaxAnswer) and NextRR(Ans.Payload,AnsStart,AnsLen,RR) do
begin
- if (Ntohs(RR.AType)=DNSQRY_A) and (1=NtoHS(RR.AClass)) then
- begin
- Move(Ans.PayLoad[AnsStart],Addresses[i],SizeOf(THostAddr));
- inc(Result);
- Inc(AnsStart,RR.RDLength);
+ if htons(rr.AClass) = 1 then
+ case ntohs(rr.AType) of
+ DNSQRY_A: begin
+ Move(Ans.PayLoad[AnsStart],Addresses[i],SizeOf(THostAddr));
+ inc(Result);
+ Inc(AnsStart,htons(RR.RDLength));
+ end;
+ DNSQRY_CNAME: begin
+ if Recurse >= MaxRecursion then begin
+ Result := -1;
+ exit;
+ end;
+ rr.rdlength := ntohs(rr.rdlength);
+ setlength(cname, rr.rdlength);
+ cname := stringfromlabel(ans.payload, ansstart);
+ Result := ResolveNameAt(Resolver, cname, Addresses, Recurse+1);
+ exit; // FIXME: what about other servers?!
+ end;
end;
- Inc(I);
+ Inc(I);
end;
end;
end;
@@ -550,33 +591,13 @@
CheckResolveFile;
I:=1;
Result:=0;
- While (Result=0) and (I<=DNSServerCount) do
+ While (Result<=0) and (I<=DNSServerCount) do
begin
- Result:=ResolveNameAt(I,HostName,Addresses);
+ Result:=ResolveNameAt(I,HostName,Addresses,0);
Inc(I);
end;
end;
-function stringfromlabel(pl: TPayLoad; start: integer): string;
-var
- l,i: integer;
-begin
- result := '';
- l := 0;
- i := 0;
- repeat
- l := ord(pl[start]);
- if l <> 0 then begin
- setlength(result,length(result)+l);
- move(pl[start+1],result[i+1],l);
- result := result + '.';
- inc(start,l); inc(start);
- inc(i,l); inc(i);
- end;
- until l = 0;
- if result[length(result)] = '.' then setlength(result,length(result)-1);
-end;
-
Function ResolveNameAt6(Resolver : Integer; HostName : String; Var Addresses : Array of THostAddr6; Recurse: Integer) : Integer;
Var
@@ -585,13 +606,29 @@
AnsLen,AnsStart : Longint;
RR : TRRData;
cname : string;
+ LIP4mapped: array[0..MaxIP4Mapped-1] of THostAddr;
+ LIP4count: Longint;
begin
Result:=0;
QryLen:=BuildPayLoad(Qry,HostName,DNSQRY_AAAA,1);
- If Not Query(Resolver,Qry,Ans,QryLen,AnsLen) then
- Result:=-1
- else
+ If Not Query(Resolver,Qry,Ans,QryLen,AnsLen) then begin
+ // no answer? try IPv4 mapped addresses, maybe that will generate one
+ LIP4Count := ResolveName(HostName, LIP4Mapped);
+ if LIP4Count > 0 then begin
+ inc(LIP4Count); // we loop to LIP4Count-1 later
+ if LIP4Count > MaxIP4Mapped then LIP4Count := MaxIP4Mapped;
+ if LIP4Count > Length(Addresses) then LIP4Count := Length(Addresses);
+ for i := 0 to LIP4Count-2 do begin
+ Addresses[i] := NoAddress6;
+ Addresses[i][5] := $FFFF;
+ Move(LIP4Mapped[i], Addresses[i][6], 4);
+ end;
+ Result := LIP4Count;
+ end else begin
+ Result:=-1
+ end;
+ end else
begin
AnsStart:=SkipAnsQueries(Ans,AnsLen);
MaxAnswer:=Ans.AnCount-1;
@@ -614,10 +651,8 @@
exit;
end;
rr.rdlength := ntohs(rr.rdlength);
- writeln(rr.rdlength);
setlength(cname, rr.rdlength);
cname := stringfromlabel(ans.payload, ansstart);
- writeln(cname);
Result := ResolveNameAt6(Resolver, cname, Addresses, Recurse+1);
exit; // FIXME: what about other servers?!
end;
@@ -636,7 +671,7 @@
CheckResolveFile;
i := 1;
Result := 0;
- while (Result = 0) and (I<= DNSServerCount) do begin
+ while (Result <= 0) and (I<= DNSServerCount) do begin
Result := ResolveNameAt6(I, Hostname, Addresses, 0);
Inc(i);
end;
@@ -669,6 +704,7 @@
begin
Names[i]:=BuildName(Ans.Payload,AnsStart,AnsLen);
inc(Result);
+ RR.RDLength := ntohs(RR.RDLength);
Inc(AnsStart,RR.RDLength);
end;
Inc(I);
@@ -694,6 +730,45 @@
Inc(I);
end;
end;
+
+Function ResolveAddress6(HostAddr : THostAddr6; Var Addresses : Array of String) : Integer;
+
+const
+ hexdig: string[16] = '0123456789abcdef';
+
+Var
+ I : Integer;
+ S : ShortString;
+
+begin
+ CheckResolveFile;
+ Result:=0;
+ S := '0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.int';
+ for i := 7 downto 0 do begin
+ S[5+(7-i)*8] := hexdig[1+(HostAddr[i] and $000F) shr 00];
+ S[7+(7-i)*8] := hexdig[1+(HostAddr[i] and $00F0) shr 04];
+ S[1+(7-i)*8] := hexdig[1+(HostAddr[i] and $0F00) shr 08];
+ S[3+(7-i)*8] := hexdig[1+(HostAddr[i] and $F000) shr 12];
+ end;
+ I := 1;
+ While (Result=0) and (I<=DNSServerCount) do
+ begin
+ Result:=ResolveAddressAt(I,S,Addresses);
+ Inc(I);
+ end;
+end;
+
+function IN6_IS_ADDR_V4MAPPED(HostAddr: THostAddr6): boolean;
+begin
+ Result :=
+ (HostAddr[0] = 0) and
+ (HostAddr[1] = 0) and
+ (HostAddr[2] = 0) and
+ (HostAddr[3] = 0) and
+ (HostAddr[4] = 0) and
+ (HostAddr[5] = $FFFF);
+end;
+
Function ResolveHostByName(HostName : String; Var H : THostEntry) : Boolean;
signature.asc
Description: This is a digitally signed message part
