Unit NwRIP;

{ NwTP Version 0.6, Copyright 1993,1994 R. Spronk

  WARNING: Test your program thoroughly if you're using nwRip functions.
  ----------------------------------------------------------------------

  Using the RIP functionality the wrong way may very well result in
  aborting servers ! (no kidding.)

  As far as I know the diagnostic RIP function(s) included in this unit
  are perfectly safe to use.

  Based on:

  -GETALL, written in C by Barry Lagerweij of 2:2802/110.2
   posted in the Fido NOVELL area on Tue 7 Sep 93  0:36.
  -GETRIP, written in C by Koos van den Hout of 2:500/101.11012
   last updated 8 Feb 93 }

INTERFACE

Uses nwMisc,nwIPX;

CONST ECB_COUNT=10;
{ assumption : 10 receiveECBs are used, which means a max of 500 networks }

{ Type definitions for RIP request/response structures}
type TRIPentry=record
               network:TnetworkAddress;
               hops   :word;
               ticks  :word;
               end;

     TRIPanswerPacket=record
                      operation:word;
                      entry    :array[1..50] of TRIPEntry;
                      end;

     TRIPinfo=array[1..50*ECB_COUNT] of record
                                        address:TnetworkAddress;
                                        hops   :byte;
                                        Ticks  :word;
                                        end;

Function GetAllNetworks(SegmentNetworkAddress:TnetworkAddress;
                    Var NetInfo:TRIPinfo):word;
{SegmentNetworkAddress: The target network whose routers
                        will be queried. Set to all zeroes (00 00 00 00)
                        if querying your own segment.
 NetInfo : the buffer where the network-info is stored.
 Returns : the number of known networks.

 Assumed is that IPXInitialize is already called. }

IMPLEMENTATION {===========================================================}

Function GetAllNetworks(SegmentNetworkAddress:TnetworkAddress;
                    Var NetInfo:TRIPinfo):word;
Var
    RIPrequest      :TRIPanswerPacket;
    RIPanswer       :array[1..ECB_COUNT] of TRIPanswerPacket;
    RequestEcb      :Tecb;
    RequestIPXheader:TipxHeader;
    ReplyECB        :array[1..ECB_COUNT] of Tecb;
    ReplyIPX        :array[1..ECB_COUNT] of TipxHeader;
    Target          :TinternetworkAddress;
    Sourcesocket    :word;
    RIPsocket       :word;

    NumberOfNets    :word;
    cnt             :word;
    n               :word;
    RoutableNetworks:word;
    timer1,timer2:word;

Begin
RIPsocket:=$0453;

SourceSocket:=0;
{ open socket for receiving the RIP packets }
IF NOT IPXopenSocket(SourceSocket,SHORT_LIVED_SOCKET)
 then begin
      result:=nwIPX.result;
      GetAllnetworks:=0;
      exit;
      end;

{set-up sendpacket }
target.net:=SegMentNetworkAddress;
fillchar(target.node,6,#$FF); { all nodes i.e. all routers }
target.socket:=RIPsocket;
IPXsetUpSendECB(NIL,SourceSocket,target,@RIPrequest,SizeOf(RIPrequest),
                RequestIPXheader, RequestECB);
RequestIPXheader.packetType := 1;
 { 1=RIP / Any value will work/ type seems to be ignored by Routers
           as long as socket is OK.  }

{ set-up the RIP request }
FillChar(RIPrequest,SizeOf(RIPrequest),#$FF);
RIPrequest.operation := $0100;  { hi-lo, RIP request }
FillChar(RIPanswer,SizeOf(RIPanswer),#$00);


{ set-up the receive ECBs }
for n:=1 to ECB_COUNT
 do begin
    IPXsetupListenECB(NIL,SourceSocket,
                      @RIPanswer[n],SizeOf(TRIPanswerPacket),
                      ReplyIpx[n],ReplyECB[n]);
    IPXListenForPacket(ReplyECB[n]);
    end;

{ send the RIP request }
IPXSendPacket(RequestECB);

{ wait a while for answers }
IPXgetIntervalMarker(timer1);
REPEAT
 IPXrelinquishcontrol;
 IPXGetIntervalMarker(timer2);
UNTIL abs(timer2-timer1)>20;

NumberOfNets := 0;

{ check all possible RIP responses, and fill the tables }
for n:=1 to ECB_COUNT
 do if (ReplyECB[n].INuseFlag=0) and (RIPanswer[n].operation=$0200)
     then begin
          RoutableNetworks:=(swap(ReplyIPX[n].Length)-32) DIV SizeOf(TRIPentry);
          for cnt:=1 to RoutableNetworks
           do begin
              inc(NumberOfNets);
              With NetInfo[NumberOfNets]
               do begin
                  Address:=RIPanswer[n].entry[cnt].network;
                  hops:=swap(RIPanswer[n].entry[cnt].hops);
                  ticks:=swap(RIPanswer[n].Entry[cnt].ticks);
                  end;
              end;
          end
     else IPXcancelEvent(ReplyECB[n]);

{ our socket is no longer needed }
IPXCloseSocket(SourceSocket);

{ return the number of networks we found }
GetAllNetworks:=NumberOfNets;
end;


end.
