Unit inet;

{ --------------------------------------------------------------------
  Unit for internet domain calls.
  Copyright (C) 1997  Michael Van Canneyt

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 1, or (at your option)
  any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

  ChangeLog
  ---------

  Current version is 0.6

  Version          Date             Remarks
  -------          ----             ----
  0.1              07/16/97         Unit started. Michael.
  0.2              07/06/98         Updated for version 0.99.5
  0.4              08/01/98         Objects for name lookup implemented
  0.5              09/10/98         Updated calls for 0.99.8.
  0.6              05/04/99         Added explicit asmmode.

  ------------------------------------------------------------------- }


interface

Uses Initc;	// link to libc.

Const
  { Net type }
  AF_INET = 2;

  { Error constants. Returned by LastError method of THost, TNet}

  NETDB_INTERNAL= -1;       { see errno }
  NETDB_SUCCESS = 0;        { no problem }
  HOST_NOT_FOUND= 1;        { Authoritative Answer Host not found }
  TRY_AGAIN     = 2;        { Non-Authoritive Host not found, or SERVERFAIL }
  NO_RECOVERY   = 3;        { Non recoverable errors, FORMERR, REFUSED, NOTIMP }
  NO_DATA       = 4;        { Valid name, no data record of requested type }
  NO_ADDRESS    = NO_DATA;  { no address, look for MX record }




Type
  THostAddr = array[1..4] of byte;
  PHostAddr = ^THostAddr;

Const
  NoAddress : THostAddr = (0,0,0,0);

Type

  { THostEnt Object }
  THostEnt = record
    Name     : pchar;   { Official name }
    Aliases  : ppchar;  { Null-terminated list of aliases}
    Addrtype : longint; { Host address type }
    Addrlen  : longint; { Length of address }
    Addrlist : ppchar;  { null-terminated list of adresses }
  end;
  PHostEnt = ^THostEnt;

  { TNetEnt object }
  TNetEnt = record
    Name     : pchar;   { Official name }
    Aliases  : ppchar;  { Nill-terminated alias list }
    AddrType : longint; { Net address type }
    net      : Longint; { Network number }
  end;
  PNetEnt = ^TNetEnt;

  TServEnt = record
    name    : pchar;    { Service name }
    aliases : ppchar;   { Null-terminated alias list }
    port    : longint;  { Port number }
    proto   : pchar;    { Protocol to use }
  end;
  PServEnt = ^TServEnt;

  { Pascal Wrapper objects }

  TSelectType = (stFirst,stNext,stPrevious);

  THost = Object
    FHostEntry : PHostEnt;
    FAlias,FAddr,FError : Longint;
    Constructor NameLookup (HostName : String);
    Constructor AddressLookup (Const Address : THostAddr);
    Destructor Done;
    Function Name : String;
    Function GetAddress (Select : TSelectType) : String;
    Function GetAlias (Select : TSelectType) : String;
    Function IPAddress : THostAddr;
    Function IPString : String;
    Function LastError : Longint;
  end;

  TNet = Object
    FNetEntry : PNetEnt;
    FAlias,FError : Longint;
    Constructor NameLookup (NetName : String);
    Constructor AddressLookup (Const Address : Longint);
    Destructor Done;
    Function Name : String;
    Function GetAlias (Select : TSelectType) : String;
    Function IPAddress : Longint;
    Function IPString : String;
    Function LastError : Longint;
  end;

  TService = Object
    FServiceEntry : PServEnt;
    FAlias,FError : Longint;
    Constructor NameLookup (ServiceName,Proto : String);
    Constructor PortLookup (APort : Longint; Proto: string);
    Destructor Done;
    Function Name : String;
    Function Protocol : String;
    Function GetAlias (Select : TSelectType) : String;
    Function Port : Longint;
    Function LastError : Longint;
  end;



{ Pascal style calls }

function HostAddrToStr (Entry : THostAddr) : String;
function StrToHostAddr (IP : String) : THostAddr;
function NetAddrToStr (Entry : Longint) : String;
function StrToNetAddr (IP : String) : Longint;
Function HostToNet (Host : Longint) : Longint;
Function NetToHost (Net : Longint) : Longint;
Function ShortHostToNet (Host : Word) : Word;
Function ShortNetToHost (Net : Word) : Word;

{ C style calls, linked in from Libc }

function gethostent : PHostEnt; cdecl; external;
function gethostbyname ( Name : Pchar) : PHostEnt; cdecl; external;
function gethostbyaddr ( Addr : PHostAddr; Len : Longint; HType : Longint) : PHostent ; cdecl; external;
procedure sethostent (stayopen : longint); cdecl; external;
procedure endhostent; cdecl; external;

function getnetent : PNetEnt; cdecl; external;
function getnetbyname ( Name : pchar) : PNetEnt; cdecl; external;
function getnetbyaddr ( Net : Longint; nettype : Longint) : PNetEnt; cdecl; external;
procedure setnetent ( Stayopen : Longint);  cdecl; external;
procedure endnetent; cdecl; external;

function getservent : PServEnt; cdecl; external;
function getservbyname (name : pchar  ; protocol : pchar) : PServEnt; cdecl; external;
function getservbyport (port : longint; protocol : pchar) : PServEnt; cdecl; external;
procedure setservent (StayOpen : longint); cdecl; external;
procedure endservent; cdecl; external;

Function GetDNSError : libcint;

implementation

Uses strings;

Function GetDNSError:libcint;

begin
  GetDNSError:=fpGetCErrno;
end;

function HostAddrToStr (Entry : THostAddr) : String;

Var Dummy : String[4];
    I : Longint;

begin
  HostAddrToStr:='';
  For I:=1 to 4 do
   begin
   Str(Entry[I],Dummy);
   HostAddrToStr:=HostAddrToStr+Dummy;
   If I<4 Then HostAddrToStr:=HostAddrToStr+'.';
   end;
end;

function StrToHostAddr(IP : String) : THostAddr ;

Var Dummy : String[4];
    I : Longint;
    J : Integer;
    Temp : THostAddr;

begin
  StrToHostAddr:=NoAddress;
  For I:=1 to 4 do
   begin
   If I<4 Then
     begin
     J:=Pos('.',IP);
     If J=0 then exit;
     Dummy:=Copy(IP,1,J-1);
     Delete (IP,1,J);
     end
   else
     Dummy:=IP;
   Val (Dummy,Temp[I],J);
   If J<>0 then Exit;
   end;
 StrToHostAddr:=Temp;
end;

function NetAddrToStr (Entry : longint) : String;

Var Dummy : String[4];
    I : Longint;

begin
  NetAddrToStr:='';
  For I:=4 downto 1 do
   begin
   Str(THostAddr(Entry)[I],Dummy);
   NetAddrToStr:=NetAddrToStr+Dummy;
   If I>1 Then NetAddrToStr:=NetAddrToStr+'.';
   end;
end;

function StrToNetAddr(IP : String) : Longint;

begin
  StrToNetAddr:=Longint(StrToHostAddr(IP));
end;


Constructor THost.NameLookup (HostName : String);

begin
  HostName:=HostName+#0;
  FHostEntry:=GetHostByName(pchar(@HostName[1]));
  If FHostEntry=Nil then
    FError:=GetDNSError
  else
    begin
    FAlias:=0;
    FAddr:=0;
    Ferror:=0;
    end;
end;

Constructor THost.AddressLookup (Const Address: THostAddr);

begin
  FHostEntry:=GetHostByAddr(PHostAddr(@Address),SizeOf(Address),AF_INET);
  If FHostEntry=Nil then
    FError:=GetDNSError
  else
    begin
    FAlias:=0;
    FAddr:=0;
    FError:=0;
    end;
end;


Function THost.Name : String;

begin
  Name:='';
  If (FHostEntry=Nil) or (FError<>0) then exit;
  Name:=StrPas(FHostEntry^.Name);
end;

Function THost.GetAlias (Select : TSelectType) : String;

begin
  GetAlias:='';
  If (FHostEntry=Nil) or (FError<>0) then exit;
  Case Select of
    stFirst     : FAlias:=0;
    stnext      : If FHostEntry^.Aliases[FAlias]<>Nil then
                    Falias:=Falias+1;
    stprevious  : If FAlias=0 Then Exit else FAlias:=FAlias-1;
  end;
  If FHostEntry^.Aliases[FAlias]<>Nil then
    GetAlias:=StrPas(FHostEntry^.Aliases[FAlias]);
end;

Function THost.GetAddress (Select : TSelectType) : String;

begin
  GetAddress:='';
  If (FHostEntry=Nil) or (FError<>0) then exit;
  Case Select of
    stFirst     : FAddr:=0;
    stnext      : If FHostEntry^.AddrList[FAddr]<>Nil then
                    FAddr:=FAddr+1;
    stprevious  : If FAddr=0 Then Exit else FAddr:=FAddr-1;
  end;
  If FHostEntry^.AddrList[FAddr]<>Nil then
    GetAddress:=HostAddrToStr(PHostAddr(FHostEntry^.AddrList[FAddr])^);
end;

Function THost.IPstring : String;

begin
  IPString:='';
  If (FHostEntry=Nil) or (FError<>0) then exit;
  If FHostEntry^.AddrList[0]<>Nil then
    IPString:=HostAddrToStr(PHostAddr(FHostEntry^.AddrList[0])^);
end;

Function THost.IPaddress : THostAddr;

begin
  IPAddress:=NoAddress;
  If (FHostEntry=Nil) or (FError<>0) then exit;
  IPAddress:=PHostAddr(FHostEntry^.AddrList[0])^;
end;

Destructor THost.Done;

begin
end;

Function THost.LastError : Longint;

begin
  LastError:=FError;
end;

Constructor TNet.NameLookup (NetName : String);

begin
  NetName:=NetName+#0;
  FNetEntry:=GetNetByName(pchar(@NetName[1]));
  If FNetEntry=Nil then
    FError:=GetDNSError
  else
    begin
    FAlias:=0;
    Ferror:=0;
    end;
end;

Constructor TNet.AddressLookup (Const Address: Longint);

begin
  FNetEntry:=GetNetByAddr(Address,AF_INET);
  If FNetEntry=Nil then
    FError:=GetDNSError
  else
    begin
    FAlias:=0;
    FError:=0;
    end;
end;


Function TNet.Name : String;

begin
  Name:='';
  If (FNetEntry=Nil) or (FError<>0) then exit;
  Name:=StrPas(FNetEntry^.Name);
end;

Function TNet.GetAlias (Select : TSelectType) : String;

begin
  GetAlias:='';
  If (FNetEntry=Nil) or (FError<>0) then exit;
  Case Select of
    stFirst     : FAlias:=0;
    stnext      : If FNetEntry^.Aliases[FAlias]<>Nil then
                    Falias:=Falias+1;
    stprevious  : If FAlias=0 Then Exit else FAlias:=FAlias-1;
  end;
  If FNetEntry^.Aliases[FAlias]<>Nil then
    GetAlias:=StrPas(FNetEntry^.Aliases[FAlias]);
end;

Function TNet.IPstring : String;

begin
  IPString:='';
  If (FNetEntry=Nil) or (FError<>0) then exit;
  IPString:=NetAddrToStr(FNetEntry^.Net);
end;

Function TNet.IPaddress : Longint;

begin
  IPAddress:=0;
  If (FNetEntry=Nil) or (FError<>0) then exit;
  IPAddress:=FNetEntry^.Net;
end;

Destructor TNet.Done;

begin
end;

Function TNet.LastError : Longint;

begin
  LastError:=FError;
end;

Constructor TService.NameLookup (ServiceName,Proto : String);

begin
  ServiceName:=ServiceName+#0;
  Proto:=Proto+#0;
  FServiceEntry:=GetServByName(pchar(@ServiceName[1]),pchar(@Proto[1]));
  If FServiceEntry=Nil then
    FError:=GetDNSError
  else
    begin
    FAlias:=0;
    Ferror:=0;
    end;
end;

Constructor TService.PortLookup (APort: Longint; Proto : String);

begin
  Proto:=proto+#0;
  FServiceEntry:=GetServByPort(APort,pchar(@proto[1]));
  If FServiceEntry=Nil then
    FError:=GetDNSError
  else
    begin
    FAlias:=0;
    FError:=0;
    end;
end;


Function TService.Name : String;

begin
  Name:='';
  If (FServiceEntry=Nil) or (FError<>0) then exit;
  Name:=StrPas(FServiceEntry^.Name);
end;

Function TService.GetAlias (Select : TSelectType) : String;

begin
  GetAlias:='';
  If (FServiceEntry=Nil) or (FError<>0) then exit;
  Case Select of
    stFirst     : FAlias:=0;
    stnext      : If FServiceEntry^.Aliases[FAlias]<>Nil then
                    Falias:=Falias+1;
    stprevious  : If FAlias=0 Then Exit else FAlias:=FAlias-1;
  end;
  If FServiceEntry^.Aliases[FAlias]<>Nil then
    GetAlias:=StrPas(FServiceEntry^.Aliases[FAlias]);
end;

Function TService.Protocol : String;

begin
  Protocol:='';
  If (FServiceEntry=Nil) or (FError<>0) then exit;
  Protocol:=Strpas(FServiceEntry^.proto);
end;

Function TService.Port : Longint;

begin
  Port:=0;
  If (FServiceEntry=Nil) or (FError<>0) then exit;
  Port:=FServiceEntry^.Port;
end;

Destructor TService.Done;

begin
end;

Function TService.LastError : Longint;

begin
  LastError:=FError;
end;

Function HostToNet (Host : Longint) : Longint;

begin
  HostToNet:=THostAddr(host)[1];
  HostToNEt:=HostTONet or ( (THostAddr(host)[2]) shl 8);
  HostToNEt:=HostToNet or ( (THostAddr(host)[3]) shl 16);
  HostToNEt:=HostToNet or ( (THostAddr(host)[4]) shl 24);
end;

Function NetToHost (Net : Longint) : Longint;

begin
  NetToHost:=THostAddr(Net)[1];
  NetToHost:=NetToHost or ( (THostAddr(Net)[2]) shl 8);
  NetToHost:=NetToHost or ( (THostAddr(Net)[3]) shl 16);
  NetToHost:=NetToHost or ( (THostAddr(Net)[4]) shl 24);
end;

Function ShortHostToNet (Host : Word) : Word;

begin
  ShortHostToNet:=lo(host)*256+Hi(Host);
end;

Function ShortNetToHost (Net : Word) : Word;

begin
  ShortNetToHost:=lo(Net)*256+Hi(Net);
end;

end.


   $Log: inet.pp,v $
   Revision 1.3  2003/12/10 12:16:14  marco
    * now uses initc

   Revision 1.2  2002/09/07 15:42:52  peter
     * old logs removed and tabs fixed

   Revision 1.1  2002/01/29 17:54:53  peter
     * splitted to base and extra

}
