home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / defdata / tcpwicat.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  374.3 KB  |  9,642 lines

  1. --::::::::::::::
  2. --buffer.txt
  3. --::::::::::::::
  4. -----------------------------------------------------------------------
  5. --
  6. --         DoD Protocols    NA-00008-200       80-01175-100(-)
  7. --         E-Systems, Inc.  August 07, 1985
  8. --
  9. --         buffer.txt       Author : Jim Baldo
  10. --
  11. -----------------------------------------------------------------------
  12.  
  13. -- FILE : BUFFER               AUTHOR : JIM BALDO
  14. -- 5/24/85    3:20 PM  : REVISED FOR USE WITH TELESOFT COMPILER
  15. --                       OLD CODE (DEC) MARKED WITH --&MT
  16. -- 5/28/85    10:39 AM : REVISED FOR USE WITH THE DEC COMPILER
  17. --                       OLD CODE (TELESOFT) MARKED WITH --&MT
  18. -- 5/28/85    11:38 AM : REVISED FOR USE WITH TELESOFT COMPILER
  19. --                       OLD CODE (DEC) MARKED WITH --&MT
  20. with SYSTEM;                use SYSTEM;    
  21.             
  22.                         package    BUFFER_DATA is
  23. -----------------------------------------------------------------------------
  24. --This package represents the data abstraction of a message that travels   --
  25. --through each layer in the DoD reference model.  Upon recieving a message -- 
  26. --the protocol uses a pointer to gain access to the beginning of its       --
  27. --header.  The package is implementation dependent.  Its intend is to      --
  28. --facilatate the portibility of this communications program by narrowing   --
  29. --the packages to be change to an absolute minimum for different machines. --
  30. --                                                                         --
  31. --design:                                                                  --
  32. --                                                                         --
  33. --                                                                         --
  34. -- The packed bit stream buffer definition.                                --
  35. -- A buffer record contains the following information:                     -- 
  36. --  STATUS      : indicating the current owner, if any. A process must not --
  37. --                free a buffer if it is owned by any other process.       --
  38. --  TELNET_PTR  : indicates the position of the first byte of data for     --
  39. --                Telnet.                                                  --
  40. --  TCP_PTR     : indicates the position of the first byte of data for TCP.--
  41. --  IP_PTR      : indicates the position of the first byte of data for IP. --
  42. --  SUBNET_PTR    : Indicates the position of the first byte of data         --
  43. --              for SUBNET                                       --
  44. --  SIZE        : total size in bytes                                      --
  45. --  BYTE        : The actual transmitted data, in an array of packed bytes.--
  46. --  NEXT        : A link field used to manage free buffers.                --
  47. --                                                                         -- 
  48. --                                                                         --
  49. --                                                                         --
  50. --      Organization of buffer                                             --
  51. --       Note that unused portion of the buffer is at the front or the back--
  52. --         of the buffer.                                                  --
  53. --                                                                         -- 
  54. --      +-------------+                                                    -- 
  55. --      |             |                                                    --
  56. --      |   unused    |                                                    --
  57. --      |             |                                                    --
  58. --      +-------------+ <-------- SUBNET_PTR                               --
  59. --      |             |                                                    --
  60. --      |    SUBNET   |                                                    --
  61. --      |   header    |                                                    --
  62. --      |             |                                                    -- 
  63. --      +-------------+ <-------- IP_PTR                                   --
  64. --      |             |                                                    --
  65. --      |     IP      |                                                    --
  66. --      |   header    |                                                    --
  67. --      |             |                                                    --
  68. --      +-------------+ <-------- TCP_PTR                                  --
  69. --      |             |                                                    --
  70. --      |    TCP      |                                                    --
  71. --      |   header    |                                                    --
  72. --      |             |                                                    --
  73. --      +-------------+ <-------- TELNET_PTR                               --
  74. --      |             |                                                    --
  75. --      |   TELNET    |                                                    --
  76. --      |    data     |                                                    --
  77. --      |             |                                                    --
  78. --      +-------------+                                                    --
  79. --      |             |                                                    --
  80. --      |   unused    |                                                    --
  81. --      |             |                                                    --
  82. --      +-------------+                                                    --
  83. --                                                                         --
  84. -----------------------------------------------------------------------------
  85. --&MT   subtype THIRTYTWO_BITS is INTEGER; -- DEC/Ada
  86.         subtype THIRTYTWO_BITS is LONG_INTEGER; --Telesoft Ada version 1.5
  87. --&MT   subtype SIXTEEN_BITS is SHORT_INTEGER; -- DEC/Ada
  88.         subtype SIXTEEN_BITS iS INTEGER; --Telesoft Ada version 1.5
  89. --&MT   subtype SYSTEM_BYTE is UNSIGNED_BYTE; -- DEC/Ada
  90.         subtype SYSTEM_BYTE is SYSTEM.BYTE; -- Telesoft Ada version 1.5
  91.      MAXIMUM_DATAGRAM_SIZE : constant SIXTEEN_BITS  := 576;
  92.     type BUFFER_STATUS is (NONE, OWNER_TELNET, OWNER_TCP, OWNER_IP,
  93.                    OWNER_X25);
  94. --&MT   type BUFFER_AREA IS ARRAY(1..MAXIMUM_DATAGRAM_SIZE) OF SYSTEM_BYTE;
  95.         type BUFFER_AREA IS ARRAY(1..576) OF SYSTEM_BYTE;
  96.                                                             
  97.     TELNET_SIZE : constant SIXTEEN_BITS := 512; --for efficent block transfer
  98.     TCP_SIZE : constant SIXTEEN_BITS := 512;
  99.     IP_SIZE : constant SIXTEEN_BITS := 512;
  100.     SUBNET_SIZE : constant SIXTEEN_BITS := 512; --set appropiately to SUBNET
  101.                            --specification
  102.     subtype TELNET_PTR_TYPE is SIXTEEN_BITS  range 0..TELNET_SIZE;
  103.     subtype TCP_PTR_TYPE is SIXTEEN_BITS  range 0..TCP_SIZE;
  104.     subtype IP_PTR_TYPE is SIXTEEN_BITS  range 0..IP_SIZE;
  105.     subtype SUBNET_PTR_TYPE is SIXTEEN_BITS  range 0..SUBNET_SIZE;
  106.     type PACKED_BUFFER;
  107.     type PACKED_BUFFER_PTR is access PACKED_BUFFER;
  108.     type PACKED_BUFFER is 
  109.         record 
  110.             STATUS     : BUFFER_STATUS := NONE;
  111.             IN_USE     : BOOLEAN := false;
  112.                      -- THE LAYER USING IT MAY NOT 
  113.                      -- BE THE OWNER.
  114.                         SIZE       : SIXTEEN_BITS  range 0..MAXIMUM_DATAGRAM_SIZE ;
  115.             TELNET_PTR : TELNET_PTR_TYPE;
  116.             TCP_PTR    : TCP_PTR_TYPE;
  117.             IP_PTR     : IP_PTR_TYPE;
  118.             SUBNET_PTR : SUBNET_PTR_TYPE;
  119.             BYTE       : BUFFER_AREA;
  120.             NEXT       : PACKED_BUFFER_PTR;
  121.         end record;
  122.     --type BUFFER_ERROR_TYPE is (RETURNING_A_BUFFER,OUT_OF_FREE_BUFFERS);
  123.     procedure INIT;
  124.         --This subprogram is called when the system is intialize to 
  125.         --create a finite number of buffers.
  126.     procedure BUFFREE
  127.         ( BUFPTR :  in out PACKED_BUFFER_PTR;
  128.                   BUFFTYPE : in SIXTEEN_BITS );
  129.         --This subprogram frees a buffer to be used again.
  130.         --Change buffer status to free and place it on a free list 
  131.         --of buffers.
  132.     procedure BUFFGET
  133.         ( BUFPTR : in out PACKED_BUFFER_PTR; 
  134.                   BUFFTYPE : in SIXTEEN_BITS );
  135.         --This subprogram obtains a buffer to be used.
  136. end BUFFER_DATA;
  137. -- 5/24/85    3:20 PM  : REVISED FOR USE WITH TELESOFT COMPILER
  138. --                       OLD CODE (DEC) MARKED WITH --&MT
  139. -- 5/28/85    10:39 AM : REVISED FOR USE WITH THE DEC COMPILER
  140. --                       OLD CODE (TELESOFT) MARKED WITH --&MT
  141. -- 5/28/85    11:40 AM : REVISED FOR USE WITH TELESOFT COMPILER
  142. --                       OLD CODE (DEC) MARKED WITH --&MT
  143. with UNCHECKED_CONVERSION;
  144. with TEXT_IO;           use TEXT_IO, LONG_INTEGER_IO;
  145. ----------------------------------------------------------------------------
  146. -- 
  147. -- Implementation for DEC VAX installation only!
  148. --
  149. ----------------------------------------------------------------------------
  150. package    body BUFFER_DATA  is
  151. --&MT THE FOLLOWING LINE SHOULD BE DELETED WHEN USING TELESOFT :
  152. --&MT package INT_IO is new INTEGER_IO( THIRTYTWO_BITS );
  153.   
  154. HEAD : PACKED_BUFFER_PTR; -- The pointer to the head of the buffer free 
  155. BUFFER_COUNT : THIRTYTWO_BITS ;
  156. BUFFER_PRINT_FLAG : THIRTYTWO_BITS  := 1;
  157. procedure BUFFREE
  158.     ( BUFPTR : in out PACKED_BUFFER_PTR; 
  159.           BUFFTYPE : in SIXTEEN_BITS ) is
  160. begin
  161.  if BUFPTR = null then
  162.   TEXT_IO.PUT_LINE("JUST RECEIVED A NULL POINTER IN BUFFREE");
  163.  else
  164.   if BUFPTR.STATUS = NONE and then NOT BUFPTR.IN_USE then
  165.     BUFFER_COUNT := BUFFER_COUNT + 1; 
  166. --    if BUFFER_PRINT_FLAG /= 0 then --for debug only(JB 1/25/85)
  167.      --TEXT_IO.NEW_LINE;
  168.          --TEXT_IO.PUT("FREEING A BUFFER. NUMBER OF FREE BU");
  169.      --TEXT_IO.LONG_INTEGER_IO.PUT(BUFFER_COUNT);
  170.      --TEXT_IO.NEW_LINE;
  171. --    end if;
  172.     bufptr.in_use := true;
  173.     BUFPTR.NEXT := HEAD;
  174.     HEAD := BUFPTR;
  175.     bufptr := null; -- return a null pointer
  176.   end if;
  177.  end if;
  178. exception
  179.   when CONSTRAINT_ERROR =>
  180.    TEXT_IO.PUT_LINE("CONSTRAINT ERROR in BUFFREE");
  181.   when others => 
  182. --&MT  put_line("ERROR IN BUFFREE") ;
  183.    text_io.put_line ("UNKNOWN ERROR IN BUFFREE") ;
  184. end BUFFREE;
  185. procedure BUFFGET
  186.     (BUFPTR : in out PACKED_BUFFER_PTR; 
  187.      BUFFTYPE : in SIXTEEN_BITS ) is
  188. begin
  189.  BUFPTR := HEAD;
  190.  if HEAD /= null then
  191.   HEAD := HEAD.NEXT;
  192.   bufptr.in_use     := false ;
  193.   bufptr.telnet_ptr := 255 ;
  194.   bufptr.tcp_ptr    := 255 ;
  195.   bufptr.ip_ptr     := 255 ;
  196.   bufptr.subnet_ptr := 255 ;
  197.   bufptr.status     := NONE ;
  198.  else
  199.    text_io.put_line("BUFFER_ERROR  OUT_OF_FREE_BUFFERS") ; -- for debug
  200.  end if ;
  201.  if BUFFER_COUNT /= 0 then
  202.   BUFFER_COUNT := BUFFER_COUNT - 1;
  203.  end if;
  204. -- if BUFFER_PRINT_FLAG /= 0 then--for debug only (JB 1/25/85)
  205. --    if BUFFER_COUNT /= 0 then
  206. --        TEXT_IO.NEW_LINE;
  207. --                TEXT_IO.PUT
  208. --                 ("GETTING A BUFFER. NUMBER OF FREE BU");
  209. --        TEXT_IO.INTEGER_IO.PUT(BUFFER_COUNT);
  210. --        TEXT_IO.NEW_LINE;
  211. --    else
  212. --                TEXT_IO.PUT_LINE("NO FREE BUFFERS ON BUFFER GET");
  213. --    end if;
  214. -- end if;
  215. exception
  216.   when others =>
  217.     TEXT_IO.PUT_LINE("ERROR IN BUFFER GET");
  218.     raise ;
  219. end BUFFGET;
  220. procedure INIT is
  221.  I : THIRTYTWO_BITS ;
  222.  NEXT_BUFFER : PACKED_BUFFER_PTR;
  223. begin
  224.   -- get one hundred-fifty and one buffers.
  225.   HEAD := new PACKED_BUFFER;
  226.   NEXT_BUFFER := new PACKED_BUFFER;
  227.   HEAD.NEXT := NEXT_BUFFER;
  228.   for I in 1..50 loop
  229.     next_buffer := new packed_buffer;
  230.     buffree(next_buffer,0) ;
  231.     end loop;
  232.   BUFFER_COUNT := 50;
  233.   --if BUFFER_PRINT_FLAG /= 0 then
  234.     --TEXT_IO.PUT("THE NUMBER OF INITIAL BUFFERS IS ");
  235. --&MT INT_IO.PUT(BUFFER_COUNT);
  236.     --INTEGER_IO.PUT(50) ;
  237.     --TEXT_IO.NEW_LINE;
  238.   --end if;
  239. exception 
  240.   when STORAGE_ERROR =>
  241.     TEXT_IO.PUT_LINE("OUT OF ROOM TO INITIALIZE BUFFERS");
  242.   when others =>
  243.     TEXT_IO.PUT_LINE("ERROR IN INITIALIZE BUFFERS");
  244. end INIT;
  245. --
  246. -- Package initialization
  247. --
  248. begin
  249.  BUFFER_COUNT := 0; -- initialize buffer count.
  250. end BUFFER_DATA;
  251. --::::::::::::::
  252. --icmp.txt
  253. --::::::::::::::
  254. -----------------------------------------------------------------------
  255. --
  256. --         DoD Protocols    NA-00008-200       80-01176-100(-)
  257. --         E-Systems, Inc.  August 07, 1985
  258. --
  259. --         icmp.txt       Author : Jim Baldo
  260. --
  261. -----------------------------------------------------------------------
  262. with SYSTEM;                use SYSTEM;
  263. with BUFFER_DATA;            use BUFFER_DATA;
  264. with IP_GLOBALS;            use IP_GLOBALS;
  265.             package UTILITIES_FOR_ICMP is
  266.         ----------------------------------------------------
  267.         --This implementation is for use with DEC/ADA     --
  268.         --compiler.                                       --
  269.         ----------------------------------------------------
  270. -- TEMPORARY FOR TESTING
  271. -- UNTIL TCP MODULES ARE COMBINED
  272. type TCP_PORT_ADDRESS_TYPE is array(1..2) of SYSTEM.BYTE;
  273.   function ICMP_CHECKSUM( START_PTR : SIXTEEN_BITS ; 
  274.                           END_PTR : SIXTEEN_BITS ; 
  275.                           PACKED_BUFFER : PACKED_BUFFER_PTR) 
  276.                                  return SIXTEEN_BITS ;
  277.     --This function requires a pointer to the beginning of 
  278.     --the ICMP control message, pointer to the end of the IP header, 
  279.     --and pointer to the datagram.  This function is compatible with 
  280.     --MIL-STD-1777 section 9.4.6.2.4.
  281.   procedure ICMP_MESSAGE_PROCESSOR( ICMP_MESSAGE : in out PACKED_BUFFER_PTR; 
  282.                                 BUFPTR : IP_GLOBALS.BUFFER_POINTER);
  283.     --This subprogram will determine what type of ICMP message has 
  284.     --been sent by a remote host and process the message appropiately.
  285.   procedure SEND_ICMP_MESSAGE( ICMP_MESSAGE : in out PACKED_BUFFER_PTR);
  286.     --This subprogram takes an ICMP message datagram and sends it to 
  287.     --the subnet protocol.
  288. end UTILITIES_FOR_ICMP;
  289. with BUFFER_DATA;
  290. with IP_UNPACK_AND_PACK_UTILITIES;
  291. with UNCHECKED_CONVERSION;
  292. with WITH_TCP_COMMUNICATE;
  293. with TEXT_IO;                   use TEXT_IO, INTEGER_IO ;
  294. package body UTILITIES_FOR_ICMP is
  295.   type ERROR_TYPE is ( PARAM_PROBLEM,EXPIRED_TTL,PROTOCOL_UNREACH );
  296.   function ICMP_CHECKSUM( START_PTR : SIXTEEN_BITS ; 
  297.                           END_PTR : SIXTEEN_BITS ;
  298.                           PACKED_BUFFER : BUFFER_DATA.PACKED_BUFFER_PTR) 
  299.                                    return SIXTEEN_BITS  is
  300.     --This function performs a checksum on the ICMP control message
  301.     --For purpose of computing the checksum, the checksum field
  302.     --(octets 2-3) is set to zero.  Implementation dependent action.
  303.   type TWO_WORDS is array (1..2) of SIXTEEN_BITS ;
  304.   type TELESOFT_FIXUP is array (1..1) of THIRTYTWO_BITS ;
  305.   function CONVERSION is new UNCHECKED_CONVERSION( TELESOFT_FIXUP,TWO_WORDS );
  306.   HIGH_BYTE : BOOLEAN := TRUE;
  307.   ICMP_CHECKSUM : THIRTYTWO_BITS  := 0;
  308.   CSUM : TWO_WORDS := ( 0,0 );
  309.   CHECKSUM : TELESOFT_FIXUP;
  310.   begin
  311.     for I in 0..END_PTR-1 loop
  312.       if ( I /= 2 ) and then ( I /= 3 ) then
  313.         if HIGH_BYTE then
  314.           HIGH_BYTE := FALSE;
  315.           ICMP_CHECKSUM := ICMP_CHECKSUM + 
  316.         THIRTYTWO_BITS ( PACKED_BUFFER.BYTE( START_PTR + I ) ) *
  317.                     THIRTYTWO_BITS ( 2**8 );
  318.         else
  319.           HIGH_BYTE := TRUE;
  320.           ICMP_CHECKSUM := ICMP_CHECKSUM + 
  321.         THIRTYTWO_BITS ( PACKED_BUFFER.BYTE( START_PTR + I ) );
  322.         end if;
  323.       end if;
  324.     end loop;
  325.     -- Take one's complement of ICMP_CHECKSUM
  326.     ICMP_CHECKSUM := -ICMP_CHECKSUM;
  327.     ICMP_CHECKSUM := ICMP_CHECKSUM - 1;
  328.     
  329.     -- This is a parameter passing problem globally specific to Telesoft
  330.     CHECKSUM(1) := ICMP_CHECKSUM;
  331.     
  332.     -- Get both words and return low word.
  333.     CSUM := CONVERSION( CHECKSUM );
  334.     return CSUM( 2 );
  335.     exception
  336.       when constraint_error => 
  337.         TEXT_IO.PUT_LINE( "Checksum Error in package UTILITIES_FOR_ICMP ");
  338.     TEXT_IO.PUT_LINE( "function CHECKSUM )" );
  339.         INTEGER_IO.PUT( START_PTR );
  340.       -- SYSTEM.REPORT ERROR
  341.       when others => 
  342.         TEXT_IO.PUT_LINE( "Checksum Error in package UTILITIES_FOR_ICMP ");
  343.     TEXT_IO.PUT_LINE( "function CHECKSUM )" );
  344.   end ICMP_CHECKSUM;
  345.   procedure SEND_ICMP_MESSAGE
  346.     (ICMP_MESSAGE : in out BUFFER_DATA.PACKED_BUFFER_PTR) is
  347.     --This subprogram takes an ICMP message datagram and sends it to 
  348.     --the subnet protocol.  
  349.   begin
  350.   --  X_25_DATA.LOCAL_DESTINATION_ADDRESS := ICMP_BUFPTR.DEST;
  351.   --  X_25_DATA.TYPE_OF_SERVICE := ICMP_BUFPTR.TOS;
  352.   --  X_25_DATA.LENGTH := ICMP_BUFPTR.TOT_LEN;
  353.   --  X_25_DATA.DTGM := ICMP_MESSAGE;
  354.   --  X_25_SEND(X_25_DATA);
  355.   null;
  356.   exception
  357.     when constraint_error =>
  358.       TEXT_IO.PUT_LINE("constraint error in package UTILITES_FOR_ICMP ");
  359.       TEXT_IO.PUT_LINE( "procedure SEND_ICMP_MESSAGE");
  360.     when others =>
  361.       TEXT_IO.PUT_LINE("error OTHERS in package UTILITES_FOR_ICMP procedure ");
  362.       TEXT_IO.PUT_LINE( "SEND_ICMP_MESSAGE");
  363.   end SEND_ICMP_MESSAGE;
  364.   procedure ICMP_MESSAGE_PROCESSOR
  365.     (ICMP_MESSAGE : in out BUFFER_DATA.PACKED_BUFFER_PTR; 
  366.     BUFPTR : IP_GLOBALS.BUFFER_POINTER) is
  367.   type GOOD_OR_BAD IS (GOOD,BAD);
  368.   type TWO_BYTE is array(1..2) of SYSTEM.BYTE;
  369.   type TELEGOOFUP is array(1..1) of SIXTEEN_BITS ;
  370.   function CONVERT_TO_TWO_BYTES is new
  371.         UNCHECKED_CONVERSION(TELEGOOFUP, TWO_BYTE);
  372.   WORD_TO_CONVERT : TELEGOOFUP;
  373.   TEMP : TWO_BYTE;
  374.   IHL_IN_OCTETS : SIXTEEN_BITS  := 0;
  375.   ULP_SOURCE_PORT : TCP_PORT_ADDRESS_TYPE;
  376.   ULP_DESTINATION_PORT : TCP_PORT_ADDRESS_TYPE;
  377.   ICMP_ERROR_MESSAGE : STRING(1..80);
  378.   IP_SOURCE_ADDRESS_TEMPORARY_SAVE_FRONT : SYSTEM.BYTE;
  379.   IP_SOURCE_ADDRESS_TEMPORARY_SAVE_BACK : SYSTEM.BYTE;
  380.   IP_HEADER_INFO : IP_GLOBALS.BUFFER_POINTER;
  381.   IP_HEADER_POINTER : SIXTEEN_BITS  := 0;
  382.   IP_DATAGRAM_TOTAL_LENGTH : SIXTEEN_BITS  := 0;
  383.   VERSIONS : SIXTEEN_BITS  := 0;
  384.   IHL : SIXTEEN_BITS  := 0;
  385.   ICMP_TYPE : SIXTEEN_BITS  := 0;
  386.   ICMP_CODE : SIXTEEN_BITS  :=0;
  387.   START_PTR_FOR_ICMP_CHECKSUM : SIXTEEN_BITS  := 0;
  388.   END_PTR_FOR_ICMP_CHECKSUM : SIXTEEN_BITS  := 0;
  389.   TELNET_PTR : constant SIXTEEN_BITS  := ICMP_MESSAGE.TELNET_PTR;
  390.   TCP_PTR : constant SIXTEEN_BITS  := ICMP_MESSAGE.TCP_PTR;
  391.   IP_PTR : constant SIXTEEN_BITS  := ICMP_MESSAGE.IP_PTR;
  392.   function CHECK_ICMP_CHECKSUM return GOOD_OR_BAD is
  393.     type INT_ARRAY is array(1..1) of SIXTEEN_BITS ;
  394.     type TWO_BYTES is array(1..2) of SYSTEM.BYTE;
  395.     function CONVERT_TO_INTEGER is new
  396.         UNCHECKED_CONVERSION(TWO_BYTES,INT_ARRAY);
  397.     BUF_CSUM : TWO_BYTES;
  398.     CARRIER_CSUM : INT_ARRAY;
  399.     INCOMING_ICMP_DATAGRAM_CHECKSUM_CARRIER : INT_ARRAY;
  400.     INCOMING_ICMP_DATAGRAM_CHECKSUM_CALCULATED : INT_ARRAY;
  401.     START_PRT_FOR_ICMP_CHECKSUM : SIXTEEN_BITS  := 0;
  402.     END_PTR_FOR_ICMP_CHECKSUM : SIXTEEN_BITS  := 0;
  403.     begin
  404.       BUF_CSUM(1) := ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 2);
  405.       BUF_CSUM(2) := ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 3);
  406.       INCOMING_ICMP_DATAGRAM_CHECKSUM_CARRIER := CONVERT_TO_INTEGER(BUF_CSUM);
  407.       START_PTR_FOR_ICMP_CHECKSUM := IP_HEADER_POINTER + IHL;
  408.       END_PTR_FOR_ICMP_CHECKSUM := IP_HEADER_POINTER +
  409.         IP_DATAGRAM_TOTAL_LENGTH;
  410.       INCOMING_ICMP_DATAGRAM_CHECKSUM_CALCULATED(1) :=
  411.         ICMP_CHECKSUM
  412.         (START_PRT_FOR_ICMP_CHECKSUM,END_PTR_FOR_ICMP_CHECKSUM,ICMP_MESSAGE);
  413.       if INCOMING_ICMP_DATAGRAM_CHECKSUM_CARRIER =
  414.                 INCOMING_ICMP_DATAGRAM_CHECKSUM_CALCULATED  then
  415.         return GOOD;
  416.       else
  417.         return BAD;
  418.       end if;
  419.     end CHECK_ICMP_CHECKSUM;
  420.     procedure PACK_ICMP_MESSAGE_FOR_ULP( ULP_SOURCE_PORT,
  421.                                          ULP_DESTINATION_PORT :
  422.                                          in TCP_PORT_ADDRESS_TYPE;
  423.                                          ICMP_ERROR_MESSAGE : in STRING) is
  424.     type STUPID is array(1..1) of CHARACTER;
  425.     type A_BYTE is array(1..1) of SYSTEM.BYTE;
  426.     function CONVERT_STRING_TO_SYSTEM_BYTE is
  427.         new UNCHECKED_CONVERSION(STUPID,A_BYTE);
  428.     OFFSET : SIXTEEN_BITS ;
  429.     SLICE_SAVER : STUPID;
  430.     begin
  431.       -- Load message
  432.       OFFSET := ICMP_ERROR_MESSAGE'LENGTH;
  433.       -- Convert string to system byte
  434.       for I in 0..OFFSET-1 loop
  435. --        SLICE_SAVER(1) := ICMP_ERROR_MESSAGE( I );
  436. --        ICMP_MESSAGE.BYTE(TELNET_PTR + I)
  437. --          := CONVERT_STRING_TO_SYSTEM_BYTE(SLICE_SAVER)(1) ;
  438.         null;--temp
  439.       end loop;
  440.       -- TCP Header Setput
  441.         -- Load Source Port
  442.       for I in 1..2 loop
  443.         ICMP_MESSAGE.BYTE(TCP_PTR + SIXTEEN_BITS ( I ) -1) :=
  444.           ULP_SOURCE_PORT(I);               
  445.       end loop;
  446.         -- Load Destination Port
  447.       for I in 1..2 loop
  448.         ICMP_MESSAGE.BYTE(TCP_PTR + SIXTEEN_BITS ( I ) + 2 -1) :=
  449.           ULP_DESTINATION_PORT(I);
  450.       end loop;
  451.     end PACK_ICMP_MESSAGE_FOR_ULP;
  452.     procedure OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  453.               ULP_DESTINATION_PORT :
  454.               out TCP_PORT_ADDRESS_TYPE;
  455.               IHL : SIXTEEN_BITS ) is
  456.     VERSION_SENT_DATAGRAM : SIXTEEN_BITS ;
  457.     IHL_SENT_DATAGRAM : SIXTEEN_BITS ;
  458.     IHL_PORT_POINTER : SIXTEEN_BITS ;
  459.     IHL_PORT_POINTER_SENT_DATAGRAM : SIXTEEN_BITS ;
  460.     begin
  461.       VERSION_SENT_DATAGRAM := SIXTEEN_BITS (
  462.                       ICMP_MESSAGE.BYTE(IP_PTR + IHL + 4)/2**4 ) ;
  463.       IHL_SENT_DATAGRAM := SIXTEEN_BITS (
  464.                 ICMP_MESSAGE.BYTE(IP_PTR + IHL + 4) ) -
  465.             (VERSION_SENT_DATAGRAM * (2**4)) * 4;
  466.       IHL_PORT_POINTER_SENT_DATAGRAM := IP_PTR + IHL + 4 + IHL_SENT_DATAGRAM;
  467.       ULP_SOURCE_PORT(1) := ICMP_MESSAGE.BYTE(IHL_PORT_POINTER);
  468.       ULP_SOURCE_PORT(2) := ICMP_MESSAGE.BYTE(IHL_PORT_POINTER + 1);
  469.       ULP_DESTINATION_PORT(1) := ICMP_MESSAGE.BYTE(IHL_PORT_POINTER + 2);
  470.       ULP_DESTINATION_PORT(2) := ICMP_MESSAGE.BYTE(IHL_PORT_POINTER + 3);
  471.     end OBTAIN_ULP_SOURCE_DESTINATION;
  472.   begin
  473.     IP_HEADER_POINTER := ICMP_MESSAGE.IP_PTR;
  474.     -- Convert IHL from 32-bit word size to 8-bit OCTETS
  475.     IHL_IN_OCTETS := BUFPTR.IHL * 4;
  476.     ICMP_TYPE := SIXTEEN_BITS (
  477.         ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + IHL_IN_OCTETS)) ;
  478.     ICMP_CODE := SIXTEEN_BITS (
  479.                   ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + IHL_IN_OCTETS + 1)) ;
  480.     if (BUFPTR.PROT = 1) and (CHECK_ICMP_CHECKSUM = GOOD)  then
  481.       case ICMP_TYPE is
  482.         when 0 => -- echo reply message
  483.           -- Presently not supported by this implementation version
  484.           TEXT_IO.PUT_LINE(" Recieved echo reply message ");
  485.           TEXT_IO.PUT_LINE(" package UTILITIES_FOR_ICMP ");
  486.           TEXT_IO.PUT_LINE( "procedure ICMP_MESSAGE_PROCESSOR ");
  487.           -- never recieved; always sent
  488.         when 3=> -- destination unreachable messasge
  489.           case ICMP_CODE is
  490.             when 0 => -- net unreachable
  491.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  492.                     ULP_DESTINATION_PORT,
  493.                     IHL);
  494.               -- load error message for net unreachable to be displayed by ULP
  495.               ICMP_ERROR_MESSAGE(1..38) :=
  496.                 " ICMP Error Message : Net Unreachable ";
  497.               -- format ICMP error message for ULP
  498.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  499.                     ULP_DESTINATION_PORT,
  500.                     ICMP_ERROR_MESSAGE);
  501.             when 1 => -- host unreachable
  502.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  503.                     ULP_DESTINATION_PORT,
  504.                     IHL);
  505.               -- load error message for host unreachable to be displayed by ULP
  506.               ICMP_ERROR_MESSAGE(1..39) :=
  507.                 " ICMP Error Message : Host Unreachable ";
  508.               -- format ICMP error message for ULP
  509.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  510.                     ULP_DESTINATION_PORT,
  511.                     ICMP_ERROR_MESSAGE);
  512.             when 2 => -- protocol unreachable
  513.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  514.                     ULP_DESTINATION_PORT,
  515.                     IHL);
  516.               -- load error message for protocol unreachable to be displayed 
  517.           -- by ULP
  518.               ICMP_ERROR_MESSAGE(1..43) := 
  519.         " ICMP Error Message : Protocol Unreachable ";
  520.               -- format ICMP error message for ULP
  521.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  522.                     ULP_DESTINATION_PORT,
  523.                     ICMP_ERROR_MESSAGE);
  524.             
  525.             when 3 => -- port unreachable
  526.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  527.                     ULP_DESTINATION_PORT,
  528.                     IHL);
  529.               -- load error message for port unreachable to be displayed by ULP
  530.               ICMP_ERROR_MESSAGE(1..39) := 
  531.         " ICMP Error Message : Port Unreachable ";
  532.               -- format ICMP error message for ULP
  533.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  534.                     ULP_DESTINATION_PORT,
  535.                     ICMP_ERROR_MESSAGE);
  536.             
  537.             when 4 => -- fragmentation needed and Don't Fragment
  538.                       -- Flag is set              
  539.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  540.                     ULP_DESTINATION_PORT,
  541.                     IHL);
  542.               -- load error message to be displayed by ULP
  543.           ICMP_ERROR_MESSAGE(1..74) := 
  544. " ICMP Error Message : fragmentation needed and Don't Fragment Flag is set ";
  545.               -- format ICMP error message for ULP
  546.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  547.                     ULP_DESTINATION_PORT,
  548.                     ICMP_ERROR_MESSAGE);
  549.             
  550.             when 5 => -- source route failed
  551.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  552.                     ULP_DESTINATION_PORT,
  553.                     IHL);
  554.               -- load error message to be displayed by ULP
  555.               ICMP_ERROR_MESSAGE(1..42) := 
  556.         " ICMP Error Message : source route failed ";
  557.               -- format ICMP error message for ULP
  558.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  559.                     ULP_DESTINATION_PORT,
  560.                     ICMP_ERROR_MESSAGE);
  561.             when others =>
  562.       TEXT_IO.PUT_LINE(" Error message package UTILITIES_FOR_ICMP ");
  563. TEXT_IO.PUT_LINE( "procedure ICMP_MESSAGE_PROCESSOR case exhaustive error ");
  564.           TEXT_IO.PUT_LINE(" Bogus ICMP message #3 code field ");
  565.           end case;
  566.         
  567.         when 4 => -- Source Quench Message
  568.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  569.                     ULP_DESTINATION_PORT,
  570.                     IHL);
  571.               -- load error message to be displayed by ULP
  572.               ICMP_ERROR_MESSAGE(1..44) := 
  573.         " ICMP Error Message : source quench message ";
  574.               -- format ICMP error message for ULP
  575.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  576.                     ULP_DESTINATION_PORT,
  577.                     ICMP_ERROR_MESSAGE);
  578.         
  579.         when 5 => -- Redirect Message
  580.           case ICMP_CODE is
  581.             
  582.             when 0 => -- redirect datagrams for the Network
  583.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  584.                     ULP_DESTINATION_PORT,
  585.                     IHL);
  586.               -- load error message to be displayed by ULP 
  587.         ICMP_ERROR_MESSAGE(1..57) := 
  588.           " ICMP Error Message : redirect datagrams for the Network ";
  589.               -- format ICMP error message for ULP
  590.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  591.                     ULP_DESTINATION_PORT,
  592.                     ICMP_ERROR_MESSAGE);
  593.             
  594.             
  595.             when 1 => -- redirect datagrams for the Host
  596.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  597.                     ULP_DESTINATION_PORT,
  598.                     IHL);
  599.               -- load error message to be displayed by ULP
  600.         ICMP_ERROR_MESSAGE(1..54) := 
  601.           " ICMP Error Message : redirect datagrams for the Host ";
  602.               -- format ICMP error message for ULP
  603.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  604.                     ULP_DESTINATION_PORT,
  605.                     ICMP_ERROR_MESSAGE);
  606.             
  607.             
  608.             when 2 => -- redirect datagrams for the type of service and network
  609.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  610.                     ULP_DESTINATION_PORT,
  611.                     IHL);
  612.               -- load error message to be displayed by ULP
  613.         ICMP_ERROR_MESSAGE(1..76) := 
  614. "ICMP Error Message : redirect datagrams for the type of service and network ";
  615.               -- format ICMP error message for ULP
  616.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  617.                     ULP_DESTINATION_PORT,
  618.                     ICMP_ERROR_MESSAGE);
  619.             
  620.             when 3 => -- redirect datagrams for the type of service and host
  621.               OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  622.                     ULP_DESTINATION_PORT,
  623.                     IHL);
  624.               -- load error message to be displayed by ULP
  625.         ICMP_ERROR_MESSAGE(1..74) := 
  626. " ICMP Error Message : redirect datagrams for the type of service and host ";
  627.               -- format ICMP error message for ULP
  628.               PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  629.                     ULP_DESTINATION_PORT,
  630.                     ICMP_ERROR_MESSAGE);
  631.             when others =>
  632.         TEXT_IO.PUT_LINE(" Error message package UTILITIES_FOR_ICMP ");
  633. TEXT_IO.PUT_LINE( "procedure ICMP_MESSAGE_PROCESSOR case exhaustive error ");
  634.   TEXT_IO.PUT_LINE(" Bogus ICMP message #5 code field ");
  635.           end case;            
  636.       
  637.         
  638.         when 8 => -- Echo Message
  639.           ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + IHL_IN_OCTETS) := 0; 
  640.         -- Echo Reply Message Type
  641.           ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + IHL_IN_OCTETS + 1) := 0; 
  642.         -- Code field
  643.           IP_SOURCE_ADDRESS_TEMPORARY_SAVE_FRONT := 
  644.         ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 6);
  645.           IP_SOURCE_ADDRESS_TEMPORARY_SAVE_BACK := 
  646.         ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 7);
  647.           ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 6) := 
  648.             ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 8);
  649.           ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 7) :=
  650.             ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 9);
  651.           ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 8) := 
  652.             IP_SOURCE_ADDRESS_TEMPORARY_SAVE_FRONT;
  653.           ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + 9) :=
  654.             IP_SOURCE_ADDRESS_TEMPORARY_SAVE_BACK;
  655.           START_PTR_FOR_ICMP_CHECKSUM := IP_HEADER_POINTER + IHL_IN_OCTETS;
  656.           END_PTR_FOR_ICMP_CHECKSUM := IP_HEADER_POINTER + 
  657.         IP_DATAGRAM_TOTAL_LENGTH;
  658.           -- load icmp checksum
  659.           WORD_TO_CONVERT(1) := 
  660.             ICMP_CHECKSUM(START_PTR_FOR_ICMP_CHECKSUM,END_PTR_FOR_ICMP_CHECKSUM,
  661.             ICMP_MESSAGE);
  662.           TEMP := CONVERT_TO_TWO_BYTES(WORD_TO_CONVERT);
  663.           -- implementation dependent (VAX)
  664.           ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + IHL_IN_OCTETS + 2) := TEMP(2);
  665.           ICMP_MESSAGE.BYTE(IP_HEADER_POINTER + IHL_IN_OCTETS + 3) := TEMP(1); 
  666.           SEND_ICMP_MESSAGE(ICMP_MESSAGE);
  667.         
  668.         when 12 => -- Parameter Problem Message
  669.           OBTAIN_ULP_SOURCE_DESTINATION(ULP_SOURCE_PORT,
  670.                 ULP_DESTINATION_PORT,
  671.                 IHL);
  672.           -- load error message to be displayed by ULP
  673.           ICMP_ERROR_MESSAGE(1..48) := 
  674.         " ICMP Error Message : Parameter Problem Message ";
  675.           -- format ICMP error message for ULP
  676.           PACK_ICMP_MESSAGE_FOR_ULP(ULP_SOURCE_PORT,
  677.                 ULP_DESTINATION_PORT,
  678.                 ICMP_ERROR_MESSAGE);
  679.         
  680.         when 13 => -- Timestamp Message
  681.           -- not implemented
  682.           null;
  683.         
  684.         when 14 => -- Timestamp Message Reply
  685.           -- not implemented
  686.           null;
  687.         
  688.         when 15 => -- Information Request Message
  689.           -- not implemented
  690.           null;
  691.         
  692.         when 16 => -- Information Reply
  693.           -- not implemented
  694.           null;
  695.         when others =>
  696. TEXT_IO.PUT_LINE(" Error message package UTILITIES_FOR_ICMP ");
  697. TEXT_IO.PUT_LINE( "procedure ICMP_MESSAGE_PROCESSOR case exhaustive error ");
  698.   TEXT_IO.PUT_LINE(" Bogus ICMP type ");
  699.       end case;
  700.     else
  701.       if BUFPTR.PROT /= 1 then
  702.         --for fault tolertant software reliability to protect against users of 
  703.     --package this should never happen if package is understood by user or 
  704.     --runtime system is functionally properly
  705.         TEXT_IO.PUT_LINE("Error message : package UTILITES_FOR_ICMP  ");
  706.     TEXT_IO.PUT_LINE( "procedure ICMP_MESSAGE_PROCESSOR");
  707.         TEXT_IO.PUT_LINE("procedure called with wrong protocol number");
  708.       end if;
  709.       if CHECK_ICMP_CHECKSUM = BAD then
  710.         TEXT_IO.PUT_LINE("Error message : package UTILITES_FOR_ICMP  ");
  711.     TEXT_IO.PUT_LINE( "procedure ICMP_MESSAGE_PROCESSOR");
  712.         TEXT_IO.PUT_LINE("ICMP_CHECKSUM  message was BAD");
  713.       end if;
  714.     end if;
  715.   end ICMP_MESSAGE_PROCESSOR;
  716. end UTILITIES_FOR_ICMP;
  717. --::::::::::::::
  718. --iparrive.txt
  719. --::::::::::::::
  720. -----------------------------------------------------------------------
  721. --
  722. --         DoD Protocols    NA-00008-200       80-01177-100(-)
  723. --         E-Systems, Inc.  August 07, 1985
  724. --
  725. --         iparrive.txt       Author : Jim Baldo
  726. --
  727. -----------------------------------------------------------------------
  728. with BUFFER_DATA;        use BUFFER_DATA;
  729. --WITH COMMUNICATE_AND_QUEUE;
  730. --USE COMMUNICATE_AND_QUEUE;
  731.             package IP_ARRIVE_PROCESSING is
  732.         -----------------------------------------------------
  733.         --This implementation is for use with the Telesoft --
  734.         --Ada compiler version 1.5 .                       --
  735.         -----------------------------------------------------
  736. ------------------------------------------------------------------------------
  737. -- THIS PACKAGE IS RESPONSIBLE FOR PROCESSING AN ARRIVED DATAGRAM RECEIVED  --
  738. -- FROM THE CHANNEL PROTOCOL MODULE.                                        --
  739. ------------------------------------------------------------------------------
  740.     procedure IP_DATAGRAM_ARRIVE(PACKED_BUFF : in out PACKED_BUFFER_PTR;
  741.                  BYTE_COUNT : in out SIXTEEN_BITS);
  742.         --This subprogram is called by the ip controller when a 
  743.         --datagram arrives for the IP.
  744. end IP_ARRIVE_PROCESSING;
  745. with UNCHECKED_CONVERSION;
  746. with SYSTEM;
  747. with TEXT_IO;                   use TEXT_IO;
  748. with IP_GLOBALS;        use IP_GLOBALS;
  749. with WITH_TCP_COMMUNICATE;    use WITH_TCP_COMMUNICATE;
  750. with IP_UNPACK_AND_PACK_UTILITIES; use IP_UNPACK_AND_PACK_UTILITIES;
  751. with UTILITIES_FOR_ICMP;
  752. with REASSEMBLY_UTILITIES;
  753.         
  754.                 package body IP_ARRIVE_PROCESSING is
  755. function PHYSICAL_ADDRESS is new UNCHECKED_CONVERSION(THIRTYTWO_BITS,
  756.                               SYSTEM.ADDRESS);
  757. PRINT_DATAGRAM_FLAG : SIXTEEN_BITS := 1;--for debug
  758. PRINT_FLAG : SIXTEEN_BITS := 1;--for debug
  759.  procedure IP_DATAGRAM_ARRIVE(PACKED_BUFF : in out PACKED_BUFFER_PTR;
  760.                               BYTE_COUNT : in out SIXTEEN_BITS) is
  761.     --This subprogram will accept an arrived datagram check it for 
  762.     --correctness and if correct return it to the user layer 
  763.     --(TCP in our case).
  764.     --
  765.     -- RESTRICTIONS :
  766.     --
  767.     --We do not do any fragment reassembly or any option processing, 
  768.     --other than the options required by the TCP (security and precedence.)
  769. type INT_ARRAY is array(1..1) of SIXTEEN_BITS;
  770. type TWO_BYTES is array(1..2) of SYSTEM.BYTE;
  771. function CONVERT_TO_INTEGER is new
  772.      UNCHECKED_CONVERSION(TWO_BYTES, INT_ARRAY);
  773. BUF_CSUM : TWO_BYTES;
  774. CARRIED_CSUM : INT_ARRAY;
  775. SECURITY_OPTION : SECURITY_OPTION_TYPE;
  776. X, IP_LENGTH_IN_OCTETS, HEADER_CHECKSUM : SIXTEEN_BITS;
  777. I : SIXTEEN_BITS := 1;
  778. DESTINATION_FAKE_HOST : BOOLEAN := FALSE; -- TEMPORARY FOR TEST ***
  779. BAD_OPTION : BOOLEAN := FALSE;
  780. BUFPTR : BUFFER_POINTER;
  781. OPTIONS_EXIST : BOOLEAN;
  782. TASK_MESSAGE : MESSAGE;
  783. IP_PARAMS : SEG_ARRIVE_PARAMS;
  784. BUFFTYPE : SIXTEEN_BITS; -- CURRENTLY IGNORED.
  785. --OUTPUT : SIXTEEN_BITS := 0;
  786. OUTPUT : FILE_TYPE;
  787. REASSEMBLY_TABLE_ELEMENT : 
  788.     REASSEMBLY_UTILITIES.REASSEMBLY_TABLE_POINTER;
  789.     
  790.     function ADDRESS_FOR_ME(ADDRESS : in THIRTYTWO_BITS) return BOOLEAN is
  791.     RESULT : BOOLEAN := FALSE;
  792.     begin
  793.         --REMOVE
  794.         RESULT := TRUE;
  795.         return RESULT;
  796.         --REMOVE
  797.         for I in 1..MAX_HOSTS loop
  798.         
  799.        --***DID EXPLICIT TYPE CONVERSION TO PROVIDE CLEAN COMPILE, KELLI
  800.                 
  801.                 if ADDRESS = THIRTYTWO_BITS(MY_IP_ADDRESS(I)) then
  802.             RESULT := TRUE;
  803.         
  804.                 end if;
  805.         end loop;
  806.         return RESULT;
  807.     end ADDRESS_FOR_ME;
  808.     function ADDRESS_LEGAL(X : THIRTYTWO_BITS) return BOOLEAN is
  809.         --This function searches a table in the IP global package for 
  810.         --the address.  All legal addresses are in there.  If the 
  811.         --address is correct a value of true is returned false 
  812.         --otherwise.
  813.     RESULT : BOOLEAN := FALSE;
  814.     I : SIXTEEN_BITS := 1;
  815.     begin
  816.         while I <= NUMBER_OF_ADDRESSES and (not RESULT) loop
  817.             if X = VALID_ADDRESS_LIST(I) then
  818.                 RESULT := TRUE;
  819.             end if;
  820.             I := I + 1;
  821.         end loop;
  822.         return RESULT;
  823.     exception
  824.         when CONSTRAINT_ERROR =>
  825.             PUT_LINE("CONSTRAINT ERROR IN THE ADDRESS CHECKER");
  826.             INTEGER_IO.PUT(I);
  827.         when others =>
  828.             PUT_LINE("UNKNOWN ERROR IN THE ADDRESS CHECKER");
  829.     end ADDRESS_LEGAL;
  830.  
  831.     begin
  832.         -- IP_LENGTH_IN_OCTETS := BUFPTR.IHL * 4;
  833.         -- IT WILL WORK FOR HIGH BET SET IN A BYTE.
  834.         IP_LENGTH_IN_OCTETS := (PACKED_BUFF.BYTE(PACKED_BUFF.IP_PTR) 
  835.             MOD 16)    * 4; -- LOW 4 BITS. * 4 BYTES PER 32 BITS.
  836.         -- NOTE UPPER BOUND MUST BE MOVED LATER.
  837.                 if IP_LENGTH_IN_OCTETS >= 20 AND (IP_LENGTH_IN_OCTETS <= 60) 
  838.                         then -- OK 
  839.                   HEADER_CHECKSUM := CHECKSUM(PACKED_BUFF.IP_PTR, 
  840.                     IP_LENGTH_IN_OCTETS, PACKED_BUFF);
  841.                   BUF_CSUM(1) := PACKED_BUFF.BYTE(PACKED_BUFF.IP_PTR+11);
  842.                                                         -- FIRST BYTE OF CSUM
  843.                         BUF_CSUM(2) := PACKED_BUFF.BYTE(PACKED_BUFF.IP_PTR+10);
  844.                             -- LOW BYTE OF CSUM
  845.             CARRIED_CSUM := CONVERT_TO_INTEGER(BUF_CSUM);
  846.                         
  847.         else --ERROR
  848.             PUT_LINE("BAD IP LENGTH");
  849.             HEADER_CHECKSUM := 0;
  850.             CARRIED_CSUM(1) := 4;
  851.         end if;
  852.                 BUFPTR := IP_UNPACK_AND_PACK_UTILITIES.UNPACK
  853.                 (PACKED_BUFF); -- UNPACK IT.
  854.                 if HEADER_CHECKSUM = CARRIED_CSUM(1) then
  855.                  BUFPTR := IP_UNPACK_AND_PACK_UTILITIES.UNPACK
  856.                 (PACKED_BUFF); -- UNPACK IT.
  857.             -- SET OPTIONS EXIST FLAG.
  858.             -- TESTING
  859.             -- FOR VAX TESTING *****************
  860.             PRINT_DATAGRAM_FLAG := 0;
  861.             OPTIONS_EXIST := BUFPTR.IP_OPTIONS(1) /= 0;
  862.             if ADDRESS_LEGAL(BUFPTR.DEST) and 
  863.             ADDRESS_LEGAL(BUFPTR.SOURCE) then
  864.               if ADDRESS_FOR_ME(BUFPTR.DEST)  then
  865.                 -- IT'S FOR ME.
  866.               if BUFPTR.TTL > 0 then -- WE CAN PROCESS IT.
  867.                -- ONLY IF WE ARE PASSING IT ON WHICH WE 
  868.                --CURRENTLY DO NOT.
  869.                --/ DECREMENT TTL BY THE TIME IT TAKES TO 
  870.                    --DO INTERNET PROCESSING /***
  871.                    -- DO ALL NECESSARY OPTION CHECKING
  872.                while OPTIONS_EXIST loop
  873.                 case BUFPTR.IP_OPTIONS(I) is
  874.                  -- THE OPTION TYPE IS?
  875.                  when 0 => OPTIONS_EXIST := FALSE;
  876.                  when 1 => I := I + 1; -- A NO OPERATION.
  877.                  when 130 => 
  878.                   -- SECURITY, COMPARTMENTS, HANDLING 
  879.                   --RESTRICTIONS, AND
  880.                   -- TRANSMISSION CONTROL CODE OPTION.
  881.                   if BUFPTR.IP_OPTIONS(I + 1) = 11 and 
  882.                   (BUFPTR.IP_OPTIONS(I + 2) <= 7) and
  883.                   (BUFPTR.IP_OPTIONS(I + 3) <= 7) and 
  884.                   (BUFPTR.IP_OPTIONS(I + 2) >= 0) and
  885.                   (BUFPTR.IP_OPTIONS(I + 3) >= 0) and 
  886.                   (BUFPTR.IP_OPTIONS(I + 4) = 0)  and
  887.                   (BUFPTR.IP_OPTIONS(I + 5) = 0)  and
  888.                   (BUFPTR.IP_OPTIONS(I + 2) = 
  889.                   BUFPTR.IP_OPTIONS(I + 3)) then
  890.                    -- WE ARE OK. A GOOD OPTION
  891.                    -- SET UP SECURITY OPTION FOR TCP.
  892.                    for INDEX in I+2..I+10 loop
  893.                 SECURITY_OPTION(INDEX - I - 1) := 
  894.                         BUFPTR.IP_OPTIONS(INDEX);
  895.                    end loop;
  896.                    I := I + 11;
  897.                   else
  898.                    BAD_OPTION := TRUE;
  899.                    OPTIONS_EXIST := FALSE;
  900.                   end if;
  901.                  when 131 => -- LOOSE SOURCE AND RECORD 
  902.                   -- ROUTE FROM THE SOURCE
  903.                   -- ONLY FOR GATEWAYS OR RELAYS 
  904.                   -- AND WE ARE CURRENTLY NOT ONE.
  905.                   I := I + BUFPTR.IP_OPTIONS(I + 1);
  906.                  when 137 => -- STRICT SOURCE AND RECORD 
  907.                   -- ROUTE. INFORMATION TO BE
  908.                   -- USED BY GATEWAYS AND TO 
  909.                   -- RECORD THE ROUTE INFORMATION
  910.                   -- WE ARE NOT A GATEWAY NOR DO 
  911.                   -- WE PASS STUFF ON.
  912.                   I := I + BUFPTR.IP_OPTIONS(I + 1);
  913.                  when 7  => -- SAVE THE RETURN ROUTE, 
  914.                   -- UNNECESSARY IF NOT A RELAY.
  915.                   -- PUT OUR ADDRESS IN AT PROPER 
  916.                   -- POINT. MOVE OTHER DATA 
  917.                   -- BEHIND ADDRESS TO ENABLE IT 
  918.                   -- TO BE PUT IN. IF THIS
  919.                   -- FORCES TO USE PART OF A 32 
  920.                   -- BIT FIELD THEN DO ANY
  921.                   -- PADDING NECESSARY.
  922.                   I := I + BUFPTR.IP_OPTIONS(I + 1);
  923.                  when 136 =>  -- STREAM IDENTIFIER
  924.                   -- ACTION TBD.
  925.                   I := I + 4;
  926.                  when 68  => -- INTERNET TIMESTAMP
  927.                   -- ACTION TBD.
  928.                   I := I + BUFPTR.IP_OPTIONS(I + 1);
  929.                  when others => BAD_OPTION := TRUE;
  930.                   OPTIONS_EXIST := FALSE;
  931.                 end case;
  932.                end loop;
  933.               if not BAD_OPTION then
  934.                if DESTINATION_FAKE_HOST then
  935.                 -- /PUT IN FAKE HOST QUEUE/
  936.                 null;
  937.                else
  938.                 -- HERE WE GIVE THE DATAGRAM TO THE TO TCP 
  939.                 -- QUEUE TASK. THIS NOTIFIES
  940.                 -- THE TCP OF A DATAGRAM AS PER THE SPEC. 
  941.                 -- TCP TAKING IT OUT OF THE
  942.                 -- QUEUE IS DOING AN IMPLICIT CALL ON THE 
  943.                 -- IP. THE NECESSARY PARAMETERS
  944.                 -- WILL BE IN THE QUEUE RECORD.
  945.                 -- ALL REQUIRED FIELDS ARE IN THE BUFFER 
  946.                 -- EXCEPT FOR THE LENGTH WHICH
  947.                 -- IS EXPLICITLY RETURNED.
  948.                 -- SET THE BYTE COUNT. THIS IS THE TCP 
  949.                 -- LENGTH IN OCTETS.
  950.                 BYTE_COUNT := BUFPTR.TOT_LEN - (BUFPTR.IHL * 4);
  951. --                if PRINT_FLAG /= 0 then
  952. --                 PUT_LINE("THE POINTER FOR THE BUFFER TO TCP");
  953. --                 INTEGER_IO.PUT(PACKED_BUFF.TCP_PTR);
  954. --                end if;
  955.                 if BUFPTR.PROT =1 then
  956.                  UTILITIES_FOR_ICMP.ICMP_MESSAGE_PROCESSOR
  957.                  (PACKED_BUFF,BUFPTR);
  958.                 end if;
  959.                 if REASSEMBLY_UTILITIES.A_FRAG
  960.                  (PACKED_BUFF,BUFPTR) = REASSEMBLY_UTILITIES.NO 
  961.                  then
  962.                  IP_PARAMS := ( PACKED_BUFF, 
  963.                                             BYTE_COUNT, 
  964.                                 BUFPTR.SOURCE, 
  965.                                             BUFPTR.DEST, 
  966.                                 BUFPTR.PROT, 
  967.                                             BUFPTR.TOS, 
  968.                                             SECURITY_OPTION);
  969.                  TASK_MESSAGE := (DATA_FROM_IP, IP_PARAMS);
  970.                  MESSAGE_FOR_TCP(TASK_MESSAGE);--SEND TO THE TCP
  971.                  --if PRINT_FLAG /= 0 then
  972.                   --PUT("A GOOD MESSAGE FOR THE TCP");
  973.                  --end if;
  974.                 else
  975.                  REASSEMBLY_UTILITIES.REASSEMBLY
  976.                   (PACKED_BUFF,REASSEMBLY_TABLE_ELEMENT,BUFPTR);
  977.                  if REASSEMBLY_UTILITIES.REASS_DONE
  978.                   (REASSEMBLY_TABLE_ELEMENT,BUFPTR) = 
  979.                 REASSEMBLY_UTILITIES.YES then
  980.                   IP_PARAMS := (PACKED_BUFF, BYTE_COUNT, 
  981.                   BUFPTR.SOURCE, BUFPTR.DEST, 
  982.                   BUFPTR.PROT, BUFPTR.TOS, SECURITY_OPTION);
  983.                   TASK_MESSAGE := (DATA_FROM_IP, IP_PARAMS);
  984.                   --SEND TO THE TCP.
  985.                   MESSAGE_FOR_TCP(TASK_MESSAGE);
  986.                   --if PRINT_FLAG /= 0 then
  987.                    --PUT(OUTPUT,"A GOOD MESSAGE FOR THE TCP");
  988.                   --end if;
  989.                  end if;
  990.                 end if;
  991.                end if;
  992.               else
  993.                --/ERROR EXIT: ILLEGAL OPTION/
  994.                -- DELETE DATAGRAM
  995.                PUT(OUTPUT,"BAD OPTION");--**TESTING
  996.                BUFFREE(PACKED_BUFF, BUFFTYPE);
  997.               end if;
  998.              else
  999.               -- WE HAVE TIMED OUT SO DROP THE DATAGRAM.
  1000.               PUT(OUTPUT, "TIMED OUT");--** TESTING
  1001.               BUFFREE(PACKED_BUFF, BUFFTYPE);
  1002.              end if;
  1003.             else
  1004.              -- /ERROR EXIT: NOT FOR ME/ 
  1005.              -- DELETE DATAGRAM
  1006.              PUT(OUTPUT,"NOT FOR ME");--- DEBUG
  1007.              BUFFREE(PACKED_BUFF, BUFFTYPE);
  1008.                 end if;
  1009.                else
  1010.             -- / ERROR: ILLEGAL DESTINATION/
  1011.             PUT(OUTPUT,"BAD DEST, OR AN INVALID SOURCE ADDRESS");
  1012.             BUFFREE(PACKED_BUFF, BUFFTYPE);
  1013.                end if;
  1014.               else 
  1015.                -- BAD CHECKSUM. COUNT IT AND GET OUT
  1016.                PUT("BAD CHECKSUM");
  1017.                BAD_CHECKSUM := BAD_CHECKSUM + 1;
  1018.                BUFFREE(PACKED_BUFF, BUFFTYPE);
  1019.               end if;
  1020.               --if PRINT_FLAG /= 0 then
  1021.                --PUT_LINE("END OF PACKET");
  1022.                    --NEW_LINE; -- ** TESTING ON VAX
  1023.               --end if;
  1024. exception
  1025.     when CONSTRAINT_ERROR =>
  1026.         PUT_LINE("CONSTRAINT ERROR IN IPARRIVE");
  1027.         INTEGER_IO.PUT(I);
  1028.     when others =>
  1029.         PUT_LINE("ERROR IN IPARRIVE");---DEBUG
  1030.         raise;
  1031. end IP_DATAGRAM_ARRIVE;
  1032. END IP_ARRIVE_PROCESSING; -- PACKAGE
  1033. --::::::::::::::
  1034. --ipcntsnd.txt
  1035. --::::::::::::::
  1036. -----------------------------------------------------------------------
  1037. --
  1038. --         DoD Protocols    NA-00008-200       80-01178-100(-)
  1039. --         E-Systems, Inc.  August 07, 1985
  1040. --
  1041. --         ipcntsnd.txt       Author : Jim Baldo
  1042. --
  1043. -----------------------------------------------------------------------
  1044.     package INTERNET_PROTOCOL_CONTROL_AND_SEND_PROCESSING is
  1045.     -----------------------------------------------------------
  1046.     --This implementation is for use with the Telesoft ada   --
  1047.         --compiler version 1.3d .                                --
  1048.     -----------------------------------------------------------
  1049. -----------------------------------------------------------------------------
  1050. -- THIS PACKAGE WILL CONTAIN THE INTERNET CONTROLLER TASK AS WELL AS       --
  1051. -- ALL PROCEDURES AND FUNCTIONS NECESSARY FOR IP TO TRANSMIT A DATAGRAM    --
  1052. -- PER A TCP REQUEST.                                                      --
  1053. -----------------------------------------------------------------------------
  1054.   procedure IP_CONTROLLER;
  1055.     --This subprogram gets a message from the communicate and queue 
  1056.     --procedure it then decodes the message and calls the appropriate 
  1057.     --procedure or function to perform the necessary action.
  1058. end INTERNET_PROTOCOL_CONTROL_AND_SEND_PROCESSING;
  1059. with IP_UNPACK_AND_PACK_UTILITIES;      use IP_UNPACK_AND_PACK_UTILITIES;
  1060. with UNCHECKED_CONVERSION;
  1061. with TEXT_IO;                           use TEXT_IO, INTEGER_IO ;
  1062. with IP_ARRIVE_PROCESSING;              use IP_ARRIVE_PROCESSING;
  1063. with IP_GLOBALS;                        use IP_GLOBALS;
  1064. with WITH_IP_COMMUNICATE;               use WITH_IP_COMMUNICATE;
  1065. with WITH_TCP_COMMUNICATE;              use WITH_TCP_COMMUNICATE;
  1066. with BUFFER_DATA;                       use BUFFER_DATA;
  1067. with SUBNET_CALLS;                      use SUBNET_CALLS;
  1068. with SYSTEM;---DEBUG
  1069.     
  1070.         package body INTERNET_PROTOCOL_CONTROL_AND_SEND_PROCESSING is
  1071.    
  1072.   procedure IP_ERROR_HANDLER(ERROR_NUMBER : SIXTEEN_BITS) is
  1073.     --This subprogram will be called to handle errors that occur during 
  1074.     --the course of IP processing.
  1075.   begin
  1076.     PUT_LINE("IP ERROR HANDLER WAS CALLED");
  1077.   end IP_ERROR_HANDLER; 
  1078.   
  1079.   procedure SEND_IP(SRC, DEST : THIRTYTWO_BITS; 
  1080.                     TOS, TTL : SIXTEEN_BITS; 
  1081.                     PACKED_BUFF : in out PACKED_BUFFER_PTR; 
  1082.                     LEN, ID, DF : SIXTEEN_BITS; 
  1083.                     OPTIONS : in IP_GLOBALS.OPTION_TYPE) is
  1084.     --This subprogram takes a segment from the user layer(TCP) and wraps 
  1085.     --it in a datagram. It checks to make sure a viable call has been 
  1086.     --made.  It will send a formatted datagram to the subnet protocol 
  1087.     --SUBNET.  It is called by the IP controller after the TCP has 
  1088.     --requested that a segment be sent wrapped in a datagram.  The 
  1089.     --following is a description of the parameters:
  1090.     --
  1091.     --   SRC - THE SOURCE ADDRESS OF THE DATAGRAM.
  1092.     --   DEST - THE DESTINATION OF THE DATAGRAM.
  1093.     --   TOS - THE TYPE OF SERVICE DESIRED BY THE TCP(USER APPLICATION).
  1094.     --   TTL - THE TIME TO LIVE FOR THE DATAGRAM.
  1095.     --   LEN - THE NUMBER OF OCTETS IN THE BUFFER.
  1096.     --   ID - VARIABLE THAT IS SET BY THE SENDER TO HELP IN REASSEMBLING 
  1097.     --        FRAGMENTS.
  1098.     --   DF - THE DONT FRAGMENT BIT. ALWAYS SET IN OUR CASE.
  1099.     --   OPTIONS - THE ARRAY THAT CONTAINS THE OPTIONS THAT THE TCP OR 
  1100.     --             USER WISHES TO HAVE IMPLEMENTED.
  1101.   type TEST_RESULT is (CORRECT, INCORRECT);
  1102.   ROUTINE_VAR : PRECEDENCE_TYPE := ROUTINE;
  1103.   NORMAL_REL_VAR : RELIABILITY_TYPE := NORMAL;
  1104.   NORMAL_DEL_VAR : DELAY_TYPE := NORMAL;
  1105.   NORMAL_THRO_VAR : THROUGHPUT_TYPE := NORMAL;
  1106.   TASK_MESSAGE : MESSAGE;
  1107.   IP_PARAMS : SEG_ARRIVE_PARAMS;
  1108.   BUFPTR : IP_GLOBALS.BUFFER_POINTER;
  1109.   BYTE_COUNT : SIXTEEN_BITS := 0;
  1110.   CURRENT_VERSION : constant SIXTEEN_BITS := 4;
  1111.   TCP : constant SIXTEEN_BITS := 5;
  1112.   INDEX : SIXTEEN_BITS := 1;
  1113.   ERROR : SIXTEEN_BITS;
  1114.   PROPER_DESTINATION, OPTION_CHECK : TEST_RESULT;
  1115.   OPTIONS_REQUESTED_BY_IP_EXIST : BOOLEAN := FALSE;-- NONE NOW
  1116.   TCP_OPTIONS : WITH_TCP_COMMUNICATE.SECURITY_OPTION_TYPE ;
  1117.     
  1118.     function OPTION_CHECKER
  1119.       ( OPTIONS : IP_GLOBALS.OPTION_TYPE) return TEST_RESULT is
  1120.         --This function will check that the options have been 
  1121.         --correctly supplied in the option array.  It will return the 
  1122.         --result of the test.
  1123.         --The security values have been mapped to the integers in the 
  1124.         --following manner:
  1125.         --
  1126.         --   00000000 00000000 - UNCLASSIFIED => 0
  1127.         --   11110001 00110101 - CONFIDENTIAL => 1
  1128.         --   01111000 10011010 - EFTO => 2
  1129.         --   10111100 01001101 - MMMM  => 3
  1130.         --   01011110 00100110 - PROG => 4
  1131.         --   10101111 00010011 - RESTRICTED => 5
  1132.         --   11010111 10001000 - SECRET => 6
  1133.         --   01101011 11000101 - TOP SECRET => 7
  1134.     RESULT : TEST_RESULT := CORRECT;
  1135.     OPTION_NOT_CORRECT, OPTIONS_EXIST : BOOLEAN;
  1136.     I : SIXTEEN_BITS := 1;
  1137.     begin
  1138.       while OPTIONS(I) /= 0 and then (RESULT = CORRECT) loop
  1139.       -- WE MUST DETERMINE THE TYPE AND CHECK THE TYPE 
  1140.       --VALIDITY.
  1141.         case OPTIONS(I) is
  1142.           when 1 => null;
  1143.           when 130 => -- SECURITY OPTION
  1144.             if OPTIONS(I + 1) /= 11 then
  1145.               RESULT := INCORRECT;
  1146.             else
  1147.               case OPTIONS(I + 2) is
  1148.              -- 0 - 7 MAP TO THE 8 
  1149.              --LEGAL VALUES FOR SECURITY.
  1150.               when 0 | 1 |2 | 3 | 4 | 5 
  1151.               | 6 | 7 => null;
  1152.               when others =>  
  1153.                RESULT := INCORRECT;
  1154.               end case;
  1155.               if RESULT = CORRECT then
  1156.                case OPTIONS(I + 3) is
  1157.                            -- 0 - 7 MAP TO THE 8 LEGAL 
  1158.                --VALUES FOR SECURITY.
  1159.                 when 0 | 1 | 2 | 3 | 4 
  1160.                  | 5 | 6 | 7 => null;
  1161.                 when others =>  
  1162.                  RESULT := INCORRECT;
  1163.                 end case;
  1164.               end if;
  1165.                     if RESULT = CORRECT and 
  1166.                     (OPTIONS(I + 4) = 0) and 
  1167.               (OPTIONS(I + 5) = 0)
  1168.                     then
  1169.                if OPTIONS(I + 2) /= OPTIONS(I 
  1170.                + 3) then
  1171.                 RESULT := INCORRECT;
  1172.                end if;
  1173.               else
  1174.                RESULT := INCORRECT;
  1175.               end if;
  1176.               -- HERE WE WOULD CHECK OTHER 
  1177.               --FIELDS WHICH ARE CURRENTLY 
  1178.               --UNKNOWN IN FORMAT
  1179.               I := I + 11;
  1180.                    end if;
  1181.                   when 131 | 137 | 7 => 
  1182.             -- LOOSE SOURCE AND RECORD 
  1183.             --ROUTE, STRICT SOURCE AND 
  1184.             --RECORD ROUTE,  AND RECORD 
  1185.             --ROUTE OPTIONS RESPECTIVELY.
  1186.             -- WE WILL CHECK FOR A VALID 
  1187.             --POINTER.
  1188.              if (OPTIONS(I + 2) < 4) or 
  1189.              (OPTIONS(I + 2) > 
  1190.              (OPTIONS(I + 1) + 1)) then
  1191.               RESULT := INCORRECT;
  1192.              end if;
  1193.              I := I + OPTIONS(I +1); 
  1194.              --UPDATE THE INDEX.
  1195.             when 136 => 
  1196.             -- STREAM IDENTIFIER
  1197.             -- CHECK FOR PROPER LENGTH. WE 
  1198.             --DON'T KNOW WHAT THE PROPER 
  1199.             --STREAM ID IS.
  1200.              if OPTIONS(I + 1) /= 4 then
  1201.               RESULT := INCORRECT;
  1202.              end if;
  1203.              I := I + 4; -- ADVANCE INDEX
  1204.             when 68 => 
  1205.             -- THE INTERNET TIMESTAMP OPTION
  1206.             -- CHECK LENGTH AND POINTER
  1207.              if OPTIONS(I + 1) >= 40 or 
  1208.              (OPTIONS(I + 1) < 12) then
  1209.               RESULT := INCORRECT;
  1210.              elsif OPTIONS(I + 2) < 5 then
  1211.               RESULT := INCORRECT;
  1212.              end if;
  1213.              I := I + OPTIONS(I + 1); 
  1214.              -- ADVANCE INDEX
  1215.             when others => -- A BAD TYPE
  1216.              RESULT := INCORRECT;
  1217.         end case;
  1218.       end loop;
  1219.     return RESULT;
  1220.     end OPTION_CHECKER;
  1221.     function DESTINATION_CHECK
  1222.       (DEST : THIRTYTWO_BITS) return TEST_RESULT is
  1223.     
  1224.         --This subprogram will check that the requested destination is 
  1225.         --legal.
  1226.     RESULT : TEST_RESULT := INCORRECT;
  1227.     DONE : BOOLEAN := FALSE;
  1228.     I : SIXTEEN_BITS := 1;
  1229.     begin
  1230.       while I <= NUMBER_OF_ADDRESSES and (not DONE) loop
  1231.         if DEST = VALID_ADDRESS_LIST(I) then
  1232.           RESULT := CORRECT;
  1233.           DONE := TRUE;
  1234.         end if;
  1235.         -- NEXT ENTRY
  1236.         I := I + 1;
  1237.       end loop;
  1238.       return RESULT;
  1239.     end DESTINATION_CHECK;
  1240.     function OPTION_OCTETS(X : IP_GLOBALS.OPTION_TYPE) 
  1241.                                                   return SIXTEEN_BITS is
  1242.         --Option_octets will determine how many option octets there 
  1243.         --are in an IP header.  It determines the number by looking 
  1244.         --at the length field of each existent option type and adding 
  1245.         --them up.  The total is then returned to  the caller.  This 
  1246.         --routine knows the option format.  One octet is contained
  1247.         --in each element of the option array x.
  1248.     I : SIXTEEN_BITS := 1;
  1249.     OCTET_COUNT : SIXTEEN_BITS := 0;
  1250.     OPTION_LENGTH : SIXTEEN_BITS;
  1251.     begin
  1252.       -- WE WILL PUT ONE OCTET IN PER 16 BITS.
  1253.       while X(I) /= 0 and then (X(I + 1) > 0) loop
  1254.         OPTION_LENGTH := X(I + 1);
  1255.         OCTET_COUNT := OCTET_COUNT + OPTION_LENGTH;
  1256.         I := I + X(I + 1); -- NEXT OPTION FIELD.
  1257.       end loop;
  1258.       if OCTET_COUNT /= ((OCTET_COUNT/4)*4) then
  1259.         OCTET_COUNT := ((OCTET_COUNT/4) + 1) * 4; 
  1260.             -- PAD WITH OCTETS.
  1261.       end if;
  1262.       return OCTET_COUNT;
  1263.     end OPTION_OCTETS;
  1264.   
  1265.   begin
  1266.   -- CHECK ALL PARAMETERS ON SEND CALL HERE. ARE ANY NOT CHECKED??
  1267.     PROPER_DESTINATION := DESTINATION_CHECK(DEST);
  1268.     ERROR := 0;
  1269.     if PROPER_DESTINATION = INCORRECT then
  1270.       ERROR := 1;
  1271.     elsif (TOS > 256) or (TOS < 0) then
  1272.       ERROR := 2;
  1273.     elsif (TTL > 255) or (TTL < 0) then -- TIMES ARE IN SECONDS.
  1274.       ERROR := 3;
  1275.     else 
  1276.       OPTION_CHECK := OPTION_CHECKER(OPTIONS);
  1277.       if OPTION_CHECK = INCORRECT then
  1278.         ERROR := 4;
  1279.       end if;
  1280.     end if;
  1281.     if ERROR /= 0 then
  1282.       NEW_LINE;
  1283.       PUT("BAD PACKET FOR TRANSMIT"); --** TEMP
  1284.       INTEGER_IO.PUT( ERROR); --** TEMP
  1285.       NEW_LINE;
  1286.       PACKED_BUFF.IN_USE := FALSE;
  1287.       BUFFREE(PACKED_BUFF, 1); -- TEMPORARY FOR TEST**
  1288.       IP_ERROR_HANDLER(ERROR);
  1289.     else
  1290.       -- FORMAT AN IP HEADER
  1291.       BUFPTR.VERSION := CURRENT_VERSION;
  1292.       BUFPTR.TOS := TOS;
  1293.       BUFPTR.ID := ID;
  1294.       BUFPTR.FLAGS := 2; 
  1295.       -- REALLY THREE BITS (010) MEANS DONT FRAGMENT.
  1296.       BUFPTR.FRAG_OFFSET := 0; -- WE DO NOT FRAGMENT.
  1297.       BUFPTR.TTL := TTL; -- TIME TO LIVE (TBD)
  1298.       BUFPTR.PROT := TCP; -- PROTOCOL NUMBERS DEFINED IN RFC 870
  1299.       BUFPTR.SOURCE := SRC;
  1300.       BUFPTR.DEST := DEST;
  1301.       -- SET UP TRANSMIT OPTIONS AS REQUESTED BY THE ABOVE 
  1302.       --LAYER(TCP). COPY ARRAY.
  1303.       BUFPTR.IP_OPTIONS := OPTIONS;
  1304.  
  1305.       -- CURRENTLY IP WILL NOT REQUEST ANY OPTIONS. LATER 
  1306.       -- SWITCHES MAY BE SET. TO CAUSE OPTIONS TO BE USED.
  1307.       while OPTIONS_REQUESTED_BY_IP_EXIST loop
  1308.       --/PUT IN ANY NEW OPTIONS IN THE PROPER PLACE/
  1309.       --/ INCREMENT OPTIONS_OCTET COUNT THE PROPER AMOUNT./
  1310.         null;
  1311.       end loop;
  1312.       -- SET UP THE INTERNET HEADER LENGTH
  1313.       BUFPTR.IHL := 5 + OPTION_OCTETS(BUFPTR.IP_OPTIONS)/4;
  1314.       BUFPTR.TOT_LEN := (BUFPTR.IHL * 4) + LEN; 
  1315.         -- THE TOTAL NUMBER OF OCTETS IN THE
  1316.               -- DATAGRAM INCLUDING HEADER AND DATA.
  1317.       -- DETERMINE AND FILL IN THE CHECKSUM. DONE ON THE PACK
  1318.       -- PACK THE BUFFER UP
  1319.       IP_UNPACK_AND_PACK_UTILITIES.PACK_BUFFER_INTO_BIT_STREAM
  1320.         (BUFPTR, PACKED_BUFF);
  1321.       --/ SEND IT ON TO THE CHANNEL PROTOCOL MODULE/
  1322.      SNP.SEND (PACKED_BUFF, 
  1323.                LOCAL_ADDRESS_TYPE( DEST ),
  1324.                ROUTINE_VAR,
  1325.                NORMAL_REL_VAR,
  1326.                NORMAL_DEL_VAR,
  1327.                NORMAL_THRO_VAR,
  1328.                DATAGRAM_LENGTH( BUFPTR.TOT_LEN ) );
  1329.     end if;
  1330.   exception
  1331.     when CONSTRAINT_ERROR => 
  1332.     PUT_LINE("CONSTRAINT ERROR IN SEND_IP ROUTINE OF IP SYSTEM");
  1333.     when others => 
  1334.       PUT_LINE("ERROR IN SEND_IP ROUTINE OF IP SYSTEM");
  1335.   end SEND_IP;
  1336.   procedure IP_CONTROLLER is
  1337.     --This subprogram is responsible for controlling all the IP 
  1338.     --functions.  It will get messages from the layers above and below.
  1339.     --The only options implemented will be the required security and 
  1340.     --precedence as required by the TCP(transmit side).  We will accept 
  1341.     --but not necessarily process all options (receive side).  We do not 
  1342.     --implement fragmentation and reassembly currently.  We also cannot 
  1343.     --act as a gateway at this time.  We do not actually get called by the 
  1344.     --TCP to return an arrived datagram but it is done in an implicit sort 
  1345.     --of fashion described in the IP_DATAGRAM_RECEIVE procedure.
  1346.   MESSAGE_TO_IP : WITH_IP_COMMUNICATE.IP_MESSAGE;
  1347.   begin
  1348.       -- GET THE REQUEST FOR ACTION FROM THE COMMUNICATE TASK.
  1349.       -- COMMUNICATE_BETWEEN_LAYERS.IP_WAIT(MESSAGE_TO_IP);
  1350.       IP_WAIT(MESSAGE_TO_IP);
  1351.       case MESSAGE_TO_IP.EVENT is
  1352.         when RECEIVE_IP =>
  1353.            null; -- WE CURRENTLY DO NOT GET 
  1354.                          -- CALLED BY THE TCP TO RETURN 
  1355.                          -- A BUFFER.
  1356.         when ERROR_MESSAGE =>
  1357.          -- CALL ERROR_HANDLER
  1358.          IP_ERROR_HANDLER(MESSAGE_TO_IP.ERROR_NUMBER);
  1359.         when DATA_FROM_SUBNET =>
  1360.           IP_DATAGRAM_ARRIVE( MESSAGE_TO_IP.BUFPTR, 
  1361.                               MESSAGE_TO_IP.BYTE_COUNT);
  1362.         when IP_SEND => 
  1363.           SEND_IP( MESSAGE_TO_IP.SRC, 
  1364.                    MESSAGE_TO_IP.DEST, 
  1365.                    MESSAGE_TO_IP.TOS,
  1366.                    MESSAGE_TO_IP.TTL,
  1367.                    MESSAGE_TO_IP.BUFPTR, 
  1368.                    MESSAGE_TO_IP.LEN, 
  1369.                    MESSAGE_TO_IP.ID,
  1370.                    MESSAGE_TO_IP.DF, 
  1371.                    MESSAGE_TO_IP.OPTIONS);
  1372.         when NO_IP_ACTION => 
  1373.          --TEXT_IO.PUT_LINE("NO_IP_ACTION");
  1374.         null;
  1375.       end case;
  1376.   exception
  1377.     when CONSTRAINT_ERROR => 
  1378.       PUT_LINE("FAILED IN IPCNTSND/ CONSTRAINT ERROR");
  1379.     when others =>
  1380.       PUT_LINE("FAILED IN IPCNTSND");
  1381.   end IP_CONTROLLER;
  1382. end INTERNET_PROTOCOL_CONTROL_AND_SEND_PROCESSING; -- PACKAGE
  1383. --::::::::::::::
  1384. --ipglb.txt
  1385. --::::::::::::::
  1386. -----------------------------------------------------------------------
  1387. --
  1388. --         DoD Protocols    NA-00008-200       80-01179-100(-)
  1389. --         E-Systems, Inc.  August 07, 1985
  1390. --
  1391. --         ipglb.txt       Author : Jim Baldo
  1392. --
  1393. -----------------------------------------------------------------------
  1394. with BUFFER_DATA ;        use BUFFER_DATA ;
  1395. with SYSTEM;            use SYSTEM;
  1396. with TEXT_IO;            use TEXT_IO;
  1397.             package IP_GLOBALS is
  1398.         -----------------------------------------------
  1399.         --This implementation is for use with the    --
  1400.         --DEC/Ada compiler .                         --
  1401.         -----------------------------------------------
  1402. ------------------------------------------------------------------------------
  1403. -- THIS SPECIFICATION CONTAINS ALL NECESSARY GLOBAL VARIABLES FOR THE       --
  1404. -- INTERNET PROTOCOL.                                                       --
  1405. ------------------------------------------------------------------------------
  1406.         subtype LOCAL_ADDRESS_TYPE  is SIXTEEN_BITS ;
  1407.     NUMBER_OF_ADDRESSES : constant SIXTEEN_BITS  := 4; -- TEMPORARY VALUE ***
  1408.     MAX_HOSTS : constant SIXTEEN_BITS  := 4; -- TEMP.
  1409.     type MY_ADDRESS_LIST is array(1..MAX_HOSTS) of LOCAL_ADDRESS_TYPE ;
  1410.     type ADDRESS_LIST is array(1..NUMBER_OF_ADDRESSES) of THIRTYTWO_BITS ;
  1411.     VALID_ADDRESS_LIST : constant ADDRESS_LIST := (1, 2, 3, 128);
  1412.     MY_IP_ADDRESS : constant MY_ADDRESS_LIST := (1,2,3,128); -- TEMPORARY **
  1413.     BAD_CHECKSUM : SIXTEEN_BITS  := 0;
  1414.         WHOIAM : constant THIRTYTWO_BITS  := 3 ;
  1415.     subtype    SEVEN_BITS is SIXTEEN_BITS ;
  1416.     subtype    TEN_BITS is SIXTEEN_BITS ;
  1417.     subtype    THREE_BITS is SIXTEEN_BITS ;
  1418.     subtype    TWO_BITS is SIXTEEN_BITS ;
  1419.     subtype    FOUR_OCTETS is THIRTYTWO_BITS ;
  1420.     subtype    TWO_OCTETS is SIXTEEN_BITS ;
  1421.     subtype    ONE_OCTET is SIXTEEN_BITS ;
  1422.     subtype    HALF_OCTET is SIXTEEN_BITS ;
  1423.     subtype    SIX_BITS is SIXTEEN_BITS ;
  1424.     subtype    ONE_BIT    is SIXTEEN_BITS ;
  1425.     subtype BTYPE_TYPE is SIXTEEN_BITS ;
  1426.         subtype OPTION_TYPE_RANGE is SIXTEEN_BITS range 1..50;
  1427.     type OPTION_TYPE is array(OPTION_TYPE_RANGE) of SIXTEEN_BITS ;
  1428.     type BUFFER_POINTER is
  1429.         record
  1430.             BTYPE :    BTYPE_TYPE;
  1431.             VERSION    : HALF_OCTET;
  1432.             IHL : HALF_OCTET;
  1433.             TOS : ONE_OCTET;
  1434.             TOT_LEN    : TWO_OCTETS;
  1435.             ID : TWO_OCTETS;
  1436.             FLAGS : THREE_BITS;
  1437.             FRAG_OFFSET : TWO_OCTETS;
  1438.             TTL : ONE_OCTET;
  1439.             PROT : ONE_OCTET;
  1440.             IPCSUM : TWO_OCTETS;
  1441.             SOURCE : FOUR_OCTETS;
  1442.             DEST : FOUR_OCTETS;
  1443.               --OPTIONS    FOR IP HERE.
  1444.             IP_OPTIONS : OPTION_TYPE := 
  1445.                         (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1446.                          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1447.                          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1448.                          0);
  1449.         end record;
  1450. type PRECEDENCE_TYPE is ( NETWORK_CONTROL, -- 111
  1451.                           INTERNETWORK_CONTROL, -- 110
  1452.                           CRITIC_ECP, -- 101
  1453.                           FLASH_OVERRIDE, --100
  1454.                           FLASH, --011
  1455.                           IMMEDIATE, --010
  1456.                           PRIORITY, --001
  1457.                           ROUTINE); --000
  1458. type RELIABILITY_TYPE is ( NORMAL,
  1459.                            HIGH);
  1460. type DELAY_TYPE is ( NORMAL,
  1461.                      LOW);
  1462. type THROUGHPUT_TYPE is ( NORMAL,
  1463.                           HIGH);
  1464. subtype DATAGRAM_LENGTH is SIXTEEN_BITS ;
  1465. type RESULT_TYPE is (OK, NOK);
  1466. type IP_ACTION is ( IP_SEND, ERROR_MESSAGE, DATA_FROM_SUBNET, 
  1467.                    FROM_TCP, RECEIVE_IP, NO_IP_ACTION ) ;
  1468. type IP_MESSAGE(EVENT : IP_ACTION := IP_SEND) is
  1469.  record
  1470.   BUFPTR : PACKED_BUFFER_PTR := null;
  1471.   case EVENT is
  1472.    when IP_SEND => 
  1473.     LOCAL_DESTINATION : LOCAL_ADDRESS_TYPE ;
  1474.     PRECEDENCE : PRECEDENCE_TYPE := ROUTINE;
  1475.     RELIABILITY : RELIABILITY_TYPE := NORMAL;
  1476.     DELAY_IP : DELAY_TYPE := NORMAL;
  1477.     THROUGHPUT : THROUGHPUT_TYPE := NORMAL;
  1478.     LENGTH : DATAGRAM_LENGTH := 0 ;
  1479.    when ERROR_MESSAGE => ERROR_NUMBER : SIXTEEN_BITS ;
  1480.    when RECEIVE_IP => 
  1481.     SOURCE : THIRTYTWO_BITS ;
  1482.     PROT : SIXTEEN_BITS ;
  1483.     RESULT : RESULT_TYPE;
  1484.    when FROM_TCP => 
  1485.     DEST : THIRTYTWO_BITS ;
  1486.     TOS, TTL, LEN, ID, DF : SIXTEEN_BITS ;
  1487.     OPTIONS : OPTION_TYPE ;
  1488.     SRC : THIRTYTWO_BITS ;
  1489.    when DATA_FROM_SUBNET => BYTE_COUNT : SIXTEEN_BITS ;
  1490.    when NO_IP_ACTION => null;
  1491.   end case;
  1492.  end record;
  1493. end IP_GLOBALS;
  1494. --::::::::::::::
  1495. --lcnkeep.txt
  1496. --::::::::::::::
  1497. -----------------------------------------------------------------------
  1498. --
  1499. --         DoD Protocols    NA-00008-200       80-01180-100(-)
  1500. --         E-Systems, Inc.  August 07, 1985
  1501. --
  1502. --         lcnkeep.txt       Author : Jim Baldo
  1503. --
  1504. -----------------------------------------------------------------------
  1505. with T_TCP_GLOBALS_DATA_STRUCTURES;    use T_TCP_GLOBALS_DATA_STRUCTURES;
  1506.             package TCB_ALLOCATOR is
  1507.     -----------------------------------------------------------
  1508.     --This implementation is for use with the DEC/Ada        --
  1509.     --compiler .                                             --
  1510.     -----------------------------------------------------------
  1511.         procedure TCB_CLEAR( LCN : in TCB_PTR);
  1512.             --This subprogram reintializes a TCB.
  1513.     procedure TCB_FREE
  1514.         (LCN :  in out TCB_PTR);
  1515.         --This subprogram frees a buffer to be used again.
  1516.                 --If TCB is not returned null, the TCB was not found
  1517.                 --on the TCB_IN_USE_LIST.
  1518.     function TCB_GET return TCB_PTR;
  1519.         --This subprogram obtains a buffer to be used.
  1520.                 --If TCB is returned null, the TCB_FREE_LIST resource is
  1521.                 --empty.
  1522.         function OBTAIN_HEAD_OF_LCN_IN_USE_QUEUE return TCB_PTR;
  1523.         --The function returns the head of a queue containing
  1524.         --all current active LCNs in use.
  1525. end TCB_ALLOCATOR;
  1526. with BUFFER_DATA ;            use BUFFER_DATA ;
  1527. with MODULO;                use MODULO;
  1528. with UNCHECKED_CONVERSION;
  1529. with TEXT_IO;                         use TEXT_IO;
  1530. with SYSTEM;
  1531.         package    body TCB_ALLOCATOR is
  1532.   
  1533. TCB_FREE_LIST_HEAD : TCB_PTR; -- The pointer to the head of the buffer free 
  1534. TCB_FREE_LIST_BUFFER_COUNT : SIXTEEN_BITS ;
  1535. TCB_IN_USE_LIST_HEAD : TCB_PTR := null; --Pointer to the head of buffers currently
  1536.                                 --being used.
  1537. TCB_IN_USE_LIST_BUFFER_COUNT : SIXTEEN_BITS ;
  1538. function PHYSICAL_ADDRESS is new UNCHECKED_CONVERSION( THIRTYTWO_BITS ,
  1539.                           SYSTEM.ADDRESS);
  1540. CURRENT_LIST_POINTER : TCB_PTR;
  1541. PRIOR_LIST_POINTER : TCB_PTR;
  1542. procedure TCB_CLEAR( LCN : in TCB_PTR) is
  1543. begin
  1544. LCN.STATE := CLOSED;
  1545. LCN.CONNECTION_STATUS := CONNECTION_CLOSED;
  1546. LCN.LOCAL_PORT := -1;
  1547. LCN.LOCAL_NET :=0;
  1548. LCN.LOCAL_HOST :=3;
  1549. LCN.SOURCE_ADDRESS := 3;
  1550. LCN.DESTINATION_ADDRESS := 0;
  1551. LCN.FOREIGN_PORT := -1;
  1552. LCN.FOREIGN_HOST := -1;
  1553. LCN.FOREIGN_NET := -1; 
  1554. LCN.SND_UNA := MODULAR_CONVERT( THIRTYTWO_BITS ( 0 ) );
  1555. LCN.SND_UP := MODULAR_CONVERT( THIRTYTWO_BITS ( 0 ) );
  1556. LCN.SND_NXT := MODULAR_CONVERT( THIRTYTWO_BITS ( 0 ) );
  1557. LCN.SND_WND := 190;
  1558. LCN.RCV_NXT := MODULAR_CONVERT( THIRTYTWO_BITS ( 0 ) );
  1559. LCN.PRECEDENCE := 0;
  1560. LCN.USER_NOTIFICATION := FALSE;
  1561. LCN.SECURITY := SECURE_CLEAR;
  1562. LCN.BUFFSIZE := 0;
  1563. LCN.RCV_BUFFER_SIZE := -1;
  1564. LCN.RCV_URGENT_POINTER := 0;
  1565. LCN.SND_WL1 := MODULAR_CONVERT( THIRTYTWO_BITS ( 0 ) );
  1566. LCN.SND_WL2 := MODULAR_CONVERT( THIRTYTWO_BITS ( 0 ) );
  1567. LCN.RCV_WINDOW := 190;
  1568. LCN.INIT_RCV_SEQ_NUM := MODULAR_CONVERT( THIRTYTWO_BITS ( 0 ) );
  1569. LCN.ISS := MODULAR_CONVERT( THIRTYTWO_BITS ( 0 ));
  1570. LCN.RETRANS_INTERVAL := 30;
  1571. LCN.MAX_RETRY_OF_PACKET := 0;
  1572. LCN.PROTOCOL :=0;
  1573. LCN.ACTIVE_PASSIVE := ACTIVE;
  1574. LCN.CLOSE_PENDING := FALSE;
  1575. LCN.ERROR_TABLE := ERROR_TABLE_CLEAR;
  1576. LCN.QHEADS :=INITIAL_QUEUE_HEADER_POINTERS;
  1577. LCN.IDENT := -1;
  1578. LCN.RETRANS_IDENT := 0;
  1579. LCN.NEXT_CONNECTION_TIMEOUT := 0;
  1580. LCN.NEXT_TIME_WAIT_TIMEOUT := 0;
  1581. LCN.CONNECTION_TIMEOUT := 180;
  1582. LCN.CLOSE_OK_NOTIFICATION := FALSE;
  1583. end TCB_CLEAR;
  1584. procedure TCB_FREE
  1585.     (LCN : in out TCB_PTR) is
  1586. begin
  1587.         PRIOR_LIST_POINTER := null; -- intialize
  1588.         --Remove TCB from in_use list
  1589.         CURRENT_LIST_POINTER := TCB_IN_USE_LIST_HEAD;
  1590.         while LCN /= CURRENT_LIST_POINTER  
  1591.                and (CURRENT_LIST_POINTER /= null) loop
  1592.          PRIOR_LIST_POINTER := CURRENT_LIST_POINTER;
  1593.          CURRENT_LIST_POINTER := CURRENT_LIST_POINTER.NEXT;
  1594.         end loop;
  1595.         if CURRENT_LIST_POINTER /= null then
  1596.          -- Update TCB_IN_USE_LIST_HEAD and remove from list
  1597.          if PRIOR_LIST_POINTER.NEXT = null and
  1598.           (CURRENT_LIST_POINTER.NEXT /= null ) then --new head
  1599.           TCB_IN_USE_LIST_HEAD := CURRENT_LIST_POINTER.NEXT;
  1600.          elsif PRIOR_LIST_POINTER /= null and
  1601.            ( CURRENT_LIST_POINTER.NEXT /= null ) then
  1602.           PRIOR_LIST_POINTER.NEXT := CURRENT_LIST_POINTER.NEXT;
  1603.          elsif PRIOR_LIST_POINTER /= null and
  1604.            ( CURRENT_LIST_POINTER.NEXT = null ) then
  1605.           PRIOR_LIST_POINTER.NEXT := null ;
  1606.          else -- empty list
  1607.           TCB_IN_USE_LIST_HEAD := null ;
  1608.          end if ;
  1609.          --Place TCB on free list
  1610.      TCB_FREE_LIST_BUFFER_COUNT := TCB_FREE_LIST_BUFFER_COUNT + 1; 
  1611.          -- ALWAYS INCREMENT
  1612.      LCN.NEXT := TCB_FREE_LIST_HEAD;
  1613.      TCB_FREE_LIST_HEAD := LCN;
  1614.      LCN := null; -- RETURN A NULL POINTER
  1615.         end if;
  1616. exception
  1617.  when CONSTRAINT_ERROR =>
  1618.   --PUT_LINE("Constraint error in TCB_FREE");
  1619.   null;
  1620.  when OTHERS =>
  1621.   PUT_LINE("UNKNOWN ERROR IN TCB_FREE");
  1622. end TCB_FREE;
  1623. function TCB_GET return TCB_PTR is
  1624. begin
  1625.  --Remove buffer from free list
  1626.  LCN := TCB_FREE_LIST_HEAD;
  1627.  if TCB_FREE_LIST_HEAD /= null then
  1628.   TCB_FREE_LIST_HEAD := TCB_FREE_LIST_HEAD.NEXT ;
  1629.   --Place buffer on in_use list
  1630.   LCN.NEXT :=  TCB_IN_USE_LIST_HEAD;
  1631.   TCB_IN_USE_LIST_HEAD := LCN;
  1632.   --Decrement counter
  1633.   TCB_FREE_LIST_BUFFER_COUNT := TCB_FREE_LIST_BUFFER_COUNT - 1;
  1634.   --Increment counter
  1635.   TCB_IN_USE_LIST_BUFFER_COUNT := TCB_IN_USE_LIST_BUFFER_COUNT + 1 ;
  1636.   return LCN;
  1637.  else
  1638.   LCN := null;-- out of buffers
  1639.   return LCN;
  1640.  end if ;
  1641. exception
  1642.     when CONSTRAINT_ERROR =>
  1643.         TEXT_IO.PUT_LINE("ERROR/CONSTRAINT IN TCB_GET");
  1644.     --    SYSTEM.REPORT_ERROR;
  1645.     when others =>
  1646.         TEXT_IO.PUT_LINE("ERROR IN TCB_GET");
  1647.     --    SYSTEM.REPORT_ERROR;
  1648. end TCB_GET;
  1649. procedure TCB_INIT is
  1650.         --This subprogram is called when the system is intialize to 
  1651.         --create a finite number of buffers.
  1652.  I : SIXTEEN_BITS ;
  1653.  NEXT_BUFFER : TCB_PTR;
  1654. begin
  1655.                 -- Telesoft does not allow the elboration durning instantiation
  1656.                 RESERVE := new TRANSMISSION_CONTROL_BLOCK;
  1657.         -- get 20 buffers.
  1658.         TCB_FREE_LIST_HEAD := new TRANSMISSION_CONTROL_BLOCK;
  1659.         NEXT_BUFFER := new TRANSMISSION_CONTROL_BLOCK;
  1660.         TCB_FREE_LIST_HEAD.NEXT := NEXT_BUFFER;
  1661.         for I in 1..18 loop
  1662.             NEXT_BUFFER.NEXT := new TRANSMISSION_CONTROL_BLOCK;
  1663.                                                               -- Link them 
  1664.             NEXT_BUFFER := NEXT_BUFFER.NEXT ;
  1665.         end loop;
  1666.         TCB_FREE_LIST_BUFFER_COUNT := 20;
  1667.         TCB_IN_USE_LIST_BUFFER_COUNT := 0;
  1668.     exception 
  1669.         when STORAGE_ERROR =>
  1670.          TEXT_IO.PUT_LINE("OUT OF ROOM TO INITIALIZE TCB BUFFERS");
  1671. end TCB_INIT;
  1672. function OBTAIN_HEAD_OF_LCN_IN_USE_QUEUE return TCB_PTR is
  1673. begin
  1674.  return TCB_IN_USE_LIST_HEAD;
  1675. end OBTAIN_HEAD_OF_LCN_IN_USE_QUEUE;
  1676. begin
  1677.  TCB_FREE_LIST_BUFFER_COUNT := 0; -- initialize buffer count.
  1678.  TCB_INIT;
  1679.  CURRENT_LIST_POINTER := new TRANSMISSION_CONTROL_BLOCK;
  1680.  PRIOR_LIST_POINTER := new TRANSMISSION_CONTROL_BLOCK;
  1681. end TCB_ALLOCATOR;
  1682. --::::::::::::::
  1683. --modulo.txt
  1684. --::::::::::::::
  1685. -----------------------------------------------------------------------
  1686. --
  1687. --         DoD Protocols    NA-00008-200       80-01181-100(-)
  1688. --         E-Systems, Inc.  August 07, 1985
  1689. --
  1690. --         modulo.txt       Author : Jim Baldo
  1691. --
  1692. -----------------------------------------------------------------------
  1693. with BUFFER_DATA ;              use BUFFER_DATA ;
  1694. package MODULO is
  1695. type MODULAR is private; -- ONLY THE FOLLOWING OPERATIONS ARE DEFINED.
  1696. function "<" (X,Y: MODULAR) return BOOLEAN;
  1697. function "<=" (X,Y: MODULAR) return BOOLEAN;
  1698. function ">" (X,Y: MODULAR) return BOOLEAN;
  1699. function ">=" (X,Y : MODULAR) return BOOLEAN;
  1700. function "+" (X,Y: MODULAR) return MODULAR;
  1701. function "+" (X: MODULAR;Y : THIRTYTWO_BITS) return MODULAR;
  1702. function "+" (X    : THIRTYTWO_BITS;Y : MODULAR) return MODULAR;
  1703. function "+" (X    : MODULAR; Y : SIXTEEN_BITS) return MODULAR;
  1704. function "+" (X    : SIXTEEN_BITS; Y : MODULAR) return MODULAR;
  1705. function "-" (X    : MODULAR; Y : SIXTEEN_BITS) return MODULAR;
  1706. function "-" (X,Y: MODULAR) return MODULAR;
  1707. function LONG(X : MODULAR) return THIRTYTWO_BITS;
  1708. function MODULAR_CONVERT (X : SIXTEEN_BITS) return MODULAR;
  1709. function MODULAR_CONVERT (X : THIRTYTWO_BITS) return MODULAR;
  1710. function GET_MODULAR(PP:STRING) return MODULAR;
  1711. procedure PUT_MODULAR(PP : MODULAR);
  1712. private
  1713.   type MODULAR is record
  1714.     NUM : THIRTYTWO_BITS; --RANGE 0..2**32
  1715.   end record;
  1716. -- CAN DECLARE ANY NECESSARY VARIABLES HERE.
  1717. end MODULO;
  1718. with TEXT_IO;
  1719. package body MODULO is
  1720. function LONG(X : MODULAR) return THIRTYTWO_BITS is
  1721. begin
  1722.  return X.NUM;
  1723. end LONG;
  1724. function MODULAR_CONVERT (X : SIXTEEN_BITS) return MODULAR is
  1725. Y : MODULAR;
  1726. begin
  1727.  
  1728.  Y.NUM := THIRTYTWO_BITS(X);
  1729.  return Y;
  1730. exception
  1731. when CONSTRAINT_ERROR =>
  1732. -- PUT_LINE("CONSTRAINT ERROR IN INT MODULAR_CONVERT");
  1733. raise;
  1734. when others =>
  1735. -- PUT_LINE("ERROR IN INT MODULAR_CONVERT");
  1736. raise;
  1737. end;
  1738. function MODULAR_CONVERT (X : THIRTYTWO_BITS) return MODULAR is
  1739. Y : MODULAR;
  1740. begin
  1741.  
  1742.  Y.NUM := X;
  1743.  return Y;
  1744. exception
  1745. when CONSTRAINT_ERROR =>
  1746. -- PUT_LINE("CONSTRAINT ERROR IN LONG_INT MODULAR_CONVERT");
  1747. raise;
  1748. when others =>
  1749. -- PUT_LINE("ERROR IN LONG_INT MODULAR_CONVERT");
  1750. raise;
  1751. end;
  1752. procedure PUT_MODULAR(PP : MODULAR) is
  1753. begin
  1754.   
  1755.   TEXT_IO.PUT("THE ANSWER IS ");
  1756.   TEXT_IO.LONG_INTEGER_IO.PUT(PP.NUM);
  1757.   TEXT_IO.PUT_LINE("");
  1758.   
  1759. end;
  1760. function GET_MODULAR(PP:STRING) return MODULAR is
  1761.    VAL : MODULAR;
  1762. begin
  1763.   TEXT_IO.PUT_LINE(PP);
  1764. --  TEXT_IO.LONG_INTEGER_IO.GET(VAL.NUM);
  1765.   TEXT_IO.PUT_LINE("");
  1766. return VAL;
  1767. end;
  1768. function "+" (X    : SIXTEEN_BITS; Y : MODULAR) return MODULAR is
  1769. Z : MODULAR;
  1770. begin
  1771. Z.NUM := THIRTYTWO_BITS(X) + Y.NUM;
  1772. return Z;
  1773. exception
  1774.    when NUMERIC_ERROR =>
  1775.     return Z;
  1776.    when CONSTRAINT_ERROR =>
  1777.     return Z;
  1778. end;
  1779. function "+" (X    : MODULAR; Y : SIXTEEN_BITS) return MODULAR is
  1780. Z : MODULAR;
  1781. begin
  1782. Z.NUM := X.NUM + THIRTYTWO_BITS(Y);
  1783. return Z;
  1784. exception
  1785.    when NUMERIC_ERROR =>
  1786.     return Z;
  1787.    when CONSTRAINT_ERROR =>
  1788.     return Z;
  1789. end;
  1790. function "+" (X    : THIRTYTWO_BITS;Y : MODULAR) return MODULAR is
  1791. Z : MODULAR;
  1792. begin
  1793. Z.NUM := X + Y.NUM;
  1794. return Z;
  1795. exception
  1796.    when NUMERIC_ERROR =>
  1797.     return Z;
  1798.    when CONSTRAINT_ERROR =>
  1799.     return Z;
  1800. end;
  1801. function "+" (X    : MODULAR;Y : THIRTYTWO_BITS) return MODULAR is
  1802. Z : MODULAR;
  1803. begin
  1804. Z.NUM := X.NUM + Y;
  1805. return Z;
  1806. end;
  1807. function "+" (X,Y: MODULAR) return MODULAR is
  1808. Z : MODULAR;
  1809. begin
  1810. Z.NUM := X.NUM + Y.NUM;
  1811. return Z;
  1812. exception
  1813.    when NUMERIC_ERROR =>
  1814.     return Z;
  1815.    when CONSTRAINT_ERROR =>
  1816.     return Z;
  1817. end; 
  1818. function "<=" (X,Y : MODULAR) return BOOLEAN is
  1819. RESULT : BOOLEAN;
  1820. begin
  1821. if X = Y then
  1822.   RESULT := TRUE;
  1823. else
  1824.   if ((X.NUM >=    0) and (Y.NUM >= 0)) or ((X.NUM <= 0) and (Y.NUM <= 0)) then
  1825.      if X.NUM <    Y.NUM then
  1826.       RESULT := TRUE;
  1827.      else
  1828.       RESULT := FALSE;
  1829.      end if;
  1830.   elsif (X.NUM < -1048576) or (X.NUM > 1048576) then --    ACTUALL    + OR - 2**20
  1831.   -- WE    ARE IN THE MIDDLE
  1832.      if X.NUM <    0 then
  1833.       RESULT := FALSE;
  1834.      else
  1835.       RESULT := TRUE;
  1836.      end if;
  1837.   else
  1838.   -- WRAP AROUND HAS OCCURRED
  1839.      if X.NUM >= 0 then
  1840.       RESULT := FALSE;
  1841.      else
  1842.       RESULT := TRUE;
  1843.      end if;
  1844.   end if;
  1845. end if;
  1846. return RESULT;
  1847. end;
  1848. function "<" (X,Y : MODULAR) return BOOLEAN is
  1849. RESULT : BOOLEAN;
  1850. begin
  1851. if ((X.NUM >= 0) and (Y.NUM >= 0)) or ((X.NUM <= 0) and (Y.NUM <= 0)) then
  1852.    if X.NUM < Y.NUM then
  1853.     RESULT := TRUE;
  1854.    else
  1855.     RESULT := FALSE;
  1856.    end if;
  1857. elsif (X.NUM < -1048576) or (X.NUM > 1048576) then -- ACTUALL +    OR - 2**20
  1858. -- WE ARE IN THE MIDDLE
  1859.    if X.NUM < 0    then
  1860.     RESULT := FALSE;
  1861.    else
  1862.     RESULT := TRUE;
  1863.    end if;
  1864. else
  1865. -- WRAP    AROUND HAS OCCURRED
  1866.    if X.NUM >= 0 then
  1867.     RESULT := FALSE;
  1868.    else
  1869.     RESULT := TRUE;
  1870.    end if;
  1871. end if;
  1872. return RESULT;
  1873. end;
  1874. function ">=" (X,Y : MODULAR) return BOOLEAN is
  1875. RESULT : BOOLEAN;
  1876. begin
  1877. if X = Y then
  1878.   RESULT := TRUE;
  1879. else
  1880.   if ((X.NUM >=    0) and (Y.NUM >= 0)) or ((X.NUM <= 0) and (Y.NUM <= 0)) then
  1881.      if X.NUM <    Y.NUM then
  1882.       RESULT := FALSE;
  1883.      else
  1884.       RESULT := TRUE;
  1885.      end if;
  1886.   elsif (X.NUM < -1048576) or (X.NUM > 1048576) then --ACTUALLY    + OR -2**20
  1887.   -- WE    ARE IN THE MIDDLE
  1888.      if X.NUM <    0 then
  1889.       RESULT := TRUE;
  1890.      else
  1891.       RESULT := FALSE;
  1892.      end if;
  1893.   else
  1894.   -- WRAP AROUND HAS OCCURRED
  1895.      if X.NUM >= 0 then
  1896.       RESULT := TRUE;
  1897.      else
  1898.       RESULT := FALSE;
  1899.      end if;
  1900.   end if;
  1901. end if;
  1902. return RESULT;
  1903. end;
  1904. function ">" (X,Y : MODULAR) return BOOLEAN is
  1905. RESULT : BOOLEAN;
  1906. begin
  1907. if ((X.NUM >= 0) and (Y.NUM >= 0)) or ((X.NUM <= 0) and (Y.NUM <= 0)) then
  1908.    if X.NUM <= Y.NUM then
  1909.     RESULT := FALSE;
  1910.    else
  1911.     RESULT := TRUE;
  1912.    end if;
  1913. elsif (X.NUM < -1048576) or (X.NUM > 1048576) then --ACTUALLY +    OR -2**20
  1914. -- WE ARE IN THE MIDDLE
  1915.    if X.NUM < 0    then
  1916.     RESULT := TRUE;
  1917.    else
  1918.     RESULT := FALSE;
  1919.    end if;
  1920. else
  1921. -- WRAP    AROUND HAS OCCURRED
  1922.    if X.NUM >= 0 then
  1923.     RESULT := TRUE;
  1924.    else
  1925.     RESULT := FALSE;
  1926.    end if;
  1927. end if;
  1928. return RESULT;
  1929. end;
  1930. function "-" (X    : MODULAR; Y : SIXTEEN_BITS) return MODULAR is
  1931. MDIFF :    MODULAR;
  1932. begin
  1933. if X.NUM >= THIRTYTWO_BITS(Y) then
  1934. -- NORMAL SUBTRACTION
  1935.   MDIFF.NUM := X.NUM - THIRTYTWO_BITS(Y);
  1936. else --    X HAS WRAPPED AROUND
  1937.   MDIFF.NUM := X.NUM - THIRTYTWO_BITS(Y) + 2147483647 + 2    + 2147483647; 
  1938.   --ADD IN 2**32
  1939.   -- GET THE ABSOLUTE VALUE OF MDIFF.NUM
  1940.   if MDIFF.NUM < 0 then
  1941.     MDIFF.NUM := -MDIFF.NUM;
  1942.   end if;
  1943. end if;
  1944. return MDIFF;
  1945. exception
  1946.    when NUMERIC_ERROR =>
  1947.     return MDIFF;
  1948.     when CONSTRAINT_ERROR =>
  1949.         return MDIFF;
  1950. end;
  1951. function "-" (X, Y : MODULAR) return MODULAR is
  1952. MDIFF :    MODULAR;
  1953. begin
  1954. if X.NUM >= Y.NUM then
  1955. -- NORMAL SUBTRACTION
  1956.   MDIFF.NUM := X.NUM - Y.NUM;
  1957. else --    X HAS WRAPPED AROUND
  1958.   MDIFF.NUM := X.NUM - Y.NUM + 2147483647 + 2 +    2147483647; 
  1959.   --ADD IN 2**32
  1960.   -- GET THE ABSOLUTE VALUE OF MDIFF.NUM
  1961.   if MDIFF.NUM < 0 then
  1962.     MDIFF.NUM := -MDIFF.NUM;
  1963.   end if;
  1964. end if;
  1965. return MDIFF;
  1966. exception
  1967.    when NUMERIC_ERROR =>
  1968.     return MDIFF;
  1969.     when CONSTRAINT_ERROR =>
  1970.         return MDIFF;
  1971. end;
  1972. end MODULO;
  1973. --::::::::::::::
  1974. --ncomm.txt
  1975. --::::::::::::::
  1976. -----------------------------------------------------------------------
  1977. --
  1978. --         DoD Protocols    NA-00008-200       80-01182-100(-)
  1979. --         E-Systems, Inc.  August 07, 1985
  1980. --
  1981. --         ncomm.txt       Author : Jim Baldo
  1982. --
  1983. -----------------------------------------------------------------------
  1984. with BUFFER_DATA;    use BUFFER_DATA;
  1985. with T_TCP_GLOBALS_DATA_STRUCTURES ;
  1986. use T_TCP_GLOBALS_DATA_STRUCTURES ;
  1987.                 package    WITH_TCP_COMMUNICATE is
  1988.     
  1989.         ---------------------------------------------------------------
  1990.     --This implementation is for use with Telesoft version       --
  1991.         --1.3d  Ada compiler                                         --
  1992.     ---------------------------------------------------------------
  1993. -------------------------------------------------------------------------------
  1994. --This package contains all the data abstractions and operations necessary   --
  1995. --to support the User/TCP interface and TCP/lower-level interface.           --
  1996. --The enumerated type ACTION represents the type of request primitive        --
  1997. --that is sent by the upper layer or lower layer protocols.                  --
  1998. -------------------------------------------------------------------------------
  1999.     subtype LCN_TYPE is TCB_PTR;
  2000.         
  2001.         type ACTION is (OPEN,SEND,RECEIVE,ABOR_T,CLOSE,STATUS,DATA_FROM_IP,
  2002.             TIMER_TIMEOUT, ERROR_MESSAGE, TIMEOUT_IN_RETRANS_QUEUE,
  2003.             TIMEOUT_IN_TIME_WAIT, NO_TCP_ACTION);
  2004.     type SECURITY_OPTION_TYPE is array(1..9) of SIXTEEN_BITS; 
  2005.                         -- EACH ELEMENT CONTAINS AN
  2006.                              -- OCTET OF SECURITY DATA.
  2007.     type TCP_OPTION_TYPE is array(1..50) of SIXTEEN_BITS;
  2008.     type ACKPASS is (PASSIVE, ACTIVE);
  2009.     
  2010.     type TIMER_PARAMS is
  2011.         record
  2012.             MESSAGE_NUMBER : SIXTEEN_BITS;
  2013.         end record;
  2014.     
  2015.     type TIME_WAIT_PARAMS is
  2016.         record
  2017.             LCN : TCB_PTR;
  2018.         end record;
  2019.     type OPEN_PARAMS is
  2020.         record
  2021.             LOCAL_PORT, FOREIGN_PORT : SIXTEEN_BITS;
  2022.             FOREIGN_NET_HOST : THIRTYTWO_BITS;
  2023.             ACTIVE_PASSIVE : ACKPASS;
  2024.             BUFFER_SIZE, TIMEOUT : SIXTEEN_BITS;
  2025.                         LCN : TCB_PTR;
  2026.                         SECURITY, PRECEDENCE :   SIXTEEN_BITS;
  2027.             OPTIONS : TCP_OPTION_TYPE;
  2028.         end record;
  2029.     type STATUS_PARAMS is
  2030.         record
  2031.                         LCN : TCB_PTR;
  2032.         end record;
  2033.   
  2034.     type ERROR_PARAMS is
  2035.         record
  2036.             ERROR_INDICATOR : SIXTEEN_BITS; -- THIS MAY CHANGE.
  2037.         end record;
  2038.   
  2039.     type RETRANS_PARAMS is
  2040.         record
  2041.             QUEUE_NUM : SIXTEEN_BITS;
  2042.         end record;
  2043.     type SEG_ARRIVE_PARAMS is
  2044.         record
  2045.             BUFPTR : PACKED_BUFFER_PTR;
  2046.             BYTE_COUNT : SIXTEEN_BITS;
  2047.             SOURCE_ADDRESS, DESTINATION_ADDRESS : THIRTYTWO_BITS;
  2048.             PROTOCOL : SIXTEEN_BITS;
  2049.             TOS : SIXTEEN_BITS;
  2050.             SECURITY : SECURITY_OPTION_TYPE;
  2051.         end record;
  2052.   
  2053.     type SEND_PARAMS is
  2054.         record
  2055.                         LCN : TCB_PTR;
  2056.             BUFPTR : PACKED_BUFFER_PTR;
  2057.             BYTE_COUNT, PUSH_FLAG, URG_FLAG, TIMEOUT :   
  2058.                                                              SIXTEEN_BITS;
  2059.         end record;
  2060.     type RECEIVE_PARAMS is
  2061.         record
  2062.                         LCN : TCB_PTR;
  2063.             BUFPTR : PACKED_BUFFER_PTR;
  2064.             BYTE_COUNT : SIXTEEN_BITS;
  2065.         end record;
  2066.   
  2067.     type ABORT_CLOSE_PARAMS    is
  2068.         record
  2069.                         LCN : TCB_PTR;
  2070.         end record;
  2071.   
  2072. --TCP responds to message which are associated with a type of event.  The
  2073. --data abstraction of MESSAGE creates the appropiate message for the given
  2074. --event.
  2075.     type MESSAGE(EVENT : ACTION := OPEN) is
  2076.         record
  2077.             case EVENT is
  2078.                 when   ABOR_T |  CLOSE
  2079.                 => ABORT_CLOSE_PARAMETERS : ABORT_CLOSE_PARAMS;
  2080.     
  2081.                 when DATA_FROM_IP 
  2082.                 => DATA_FROM_IP_PARAMETERS : SEG_ARRIVE_PARAMS;
  2083.     
  2084.                 when RECEIVE 
  2085.                 => RECEIVE_PARAMETERS : RECEIVE_PARAMS;
  2086.     
  2087.                 when SEND => SEND_PARAMETERS : SEND_PARAMS;
  2088.     
  2089.                 when OPEN  => OPEN_PARAMETERS : OPEN_PARAMS;
  2090.     
  2091.                 when STATUS
  2092.                 => STATUS_PARAMETERS : STATUS_PARAMS;
  2093.     
  2094.                 when  TIMEOUT_IN_TIME_WAIT
  2095.                 =>  TIME_WAIT_PARAMETERS : TIME_WAIT_PARAMS;
  2096.     
  2097.                 when TIMEOUT_IN_RETRANS_QUEUE 
  2098.                 => RETRANS_PARAMETERS    : RETRANS_PARAMS;
  2099.     
  2100.                 when ERROR_MESSAGE 
  2101.                 => ERROR_PARAMETERS : ERROR_PARAMS;
  2102.                 when TIMER_TIMEOUT 
  2103.                 => TIMER_PARAMETERS : TIMER_PARAMS;
  2104.   
  2105.                 when NO_TCP_ACTION => NULL;
  2106.             end case;
  2107.         end record;
  2108.     MESSAGE_HOLDER : MESSAGE;
  2109.     procedure MESSAGE_FOR_TCP(TASK_MESSAGE : MESSAGE);
  2110.         --Messages are passed to TCP from the both upper and lower 
  2111.         --level protocol(s).  Each interface has a queue which the 
  2112.         --adjacent protocols place there messages.  This subprogram 
  2113.         --will pass messages from either queue for processing in a
  2114.         --main queue that will be read and processed by the 
  2115.         --TCP_CONTROLLER.  
  2116.         --
  2117.         --Implementation Notes:
  2118.         -----------------------
  2119.         --Since tasking is not used in this implementation queue 
  2120.         --synchronization is not a concern.  The current queue sizes 
  2121.         --are fixed and can overflow if TCP is flooded by messages.  
  2122.     procedure WAIT( TASK_MESSAGE : OUT MESSAGE);
  2123.         --This subprogram will obtain a message from the TCP message 
  2124.         --queue.  If the if the queue is empty then the message 
  2125.         --passed is of the type NO_TCP_ACTION.  Otherwise the message 
  2126.         --is popped from the queue and passed.
  2127. end WITH_TCP_COMMUNICATE;
  2128. with TEXT_IO;        use TEXT_IO;
  2129. with MODULO;        use MODULO;
  2130.         package    body WITH_TCP_COMMUNICATE is
  2131. type QUEUE_ELEMENT;
  2132. type QUEUE_ELEMENT_POINTER is access QUEUE_ELEMENT;
  2133. subtype Q_ITEM is MESSAGE;
  2134. type QUEUE_ELEMENT is
  2135. record
  2136.   ELEMENT : Q_ITEM;
  2137.   NEXT : QUEUE_ELEMENT_POINTER;
  2138. end RECORD;
  2139. TYPE QHEADS IS 
  2140. record
  2141.   ELEMENT_COUNT : SIXTEEN_BITS := 0;
  2142.   FIRST_ELEMENT : QUEUE_ELEMENT_POINTER;
  2143.   LAST_ELEMENT  : QUEUE_ELEMENT_POINTER;
  2144. end RECORD;
  2145. QUEUE_FREE_LIST : QUEUE_ELEMENT_POINTER;
  2146. MAX_QUEUE_SIZE : CONSTANT SIXTEEN_BITS := 32;
  2147. NUMBER_OF_QUEUES : CONSTANT SIXTEEN_BITS := 1;
  2148. TO_TCP_QUEUE_LENGTH : SIXTEEN_BITS := 0;
  2149. MAX : CONSTANT SIXTEEN_BITS := 32; -- TEMPORARY
  2150. TO_TCP_QUEUE : QHEADS;
  2151. NO_ADD_COUNT : SIXTEEN_BITS := 0;
  2152.  procedure INITIALIZE_QUEUES is
  2153.  --   THIS PROCEDURE IS CALLED TO SET UP A FREE LIST OF QUEUE ELEMENTS.
  2154.  --   IT IS CALLED AT SYSTEM INITIALIZATION TIME.
  2155.  --
  2156.  --   THIS ROUTINE ALLOCATES AND LINKS TOGETHER IN A LIST (POINTED TO BY
  2157.  --   QUEUE_FREE_LIST) OF QUEUE ELEMENTS TO BE USED BY ALL OF THE QUEUE
  2158.  --   ROUTINES. IT ALLOCATES THEM VIA NEW. THEY ARE NEVER DEALLOCATED.
  2159.  --   THEY ARE SIMPLY PUT BACK IN THE FREE QUEUE ELEMENT LIST.
  2160.  --   THE MAX QUEUE SIZE TIMES THE NUMBER OF QUEUES IS THE NUMBER OF QUEUE\
  2161.  --   ELEMENTS THAT ARE ALLOCATED.
  2162.  NEXT_STRUCTURE : QUEUE_ELEMENT_POINTER;
  2163.  begin
  2164.   QUEUE_FREE_LIST := NEW QUEUE_ELEMENT;
  2165.   NEXT_STRUCTURE :=  NEW QUEUE_ELEMENT;
  2166.   QUEUE_FREE_LIST.NEXT := NEXT_STRUCTURE;
  2167.   for I in 3..MAX_QUEUE_SIZE*NUMBER_OF_QUEUES loop
  2168.    -- SET UP A FREE LIST OF QUEUE STRUCTURES.
  2169.    NEXT_STRUCTURE.NEXT := NEW QUEUE_ELEMENT;
  2170.    NEXT_STRUCTURE := NEXT_STRUCTURE.NEXT;
  2171.   end loop;
  2172.  end INITIALIZE_QUEUES;
  2173.  function GET_Q_STRUCTURE return QUEUE_ELEMENT_POINTER is
  2174.  X : QUEUE_ELEMENT_POINTER;
  2175.  begin
  2176.   X := QUEUE_FREE_LIST;
  2177.   QUEUE_FREE_LIST := QUEUE_FREE_LIST.NEXT;
  2178.   return X;
  2179.  exception
  2180.   when constraint_error =>
  2181.    TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN GET_Q_STRUCTURE");
  2182.   when others =>
  2183.    TEXT_IO.PUT_LINE("UNKNOWN ERROR RAISED IN GET_Q_STRUCTURE");
  2184.  end GET_Q_STRUCTURE;
  2185.  procedure FREE_Q_STRUCTURE(Q_STRUCTURE : in out QUEUE_ELEMENT_POINTER) is
  2186.  begin
  2187.   Q_STRUCTURE.NEXT := QUEUE_FREE_LIST;
  2188.   QUEUE_FREE_LIST := Q_STRUCTURE; --ADDS TO FRONT OF LIST
  2189.   -- MAKE THE POINTER NULL NOW.
  2190.   Q_STRUCTURE := null;
  2191.  exception
  2192.   when constraint_error =>
  2193.    TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN FREE_Q_STRUCTURE");
  2194.   when others =>
  2195.    TEXT_IO.PUT_LINE("UNKNOWN ERROR RAISED IN FREE_Q_STRUCTURE");
  2196.  end FREE_Q_STRUCTURE;
  2197.  function QUEUE_EMPTY(QUEUE : QHEADS) return BOOLEAN is
  2198.  RESULT : BOOLEAN := FALSE;
  2199.  begin
  2200.   if QUEUE.ELEMENT_COUNT = 0 then
  2201.     RESULT := TRUE;
  2202.   end if;
  2203.   return RESULT;
  2204.  end QUEUE_EMPTY;
  2205.  procedure QUEUE_GET(QHEAD : in out QHEADS; ITEM : in out Q_ITEM) is
  2206.  Q_ELEMENT_TO_BE_FREED : QUEUE_ELEMENT_POINTER;
  2207.  begin
  2208.   if QHEAD.ELEMENT_COUNT > 0 then
  2209.    QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  2210.    Q_ELEMENT_TO_BE_FREED := QHEAD.FIRST_ELEMENT;
  2211.    ITEM := QHEAD.FIRST_ELEMENT.ELEMENT;
  2212.    QHEAD.FIRST_ELEMENT := QHEAD.FIRST_ELEMENT.NEXT;
  2213.    if QHEAD.ELEMENT_COUNT = 0 then -- AN EMPTY LIST
  2214.     QHEAD.LAST_ELEMENT := null;
  2215.    end if;
  2216.    FREE_Q_STRUCTURE(Q_ELEMENT_TO_BE_FREED); -- FREE UP THE FORMER FIRST ELEMENT
  2217.   else -- AN EMPTY LIST
  2218.    TEXT_IO.PUT_LINE("A FOOLISH QGET ATTEMPT ON AN EMPTY LIST");
  2219.   end if;
  2220.  exception
  2221.   when constraint_error =>
  2222.    TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN QGET");
  2223.   when others =>
  2224.    TEXT_IO.PUT_LINE("UNKNOWN  ERROR IN QUEUE_GET");
  2225.  end QUEUE_GET;
  2226.  procedure QUEUE_DELETE(QHEAD : in out QHEADS; ITEM :Q_ITEM) is
  2227.  BEFORE_PTR : QUEUE_ELEMENT_POINTER := QHEAD.FIRST_ELEMENT;
  2228.  CURRENT_ELEMENT_POINTER : QUEUE_ELEMENT_POINTER := QHEAD.FIRST_ELEMENT;
  2229.  FOUND : BOOLEAN := FALSE;
  2230.  begin
  2231.   while CURRENT_ELEMENT_POINTER /= null and (not FOUND) loop
  2232.    if CURRENT_ELEMENT_POINTER.ELEMENT = ITEM then 
  2233.             -- FREE IT AND THE BUFFER UP
  2234.     BEFORE_PTR.NEXT := CURRENT_ELEMENT_POINTER.NEXT;
  2235.     -- TAKE CARE OF DELETING FROM THE END OR BEGINNING OF A LIST.
  2236.     if QHEAD.FIRST_ELEMENT = CURRENT_ELEMENT_POINTER then
  2237.      QHEAD.FIRST_ELEMENT := CURRENT_ELEMENT_POINTER.NEXT;
  2238.     end if;
  2239.     if QHEAD.LAST_ELEMENT = CURRENT_ELEMENT_POINTER then
  2240.          -- WE ARE DELETING LAST ELEMENT.
  2241.      if QHEAD.FIRST_ELEMENT /= null then
  2242.       QHEAD.LAST_ELEMENT := BEFORE_PTR;
  2243.      else -- AN EMPTY LIST NOW
  2244.       QHEAD.LAST_ELEMENT := NULL;
  2245.      end if;
  2246.     end if;
  2247.     -- FREE THE ELEMENT AND DECREMENT THE ELEMENT COUNT
  2248.     FREE_Q_STRUCTURE(CURRENT_ELEMENT_POINTER);
  2249.     QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  2250.     FOUND := TRUE;
  2251.    else
  2252.     BEFORE_PTR := CURRENT_ELEMENT_POINTER;
  2253.     CURRENT_ELEMENT_POINTER := CURRENT_ELEMENT_POINTER.NEXT;
  2254.    end if;
  2255.   end loop;
  2256.   if not FOUND then --ERROR
  2257.    TEXT_IO.PUT_LINE("WAS UNABLE TO DELETE");
  2258.   end if;
  2259.  exception
  2260.   when constraint_error =>
  2261.    TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN QUEUE DELETE");
  2262.   when others =>
  2263.    TEXT_IO.PUT_LINE(" ERROR IN QUEUE DELETE");
  2264.  end QUEUE_DELETE;
  2265.  procedure QUEUE_CLEAR(QHEAD : in out QHEADS) is
  2266.  X : QUEUE_ELEMENT_POINTER;
  2267.  begin
  2268.   while QHEAD.ELEMENT_COUNT > 0 loop
  2269.    X := QHEAD.FIRST_ELEMENT;
  2270.    QHEAD.FIRST_ELEMENT := X.NEXT;
  2271.    FREE_Q_STRUCTURE(X);
  2272.    QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  2273.   end loop;
  2274.   -- RESET THE HEAD AND TAIL POINTERS.
  2275.   QHEAD.FIRST_ELEMENT := null;
  2276.   QHEAD.LAST_ELEMENT := null;
  2277.  exception
  2278.   when constraint_error =>
  2279.    TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN QUEUE CLEAR");
  2280.   when others =>
  2281.    TEXT_IO.PUT_LINE("UNKNOWN ERROR TYPE IN QUEUE CLEAR");
  2282.  end QUEUE_CLEAR;
  2283.  procedure QUEUE_ADD(QHEAD : in out QHEADS; ITEM : Q_ITEM) is
  2284.  NEW_ITEM : QUEUE_ELEMENT_POINTER := GET_Q_STRUCTURE;
  2285.  begin
  2286.   NEW_ITEM.ELEMENT := ITEM;
  2287.   NEW_ITEM.NEXT := null;
  2288.   if QHEAD.ELEMENT_COUNT < MAX_QUEUE_SIZE theN
  2289.    if QHEAD.ELEMENT_COUNT /= 0 then 
  2290.     -- ITS NOT AN EMPTY QUEUE. SO LINK FORMER
  2291.     -- LAST ITEM TO NEW ONE.
  2292.     QHEAD.LAST_ELEMENT.NEXT := NEW_ITEM;
  2293.    else -- FIRST ADD TO THE QUEUE
  2294.     QHEAD.FIRST_ELEMENT := NEW_ITEM;
  2295.    end if;
  2296.    QHEAD.LAST_ELEMENT := NEW_ITEM;
  2297.    QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT + 1;
  2298.   else -- NO ROOM TOO BAD
  2299.    FREE_Q_STRUCTURE(NEW_ITEM);
  2300.   end if;
  2301.  exception
  2302.   when constraint_error =>
  2303.    TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN QUEUE ADD");
  2304.   when others =>
  2305.    TEXT_IO.PUT_LINE("ERROR IN QADD");
  2306.    TEXT_IO.INTEGER_IO.PUT(QHEAD.ELEMENT_COUNT);
  2307.  end QUEUE_ADD;
  2308.  procedure WAIT( TASK_MESSAGE : out MESSAGE) is
  2309.  
  2310.  begin
  2311.   -- GET A TASK MESSAGE
  2312.   if TO_TCP_QUEUE_LENGTH > 0 then -- ADD THE ITEM
  2313.    TO_TCP_QUEUE_LENGTH := TO_TCP_QUEUE_LENGTH - 1;
  2314.    QUEUE_GET(TO_TCP_QUEUE, TASK_MESSAGE);
  2315.   else -- NO MESSAGE
  2316.    TASK_MESSAGE := (EVENT => NO_TCP_ACTION);
  2317.   end if;
  2318.  end WAIT;
  2319.  procedure MESSAGE_FOR_TCP(TASK_MESSAGE : MESSAGE) is
  2320.  begin
  2321.   if TO_TCP_QUEUE_LENGTH < MAX then
  2322.    TO_TCP_QUEUE_LENGTH := TO_TCP_QUEUE_LENGTH + 1;
  2323.    QUEUE_ADD(TO_TCP_QUEUE, TASK_MESSAGE);
  2324.   else
  2325.    NO_ADD_COUNT := NO_ADD_COUNT + 1;
  2326.   end if;
  2327.  exception
  2328.   when others =>
  2329.    TEXT_IO.PUT("CAN'T OUTPUT LOCAL PORT NUMBER OR LCN");
  2330.  end MESSAGE_FOR_TCP;
  2331. begin -- INITIALIZE THE QUEUES.
  2332.  INITIALIZE_QUEUES;
  2333. end WITH_TCP_COMMUNICATE;
  2334. --::::::::::::::
  2335. --ncommip.txt
  2336. --::::::::::::::
  2337. -----------------------------------------------------------------------
  2338. --
  2339. --         DoD Protocols    NA-00008-200       80-01183-100(-)
  2340. --         E-Systems, Inc.  August 07, 1985
  2341. --
  2342. --         ncommip.txt       Author : Jim Baldo
  2343. --
  2344. -----------------------------------------------------------------------
  2345.             
  2346. with BUFFER_DATA;                        use BUFFER_DATA;
  2347. with IP_GLOBALS;                         use IP_GLOBALS;
  2348.                         
  2349.                         
  2350.                         package WITH_IP_COMMUNICATE is
  2351.                         
  2352.         ---------------------------------------------------
  2353.         --This implementation is for use with the        --
  2354.                 --Telesoft Ada compiler version 1.3d             --
  2355.         ---------------------------------------------------
  2356. ------------------------------------------------------------------------------
  2357. -- THIS PACKAGE CONTAINS ALL THE ROUTINES RESPONSIBLE FOR COMMUNICATING     --
  2358. -- WITH THE IP BY ACCEPTING MESSAGES FROM OTHER SOURCES.                    --
  2359. ------------------------------------------------------------------------------
  2360.     type IP_ACTION is (IP_SEND, ERROR_MESSAGE, DATA_FROM_SUBNET, 
  2361.                            RECEIVE_IP, NO_IP_ACTION);
  2362.     type RESULT_TYPE is (OK, NOK);
  2363.     type IP_MESSAGE(EVENT : IP_ACTION := IP_SEND) is
  2364.         record
  2365.             BUFPTR : PACKED_BUFFER_PTR := null;
  2366.             DEST : THIRTYTWO_BITS;
  2367.             TOS, TTL, LEN : SIXTEEN_BITS;
  2368.             case EVENT is
  2369.                 when IP_SEND => ID, DF : SIXTEEN_BITS;
  2370.                         OPTIONS : OPTION_TYPE;
  2371.                         SRC : THIRTYTWO_BITS; 
  2372.                         -- THE SOURCE HOST.
  2373.                 when ERROR_MESSAGE => ERROR_NUMBER : 
  2374.                                                       SIXTEEN_BITS;
  2375.                 when RECEIVE_IP => SOURCE : THIRTYTWO_BITS;
  2376.                            PROT : SIXTEEN_BITS;
  2377.                            RESULT : RESULT_TYPE;
  2378.                 when DATA_FROM_SUBNET => BYTE_COUNT :
  2379.                                                          SIXTEEN_BITS;
  2380.                 when NO_IP_ACTION => null;
  2381.             end case;
  2382.         end record;
  2383.     ACTION : IP_ACTION;
  2384.     MESSAGE_TO_IP : IP_MESSAGE;
  2385.     RESULT : RESULT_TYPE; -- USED TO RETURN THE RESULTS OF QUEUE ATTEMPTS.
  2386.     
  2387.         procedure SUBNET_TO_IP( DATAGRAM : in PACKED_BUFFER_PTR);
  2388.         
  2389.         procedure SEND_IP(SRC, DEST : in THIRTYTWO_BITS; 
  2390.                           TOS, TTL : in SIXTEEN_BITS; 
  2391.                           BUFFPTR : in out PACKED_BUFFER_PTR; 
  2392.                           LEN , IDENT : SIXTEEN_BITS;
  2393.                   DONT_FRAGMENT : SIXTEEN_BITS; 
  2394.                           OPTIONS : OPTION_TYPE;
  2395.                   RESULT : in out RESULT_TYPE);
  2396.         --This subprogram allows the user to send a message to IP.  
  2397.         --The message is placed on the TO_IP_QUEUE.
  2398.     procedure IP_WAIT( MESSAGE_TO_IP : in out IP_MESSAGE);
  2399.         --This subprogram will check to see if the subnet protocol 
  2400.         --has a message to send to IP or if not the TO_IP_QUEUE is 
  2401.         --examined for a message from TCP.  If neither the TCP or 
  2402.         --SUBNET has a message a null is returned.  This procedure is 
  2403.         --used by the IP controller.
  2404. end WITH_IP_COMMUNICATE;
  2405. with SYSTEM; -- FOR TESTING
  2406. with UNCHECKED_CONVERSION; -- FOR TESTING
  2407. with TEXT_IO;                           use TEXT_IO;
  2408. with MODULO;                            use MODULO;
  2409. with IP_GLOBALS;                        use IP_GLOBALS;
  2410. with SUBNET_CALLS;                      use SUBNET_CALLS;
  2411.                 package    body WITH_IP_COMMUNICATE is
  2412.                 
  2413.     MAX : constant SIXTEEN_BITS := 16; -- LACK OF MEMORY 32;
  2414.     type QUEUE_ELEMENT;
  2415.     type QUEUE_ELEMENT_POINTER is access QUEUE_ELEMENT;
  2416.     subtype Q_ITEM is IP_MESSAGE;
  2417.     type QUEUE_ELEMENT is
  2418.         record
  2419.             ELEMENT : Q_ITEM;
  2420.             NEXT : QUEUE_ELEMENT_POINTER;
  2421.         end record;
  2422.     type QHEADS is 
  2423.         record
  2424.             ELEMENT_COUNT : SIXTEEN_BITS := 0;
  2425.             FIRST_ELEMENT : QUEUE_ELEMENT_POINTER;
  2426.             LAST_ELEMENT  : QUEUE_ELEMENT_POINTER;
  2427.         end record;
  2428. -- FOR TESTING
  2429.     function PHYSICAL_ADDRESS is
  2430.           new UNCHECKED_CONVERSION(THIRTYTWO_BITS, SYSTEM.ADDRESS);
  2431.     PACKET_PRINT_FLAG : SIXTEEN_BITS;
  2432.     NO_ADD_COUNT : SIXTEEN_BITS;
  2433.     for PACKET_PRINT_FLAG use at PHYSICAL_ADDRESS(THIRTYTWO_BITS(16#F06#));
  2434.     for NO_ADD_COUNT use at PHYSICAL_ADDRESS(THIRTYTWO_BITS(16#F24#));
  2435.     QUEUE_FREE_LIST : QUEUE_ELEMENT_POINTER;
  2436.     MAX_QUEUE_SIZE : constant SIXTEEN_BITS := 32;
  2437.     NUMBER_OF_QUEUES : constant SIXTEEN_BITS := 1;
  2438.     TO_IP_QUEUE_LENGTH : SIXTEEN_BITS := 0;
  2439.     TO_IP_QUEUE : QHEADS;
  2440. -- NOTE: ALL QUEUE ROUTINES OPERATE THE SAME AS THOSE IN TCP. THEY ARE
  2441. -- FULLY EXPLAINED IN TCP'S QUEUE PACKAGE.
  2442. --******************
  2443. --* USER SEMANTICS *
  2444. --******************
  2445. --This subprogram allocates and links together in a list (pointed to by
  2446. --queue_free_list) of queue elements to be used by all of the queue
  2447. --routines. It allocates them via new. They are never deallocated.
  2448. --they are simply put back in the free queue element list.
  2449. --the max queue size times the number of queues is the number of queue
  2450. --elements that are allocated.
  2451.     procedure INITIALIZE_QUEUES is
  2452.     NEXT_STRUCTURE : QUEUE_ELEMENT_POINTER;
  2453.     begin
  2454.         QUEUE_FREE_LIST := new QUEUE_ELEMENT;
  2455.         NEXT_STRUCTURE :=  new QUEUE_ELEMENT;
  2456.         QUEUE_FREE_LIST.NEXT := NEXT_STRUCTURE;
  2457.         for I in 3..MAX_QUEUE_SIZE*NUMBER_OF_QUEUES loop
  2458.         -- SET UP A FREE LIST OF QUEUE STRUCTURES.
  2459.             NEXT_STRUCTURE.NEXT := new QUEUE_ELEMENT;
  2460.             NEXT_STRUCTURE := NEXT_STRUCTURE.NEXT;
  2461.         end loop;
  2462.     end INITIALIZE_QUEUES;
  2463.     function GET_Q_STRUCTURE return QUEUE_ELEMENT_POINTER is
  2464.         X : QUEUE_ELEMENT_POINTER;
  2465.         begin
  2466.              X := QUEUE_FREE_LIST;
  2467.             QUEUE_FREE_LIST := QUEUE_FREE_LIST.NEXT;
  2468.             return X;
  2469.         exception
  2470.             when CONSTRAINT_ERROR =>
  2471.         PUT_LINE("CONSTRAINT ERROR IN COMM WITH IP GET_Q_STRUCTURE");
  2472.             when others =>
  2473.         PUT_LINE
  2474.             ("UNKNOWN ERROR RAISED IN COMM. WITH IP GET_Q_STRUCTURE");
  2475.         end GET_Q_STRUCTURE;
  2476.     procedure FREE_Q_STRUCTURE
  2477.         (Q_STRUCTURE : in out QUEUE_ELEMENT_POINTER) is
  2478.         begin
  2479.             Q_STRUCTURE.NEXT := QUEUE_FREE_LIST;
  2480.             QUEUE_FREE_LIST := Q_STRUCTURE; --ADDS TO FRONT OF LIST
  2481.         -- MAKE THE POINTER NULL NOW.
  2482.         Q_STRUCTURE := null;
  2483.         exception
  2484.             when CONSTRAINT_ERROR =>
  2485.             PUT_LINE("CONSTRAINT ERROR IN FREE_Q_STRUCTURE");
  2486.             when others =>
  2487.             PUT_LINE("UNKNOWN ERROR RAISED IN FREE_Q_STRUCTURE");
  2488.         end FREE_Q_STRUCTURE;
  2489.     function QUEUE_EMPTY(QUEUE : QHEADS) return BOOLEAN is
  2490.     RESULT : BOOLEAN := FALSE;
  2491.     begin
  2492.         if QUEUE.ELEMENT_COUNT = 0 then
  2493.         RESULT := TRUE;
  2494.         end if;
  2495.         return RESULT;
  2496.     end QUEUE_EMPTY;
  2497.     procedure QUEUE_GET(QHEAD : in out QHEADS; ITEM : in out Q_ITEM) is
  2498.         Q_ELEMENT_TO_BE_FREED : QUEUE_ELEMENT_POINTER;
  2499.         begin
  2500.             if QHEAD.ELEMENT_COUNT > 0 then
  2501.                 QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  2502.                 Q_ELEMENT_TO_BE_FREED := QHEAD.FIRST_ELEMENT;
  2503.                 ITEM := QHEAD.FIRST_ELEMENT.ELEMENT;
  2504.                 QHEAD.FIRST_ELEMENT := 
  2505.                     QHEAD.FIRST_ELEMENT.NEXT;
  2506.                 IF QHEAD.ELEMENT_COUNT = 0 THEN 
  2507.                             -- AN EMPTY LIST
  2508.                     QHEAD.LAST_ELEMENT := null;
  2509.                 end if;
  2510.                 FREE_Q_STRUCTURE(Q_ELEMENT_TO_BE_FREED); 
  2511.                     -- FREE UP THE FORMER FIRST ELEMENT
  2512.             else -- AN EMPTY LIST
  2513.             PUT_LINE("A FOOLISH QGET ATTEMPT ON AN EMPTY LIST");
  2514.             end if;
  2515.         exception
  2516.             when CONSTRAINT_ERROR =>
  2517.                 PUT_LINE("CONSTRAINT ERROR IN QGET");
  2518.             when others =>
  2519.                 PUT_LINE("UNKNOWN  ERROR IN QUEUE_GET");
  2520.         end QUEUE_GET;
  2521.     procedure QUEUE_ADD(QHEAD : in out QHEADS; ITEM : Q_ITEM) is
  2522.         NEW_ITEM : QUEUE_ELEMENT_POINTER := GET_Q_STRUCTURE;
  2523.         begin
  2524.             NEW_ITEM.ELEMENT := ITEM;
  2525.             NEW_ITEM.NEXT := null;
  2526.             if QHEAD.ELEMENT_COUNT < MAX_QUEUE_SIZE then
  2527.                 if QHEAD.ELEMENT_COUNT /= 0 then 
  2528.                 -- ITS NOT AN EMPTY QUEUE. SO LINK FORMER
  2529.                   -- LAST ITEM TO NEW ONE.
  2530.                      QHEAD.LAST_ELEMENT.NEXT := NEW_ITEM;
  2531.                  else -- FIRST ADD TO THE QUEUE
  2532.                     QHEAD.FIRST_ELEMENT := NEW_ITEM;
  2533.                 end if;
  2534.                 QHEAD.LAST_ELEMENT := NEW_ITEM;
  2535.                 QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT + 1;
  2536.             else -- NO ROOM TOO BAD. PUT Q STRUCTURE 
  2537.                  -- ON THE FREE LIST.
  2538.                 FREE_Q_STRUCTURE(NEW_ITEM);
  2539.             end if;
  2540.         exception
  2541.             when CONSTRAINT_ERROR =>
  2542.                 PUT_LINE("CONSTRAINT ERROR IN QUEUE ADD");
  2543.             when others =>
  2544.                 PUT_LINE("ERROR IN QADD");
  2545.                 INTEGER_IO.PUT(QHEAD.ELEMENT_COUNT);
  2546.     end QUEUE_ADD;
  2547.     procedure SUBNET_TO_IP( DATAGRAM : in PACKED_BUFFER_PTR) is
  2548.                                 
  2549.         begin
  2550.          if DATAGRAM /= null then
  2551.           MESSAGE_TO_IP := ( DATA_FROM_SUBNET,
  2552.                              DATAGRAM,
  2553.                              0,
  2554.                              0,
  2555.                              0,
  2556.                              0,
  2557.                              0);
  2558.          else
  2559.           MESSAGE_TO_IP := ( NO_IP_ACTION,
  2560.                              null,
  2561.                              0,
  2562.                              0,
  2563.                              0,
  2564.                              0);
  2565.          end if;
  2566.          if TO_IP_QUEUE_LENGTH < MAX_QUEUE_SIZE then
  2567.           TO_IP_QUEUE_LENGTH := TO_IP_QUEUE_LENGTH + 1;
  2568.           QUEUE_ADD( TO_IP_QUEUE, MESSAGE_TO_IP );
  2569.          else
  2570.           DATAGRAM.IN_USE := FALSE;
  2571.           DATAGRAM.STATUS := NONE;
  2572.          end if;
  2573.        exception
  2574.         when CONSTRAINT_ERROR =>
  2575.          PUT_LINE("CONSTRAINT_ERROR in SUBNET_TO_IP");
  2576.         when others =>
  2577.          PUT_LINE("UNKNONW error in SUBNET_TO_IP");
  2578.        end SUBNET_TO_IP;
  2579.        
  2580.          procedure SEND_IP(SRC, DEST : in THIRTYTWO_BITS; 
  2581.                           TOS, TTL : in SIXTEEN_BITS; 
  2582.                           BUFFPTR : in out PACKED_BUFFER_PTR; 
  2583.                           LEN , IDENT : in SIXTEEN_BITS;
  2584.                   DONT_FRAGMENT : in SIXTEEN_BITS; 
  2585.                           OPTIONS : in OPTION_TYPE;
  2586.                   RESULT : in out RESULT_TYPE) is
  2587.     begin
  2588.         --/ PUT ON THE QUEUE FOR THE IP. WE DON'T CARE IF ITS LOST./
  2589.         -- SET UP IP MESSAGE.
  2590.     RESULT := OK; -- TEMPORARY WILL BE RESULTS OF 
  2591.                 -- ATTEMPT TO QUEUE IT.
  2592.     MESSAGE_TO_IP := (IP_SEND,
  2593.                       BUFFPTR,
  2594.                           DEST,
  2595.                           TOS,
  2596.                           TTL,
  2597.                           LEN,
  2598.                   IDENT,
  2599.                           DONT_FRAGMENT,
  2600.                           OPTIONS, 
  2601.                           SRC);
  2602.     if TO_IP_QUEUE_LENGTH < MAX_QUEUE_SIZE then
  2603.          TO_IP_QUEUE_LENGTH := TO_IP_QUEUE_LENGTH + 1;
  2604.       -- GO AHEAD AND QUEUE IT UP
  2605.      QUEUE_ADD(TO_IP_QUEUE, MESSAGE_TO_IP);
  2606.      RESULT := OK;
  2607.     else
  2608.      RESULT := NOK;
  2609.      -- RELEASE THE BUFFER FROM USE.
  2610.      BUFFPTR.IN_USE := FALSE;
  2611.     end if;
  2612.     end SEND_IP;
  2613.     procedure IP_WAIT(MESSAGE_TO_IP : in out IP_MESSAGE) is
  2614.                         -- There is a separate queue for packets
  2615.                         -- from the subnet protocol group.  The
  2616.                         -- subnet protocol(s) maintain this queue.
  2617.                         
  2618.         DATAGRAM : PACKED_BUFFER_PTR := null ;
  2619.         
  2620.         begin
  2621.         if TO_IP_QUEUE_LENGTH > 0 then
  2622.          TO_IP_QUEUE_LENGTH := TO_IP_QUEUE_LENGTH - 1;
  2623.          QUEUE_GET( TO_IP_QUEUE, MESSAGE_TO_IP);
  2624.         else
  2625.          MESSAGE_TO_IP := ( NO_IP_ACTION, null, 0,0,0,0);
  2626.          --TEXT_IO.PUT_LINE("TO_IP_QUEUE_LENGTH = 0");
  2627.         end if;
  2628.         exception
  2629.          when CONSTRAINT_ERROR =>
  2630.           NEW_LINE;
  2631.           PUT_LINE(" exception CONSTRAINT_ERROR ");
  2632.           PUT_LINE(" procedure IP_WAIT package WITH_IP_COMMUNICATE ");
  2633.          when others =>
  2634.           NEW_LINE;
  2635.           PUT_LINE(" execption others ");
  2636.           PUT_LINE(" procedure IP_WAIT package WITH_IP_COMMUNICATE ");
  2637.         end IP_WAIT;
  2638. begin -- THE PACKAGE INITIALIZTION.
  2639.     INITIALIZE_QUEUES;
  2640. end WITH_IP_COMMUNICATE;
  2641. --::::::::::::::
  2642. --ncommu.txt
  2643. --::::::::::::::
  2644. -----------------------------------------------------------------------
  2645. --
  2646. --         DoD Protocols    NA-00008-200       80-01184-100(-)
  2647. --         E-Systems, Inc.  August 07, 1985
  2648. --
  2649. --         ncommu.txt       Author : Jim Baldo
  2650. --
  2651. -----------------------------------------------------------------------
  2652. with WITH_TCP_COMMUNICATE;              use WITH_TCP_COMMUNICATE;
  2653. with BUFFER_DATA;            use BUFFER_DATA;
  2654. with T_TCP_GLOBALS_DATA_STRUCTURES ;
  2655. use T_TCP_GLOBALS_DATA_STRUCTURES ;
  2656.                         
  2657.                         package    WITH_ULP_COMMUNICATE is
  2658.         ----------------------------------------------------------
  2659.         --This implementation is for use with the Telesoft Ada  --
  2660.         --compiler version 1.5 .                                --
  2661.         ----------------------------------------------------------
  2662. type STATUS_TYPE is (CONNECTION_OPEN, CONNECTION_CLOSED, OPENING, CLOSING);
  2663. type SECURITIES is array(1..9) of SIXTEEN_BITS;
  2664. type STATE_TYPE is (CLOSED, SYN_SENT, SYN_RECEIVED, ESTABLISHED, LISTEN,
  2665.             FIN_WAIT_1, CLOSE_WAIT, FIN_WAIT_2, CLOSING, TIME_WAIT,
  2666.             LAST_ACK); -- SAME AS IN TCPGLB.
  2667. type STATUS_RECORD is
  2668.  record
  2669.   SOURCE_PORT : SIXTEEN_BITS;
  2670.   SOURCE_ADDRESS : THIRTYTWO_BITS;
  2671.   DESTINATION_PORT : SIXTEEN_BITS;
  2672.   DESTINATION_ADDRESS : THIRTYTWO_BITS;
  2673.   CONNECTION_STATE : STATE_TYPE;
  2674.   STATUS : STATUS_TYPE;
  2675.   LOCAL_RCV_WINDOW : SIXTEEN_BITS;
  2676.   REMOTE_RCV_WINDOW : SIXTEEN_BITS;
  2677.   OCTETS_ON_RETRANSMIT_QUEUE : SIXTEEN_BITS;
  2678.   DATA_WAITING_FOR_ULP : SIXTEEN_BITS;
  2679.   URGENT_STATE : BOOLEAN;
  2680.   PRECEDENCE : SIXTEEN_BITS;
  2681.   SECURITY : SECURITIES;
  2682.   ULP_TIMEOUT : SIXTEEN_BITS;
  2683. end record; 
  2684. type USER_MESSAGE(MESSAGE_NUMBER : SIXTEEN_BITS := 0) is 
  2685.   record
  2686.     LCN : TCB_PTR;
  2687.     case MESSAGE_NUMBER is
  2688.       when 10 | 19  =>
  2689.         DATA_BUFFER : PACKED_BUFFER_PTR;
  2690.       when 15 =>
  2691.             -- STATUS PARAMETERS
  2692.         STATUS_PARAMS : STATUS_RECORD;
  2693.       when others => null;
  2694.     end case;
  2695.   end record;
  2696. PROCEDURE  WAIT_FOR_TCP_MESSAGE(USER_MESS : IN OUT USER_MESSAGE);
  2697.     --This procedure obtains a message in a queue for the ULP from TCP.
  2698. PROCEDURE MESSAGE_FOR_USER(USER_MESS : USER_MESSAGE);
  2699.     --This procedure is used by TCP to put a message  for the ULP.
  2700. end WITH_ULP_COMMUNICATE;
  2701. with TEXT_IO;                use TEXT_IO;
  2702. with ASCII;
  2703.         package    body WITH_ULP_COMMUNICATE is
  2704. -------------------------------------------------------------------------------
  2705. -- THE MESSAGE NUMBERS FOR THE USER AND THEIR MEANING FOLLOW                 --
  2706. -- -1 : NO USER ACTION                                                       --
  2707. --                                                                           --
  2708. -- 2: CONNECTION ILLEGAL                                                     --
  2709. -- 3: CONNECTION DOES NOT EXIST                                              --
  2710. -- 4: FOREIGN SOCKET UNSPECIFIED                                             --
  2711. -- 5: INSUFFICIENT RESOURCES                                                 --
  2712. -- 6: CONNECTION CLOSING                                                     --
  2713. -- 7: URGENT DATA                                                            --
  2714. -- 8: OK ON ABORT                                                            --
  2715. -- 9: PRECEDENCE NOT ALLOWED                                                 --
  2716. -- 10: BUFFER FOR USER                                                       --
  2717. -- 11: SECURITY/COMPARTMENT ILLEGAL                                          --
  2718. -- 12: CONNECTION EXISTS                                                     --
  2719. -- 14: RETURN LCN                                                            --
  2720. -- 15: TCB POINTER AND STATE                                                 --
  2721. -- 16: CONNECTION RESET                                                      --
  2722. -- 17: CONNECTION REFUSED                                                    --
  2723. -- 18: OK ON CLOSE                                                           --
  2724. -- 19: PUSHED BUFFER FOR USER                                                --
  2725. -- 20: OUT OF BUFFERS                                                        --
  2726. -- 21: COULDN'T DO RESET                                                     --
  2727. -- 22: IP OVERLOADED.                                                        --
  2728. -- 23: CONNECTION IS NOW OPEN.                                               --
  2729. -------------------------------------------------------------------------------
  2730. UMAX : constant positive := 32; -- TEMPORARY
  2731. type QUEUE_ELEMENT;
  2732. type QUEUE_ELEMENT_POINTER is access QUEUE_ELEMENT;
  2733. subtype Q_ITEM is USER_MESSAGE;
  2734. type QUEUE_ELEMENT is
  2735.  record
  2736.   ELEMENT : Q_ITEM;
  2737.   NEXT : QUEUE_ELEMENT_POINTER;
  2738.  end record;
  2739. subtype ELEMENT_COUNT_TYPE is SIXTEEN_BITS;
  2740. type QHEADS is 
  2741.  record
  2742.   ELEMENT_COUNT : ELEMENT_COUNT_TYPE := 0;
  2743.   FIRST_ELEMENT : QUEUE_ELEMENT_POINTER;
  2744.   LAST_ELEMENT  : QUEUE_ELEMENT_POINTER;
  2745.  end record;
  2746. QUEUE_FREE_LIST : QUEUE_ELEMENT_POINTER;
  2747. MAX_QUEUE_SIZE : constant positive := 32;
  2748. NUMBER_OF_QUEUES : constant positive := 1;
  2749. TO_USER_QUEUE_LENGTH : SIXTEEN_BITS := 0;
  2750. TO_USER_QUEUE : QHEADS;
  2751. OUTPUT : FILE_TYPE;
  2752. procedure INITIALIZE_QUEUES is
  2753.     --THIS PROCEDURE IS CALLED TO SET UP A FREE LIST OF QUEUE ELEMENTS.
  2754.     --IT IS CALLED AT SYSTEM INITIALIZATION TIME.  THE ROUTINE 
  2755.     --ALLOCATES AND LINKS TOGETHER IN A LIST (POINTED TO BY
  2756.     --QUEUE_FREE_LIST) OF QUEUE ELEMENTS TO BE USED BY ALL OF THE QUEUE
  2757.     --ROUTINES. IT ALLOCATES THEM VIA NEW. THEY ARE NEVER DEALLOCATED.
  2758.     --THEY ARE SIMPLY PUT BACK IN THE FREE QUEUE ELEMENT LIST.
  2759.     --THE MAX QUEUE SIZE TIMES THE NUMBER OF QUEUES IS THE NUMBER OF QUEUE\
  2760.     --ELEMENTS THAT ARE ALLOCATED.
  2761. NEXT_STRUCTURE : QUEUE_ELEMENT_POINTER;
  2762. begin
  2763.  QUEUE_FREE_LIST := NEW QUEUE_ELEMENT;
  2764.  NEXT_STRUCTURE :=  NEW QUEUE_ELEMENT;
  2765.  QUEUE_FREE_LIST.NEXT := NEXT_STRUCTURE;
  2766.  for I in 3..MAX_QUEUE_SIZE*NUMBER_OF_QUEUES loop
  2767.  -- SET UP A FREE LIST OF QUEUE STRUCTURES.
  2768.    NEXT_STRUCTURE.NEXT := NEW QUEUE_ELEMENT;
  2769.    NEXT_STRUCTURE := NEXT_STRUCTURE.NEXT;
  2770.  end loop;
  2771. end INITIALIZE_QUEUES;
  2772. FUNCTION GET_Q_STRUCTURE RETURN QUEUE_ELEMENT_POINTER IS
  2773. X : QUEUE_ELEMENT_POINTER;
  2774. BEGIN
  2775.  X := QUEUE_FREE_LIST;
  2776.  QUEUE_FREE_LIST := QUEUE_FREE_LIST.NEXT;
  2777.  RETURN X;
  2778. EXCEPTION
  2779.  WHEN CONSTRAINT_ERROR =>
  2780.    PUT_LINE("CONSTRAINT ERROR IN GET_Q_STRUCTURE");
  2781.    PUT_LINE("IN COMMUNICATE WITH USER");
  2782. WHEN OTHERS =>
  2783.    PUT_LINE("IN COMMUNICATE WITH USER");
  2784.    PUT_LINE("UNKNOWN ERROR RAISED IN GET_Q_STRUCTURE");
  2785. END GET_Q_STRUCTURE;
  2786. PROCEDURE FREE_Q_STRUCTURE(Q_STRUCTURE : IN OUT QUEUE_ELEMENT_POINTER) IS
  2787. BEGIN
  2788.  Q_STRUCTURE.NEXT := QUEUE_FREE_LIST;
  2789.  QUEUE_FREE_LIST := Q_STRUCTURE; --ADDS TO FRONT OF LIST
  2790. -- MAKE THE POINTER NULL NOW.
  2791.  Q_STRUCTURE := NULL;
  2792. EXCEPTION
  2793.  WHEN CONSTRAINT_ERROR =>
  2794.    PUT_LINE("CONSTRAINT ERROR IN FREE_Q_STRUCTURE");
  2795.    PUT_LINE("IN COMMUNICATE WITH USER");
  2796. WHEN OTHERS =>
  2797.   PUT_LINE("IN COMMUNICATE WITH USER");
  2798.   PUT_LINE("UNKNOWN ERROR RAISED IN FREE_Q_STRUCTURE");
  2799. END;
  2800. FUNCTION QUEUE_EMPTY(QUEUE : QHEADS) RETURN BOOLEAN IS
  2801. RESULT : BOOLEAN := FALSE;
  2802. BEGIN
  2803. IF QUEUE.ELEMENT_COUNT = 0 THEN
  2804.  RESULT := TRUE;
  2805. END IF;
  2806. RETURN RESULT;
  2807. END QUEUE_EMPTY;
  2808. PROCEDURE QUEUE_GET(QHEAD : IN OUT QHEADS; ITEM : IN OUT Q_ITEM) IS
  2809. Q_ELEMENT_TO_BE_FREED : QUEUE_ELEMENT_POINTER;
  2810. BEGIN
  2811. IF QHEAD.ELEMENT_COUNT > 0 THEN
  2812.  QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  2813.  Q_ELEMENT_TO_BE_FREED := QHEAD.FIRST_ELEMENT;
  2814.  ITEM := QHEAD.FIRST_ELEMENT.ELEMENT;
  2815.  QHEAD.FIRST_ELEMENT := QHEAD.FIRST_ELEMENT.NEXT;
  2816.  IF QHEAD.ELEMENT_COUNT = 0 THEN -- AN EMPTY LIST
  2817.    QHEAD.LAST_ELEMENT := NULL;
  2818.  END IF;
  2819.  FREE_Q_STRUCTURE(Q_ELEMENT_TO_BE_FREED); -- FREE UP THE FORMER FIRST ELEMENT
  2820. ELSE -- AN EMPTY LIST
  2821.   PUT_LINE("A FOOLISH QGET ATTEMPT ON AN EMPTY LIST");
  2822. END IF;
  2823. EXCEPTION
  2824. WHEN CONSTRAINT_ERROR =>
  2825.   PUT_LINE("CONSTRAINT ERROR IN QGET");
  2826.   PUT_LINE("IN COMMUNICATE WITH USER");
  2827. WHEN OTHERS =>
  2828.   PUT_LINE("IN COMMUNICATE WITH USER");
  2829.   PUT_LINE("UNKNOWN  ERROR IN QUEUE_GET");
  2830. END QUEUE_GET;
  2831. PROCEDURE QUEUE_DELETE(QHEAD : IN OUT QHEADS; ITEM :Q_ITEM) IS
  2832. BEFORE_PTR : QUEUE_ELEMENT_POINTER := QHEAD.FIRST_ELEMENT;
  2833. CURRENT_ELEMENT_POINTER : QUEUE_ELEMENT_POINTER := QHEAD.FIRST_ELEMENT;
  2834. FOUND : BOOLEAN := FALSE;
  2835. BEGIN
  2836. WHILE CURRENT_ELEMENT_POINTER /= NULL AND (NOT FOUND) LOOP
  2837.   IF CURRENT_ELEMENT_POINTER.ELEMENT = ITEM THEN -- FREE IT AND THE BUFFER UP
  2838.    BEFORE_PTR.NEXT := CURRENT_ELEMENT_POINTER.NEXT;
  2839.    -- TAKE CARE OF DELETING FROM THE END OR BEGINNING OF A LIST.
  2840.    IF QHEAD.FIRST_ELEMENT = CURRENT_ELEMENT_POINTER THEN
  2841.      QHEAD.FIRST_ELEMENT := CURRENT_ELEMENT_POINTER.NEXT;
  2842.    END IF;
  2843.    IF QHEAD.LAST_ELEMENT = CURRENT_ELEMENT_POINTER THEN -- WE ARE DELETING LAST
  2844.                             -- ELEMENT.
  2845.      IF QHEAD.FIRST_ELEMENT /= NULL THEN
  2846.        QHEAD.LAST_ELEMENT := BEFORE_PTR;
  2847.      ELSE -- AN EMPTY LIST NOW
  2848.        QHEAD.LAST_ELEMENT := NULL;
  2849.      END IF;
  2850.    END IF;
  2851. -- FREE THE ELEMENT AND DECREMENT THE ELEMENT COUNT
  2852.    FREE_Q_STRUCTURE(CURRENT_ELEMENT_POINTER);
  2853.    QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  2854.    FOUND := TRUE;
  2855.   ELSE
  2856.    BEFORE_PTR := CURRENT_ELEMENT_POINTER;
  2857.    CURRENT_ELEMENT_POINTER := CURRENT_ELEMENT_POINTER.NEXT;
  2858.   END IF;
  2859. END LOOP;
  2860. IF NOT FOUND THEN
  2861.  --ERROR
  2862.  PUT_LINE("WAS UNABLE TO DELETE");
  2863. END IF;
  2864. EXCEPTION
  2865.  WHEN CONSTRAINT_ERROR =>
  2866.    PUT_LINE("CONSTRAINT ERROR IN QUEUE DELETE");
  2867.    PUT_LINE("IN COMMUNICATE WITH USER");
  2868.  WHEN OTHERS =>
  2869.    PUT_LINE("IN COMMUNICATE WITH USER");
  2870.    PUT_LINE(" ERROR IN QUEUE DELETE");
  2871. END QUEUE_DELETE;
  2872. PROCEDURE QUEUE_CLEAR(QHEAD : IN OUT QHEADS) IS
  2873. X : QUEUE_ELEMENT_POINTER;
  2874. BEGIN
  2875. WHILE QHEAD.ELEMENT_COUNT > 0 LOOP
  2876.  X := QHEAD.FIRST_ELEMENT;
  2877.  QHEAD.FIRST_ELEMENT := X.NEXT;
  2878.  FREE_Q_STRUCTURE(X);
  2879.  QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  2880. END LOOP;
  2881. -- RESET THE HEAD AND TAIL POINTERS.
  2882. QHEAD.FIRST_ELEMENT := NULL;
  2883. QHEAD.LAST_ELEMENT := NULL;
  2884. EXCEPTION
  2885.  WHEN CONSTRAINT_ERROR =>
  2886.    PUT_LINE("CONSTRAINT ERROR IN QUEUE CLEAR");
  2887.    PUT_LINE("IN COMMUNICATE WITH USER");
  2888.  WHEN OTHERS =>
  2889.    PUT_LINE("IN COMMUNICATE WITH USER");
  2890.    PUT_LINE("UNKNOWN ERROR TYPE IN QUEUE CLEAR");
  2891. END QUEUE_CLEAR;
  2892. PROCEDURE QUEUE_ADD(QHEAD : IN OUT QHEADS; ITEM : Q_ITEM) IS
  2893. NEW_ITEM : QUEUE_ELEMENT_POINTER := GET_Q_STRUCTURE;
  2894. BEGIN
  2895. NEW_ITEM.ELEMENT := ITEM;
  2896. NEW_ITEM.NEXT := NULL;
  2897. IF QHEAD.ELEMENT_COUNT < MAX_QUEUE_SIZE THEN
  2898.  IF QHEAD.ELEMENT_COUNT /= 0 THEN -- ITS NOT AN EMPTY QUEUE. SO LINK FORMER
  2899.                   -- LAST ITEM TO NEW ONE.
  2900.   QHEAD.LAST_ELEMENT.NEXT := NEW_ITEM;
  2901.  ELSE -- FIRST ADD TO THE QUEUE
  2902.   QHEAD.FIRST_ELEMENT := NEW_ITEM;
  2903.  END IF;
  2904.  QHEAD.LAST_ELEMENT := NEW_ITEM;
  2905.  QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT + 1;
  2906. ELSE -- NO ROOM TOO BAD
  2907.  FREE_Q_STRUCTURE(NEW_ITEM);
  2908. END IF;
  2909. EXCEPTION
  2910. WHEN CONSTRAINT_ERROR =>
  2911.  PUT_LINE("CONSTRAINT ERROR IN QUEUE ADD");
  2912.   PUT_LINE("IN COMMUNICATE WITH USER");
  2913. WHEN OTHERS =>
  2914.   PUT_LINE("ERROR IN QADD");
  2915.   PUT_LINE("IN COMMUNICATE WITH USER");
  2916.   INTEGER_IO.PUT(QHEAD.ELEMENT_COUNT);
  2917. END QUEUE_ADD;
  2918. procedure MESSAGE_FOR_USER(USER_MESS : USER_MESSAGE) is
  2919. begin
  2920. -- PUT ON THE QUEUE FOR THE USER. THERE SHOULD ALWAYS BE ROOM.
  2921. if TO_USER_QUEUE_LENGTH < UMAX then --QUEUE IT
  2922.  TO_USER_QUEUE_LENGTH := TO_USER_QUEUE_LENGTH + 1;
  2923.  QUEUE_ADD(TO_USER_QUEUE, USER_MESS);
  2924. end if;
  2925. case USER_MESS.MESSAGE_NUMBER is
  2926.  when 10 | 19 =>
  2927.   if USER_MESS.MESSAGE_NUMBER = 10 then
  2928.    --PUT_LINE("User message is 10");
  2929.    PUT(ASCII.BEL);
  2930.   else
  2931.    --PUT_LINE("User message is 19");
  2932.    null;
  2933.   end if;
  2934.  when 15 =>
  2935.   --PUT_LINE("User message is 15");
  2936.   null;
  2937.  when others =>
  2938.   --PUT_LINE("User message is other than 10,15, and 19");
  2939.   --NEW_LINE;
  2940.   --PUT("User Message Number : ");
  2941.   --INTEGER_IO.PUT(USER_MESS.MESSAGE_NUMBER);
  2942.   --NEW_LINE;
  2943.   null;
  2944. end case;
  2945. end MESSAGE_FOR_USER;
  2946. procedure  WAIT_FOR_TCP_MESSAGE(USER_MESS : in out USER_MESSAGE) is
  2947. begin
  2948.  if TO_USER_QUEUE_LENGTH > 0 then --GIVE EM ONE
  2949.    TO_USER_QUEUE_LENGTH := TO_USER_QUEUE_LENGTH - 1;
  2950.    QUEUE_GET(TO_USER_QUEUE, USER_MESS);
  2951.  else -- NOTHING FOR HIM
  2952.    USER_MESS := (-1, null ); -- NO USER ACTION
  2953.  end if;
  2954. end WAIT_FOR_TCP_MESSAGE;
  2955. begin -- INITIALIZE THE QUEUES
  2956.  INITIALIZE_QUEUES;
  2957. END WITH_ULP_COMMUNICATE;
  2958. --::::::::::::::
  2959. --per1.txt
  2960. --::::::::::::::
  2961. -----------------------------------------------------------------------
  2962. --
  2963. --         DoD Protocols    NA-00008-200       80-01185-100(-)
  2964. --         E-Systems, Inc.  August 07, 1985
  2965. --
  2966. --         per1.txt       Author : Jim Baldo
  2967. --
  2968. -----------------------------------------------------------------------
  2969. WITH T_tcp_arrives_1 ;
  2970. with TCP_GLOBALS;        use TCP_GLOBALS;
  2971. with QUEUES;            use QUEUES;
  2972. with T_TCP_GLOBALS_DATA_STRUCTURES;
  2973. use T_TCP_GLOBALS_DATA_STRUCTURES;
  2974. with BUFFER_DATA;        use BUFFER_DATA;
  2975.         
  2976.                 package    TCP_ARRIVES_PERIPHERALS is
  2977.     
  2978.         ----------------------------------------------------------
  2979.     --This implementation is for use with the Telesoft Ada  --
  2980.     --compiler version 1.5 .                                --
  2981.     ----------------------------------------------------------
  2982. ------------------------------------------------------------------------------
  2983. -- THIS    PACKAGE    CONTAINS ALL THE PROCEDURES AND    FUNCTIONS NECESSARY FOR     --
  2984. -- PROCESSING ARRIVED SEGMENTS.    IT ALSO    CONTAINS THE HEADER FORMAT ROUTINE. --
  2985. ------------------------------------------------------------------------------
  2986. --***********************GLOBAL ROUTINES********************************
  2987. procedure PROCESS_RESET_IN_DATA_ACCEPTING_STATES( LCN : in TCB_PTR);
  2988.     --This procedure process an arrived reset in the data accepting 
  2989.     --states. It basically closes down the connection and clears 
  2990.     --the necessary data out of the appropriate queues.
  2991. procedure SEND_A_RESET( LCN : in TCB_PTR);
  2992.     --This procedure will format and send a reset, for the remote host, to
  2993.     --the ip.
  2994. procedure FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES
  2995.                               ( LCN : in out TCB_PTR; 
  2996.                             BUFPTR : in out BUFFER_POINTER);
  2997.     --This procedure checks to see if the fin bit is set. If the fin is 
  2998.     --set it then puts the TCB in the close-wait state.
  2999. procedure PROCESS_SEGMENT_TEXT( LCN : in TCB_PTR; 
  3000.                                 BUFPTR : in out BUFFER_POINTER);
  3001.     --This procedure will determine if text exists and if so fill as many
  3002.     --receive buffers as it can and return them to the user. Any data it 
  3003.     --can not return it will queue up.
  3004. procedure PROCESS_URGENT_FLAG( LCN : in TCB_PTR; 
  3005.                                BUFPTR : in out BUFFER_POINTER);
  3006.     --This procedure checks the urgent bit and if set, it will notify the 
  3007.     --user of urgent data (if the urgent pointer is in advance of the data 
  3008.     --and the user has not already been notified).
  3009. procedure PROCESS_A_FIN( LCN : in out TCB_PTR; 
  3010.                          BUFPTR : in out BUFFER_POINTER);
  3011.     --This procedure will notify the user that the connection is closing,
  3012.     --and return all receives with data if possible. It will also ensure
  3013.     --that an ack was or will be sent for the fin.
  3014. procedure SEND_A_PIGGYBACKED_ACK( LCN : in out TCB_PTR);
  3015.     --This procedure will send an ack together with data (if available) 
  3016.     --to the IP for processing. It will also try to clear the transmit 
  3017.     --queue of data.  By sending it. It will update everything necessary 
  3018.     --in the TCB.
  3019. procedure SEND_FROM_TRANSMIT_QUEUE( LCN : in out TCB_PTR);
  3020.     --This procedure will send any segments from the transmit queue that
  3021.     --will fit in the window. It will format them for transmission.  It 
  3022.     --will check upon emptying its queue for the close pending flag and 
  3023.     --take appropriate action.
  3024. function UNPACK( PACKED_BUFFER : in PACKED_BUFFER_PTR; 
  3025.                  TOTAL_DATA_BYTES : in SIXTEEN_BITS ) return BUFFER_POINTER;
  3026.     --This function will take an array of system.bytes (a bit stream) and
  3027.     --unpack this into an easy to use record. It uses the generic
  3028.     --function unchecked conversion via several functions to move the bits 
  3029.     --into the record fields. The system bytes are considered to be 
  3030.     --integers. We simply move the proper number of bits into the proper 
  3031.     --fields in the record.
  3032. procedure PROCESS_COMMON_ACK( LCN : in TCB_PTR; 
  3033.                               BUFPTR : in BUFFER_POINTER;
  3034.                     RESULT : out T_TCP_ARRIVES_1.RES);
  3035.     --This procedure does all the processing for an arrived ack in the 
  3036.     --established state as per the specification. This processing is 
  3037.     --common to the other states also.
  3038. procedure ENTER_ESTABLISHED_STATE_PROCESSING( LCN : in TCB_PTR; 
  3039.                                               BUFPTR : in out BUFFER_POINTER);
  3040.     --This procedure will perform all the processing of a segment in the
  3041.     --established state, beginning with the check of the urgent flag.
  3042.     --It will also process all the data on the TCP received segment queue.
  3043. procedure SEND_A_SYN_AND_ACK( LCN : in TCB_PTR);
  3044.     --This procedure will format a segment for a syn and an ack and send it
  3045.     --to the IP bound for the remote host.
  3046. procedure BAD_SYN_HANDLER( LCN : in TCB_PTR; 
  3047.                            BUFPTR : in out BUFFER_POINTER);
  3048.     --This procedure checks to make sure that the syn is indeed bad. Then
  3049.     --it sends a reset to the offending host and clears the necessary 
  3050.     --queues of entries for this connection. It tells the user that the 
  3051.     --connection was reset and closes the connection.
  3052. procedure SEND_A_RESET_AND_ACK( LCN : in TCB_PTR);
  3053.     --This procedure will format a header for a segment with the reset 
  3054.     --and ack control bits set. This will be sent to the IP layer for 
  3055.     --transmission to the remote host.
  3056. -- *******************************************************************
  3057. RESULTS    : T_TCP_ARRIVES_1.RES;
  3058. BUFFTYPE : CONSTANT SIXTEEN_BITS  := 1; -- ONLY ONE TYPE OF BUFFER FOR NOW.
  3059. GLOBAL_PACKED_BUFFER : PACKED_BUFFER_PTR;
  3060. end TCP_ARRIVES_PERIPHERALS;
  3061. with IP_GLOBALS ;        use IP_GLOBALS ;
  3062. with TEXT_IO;                   use TEXT_IO;
  3063. with SYSTEM;
  3064. with UNCHECKED_CONVERSION;
  3065. with MODULO;            use MODULO;
  3066. with WITH_TCP_COMMUNICATE;    use WITH_TCP_COMMUNICATE;
  3067. with WITH_IP_COMMUNICATE;       use WITH_IP_COMMUNICATE;
  3068. with WITH_ULP_COMMUNICATE;      use WITH_ULP_COMMUNICATE;
  3069. with TCB_ALLOCATOR;        use TCB_ALLOCATOR;
  3070.         
  3071.                 package    body TCP_ARRIVES_PERIPHERALS is
  3072.     procedure PROCESS_RESET_IN_DATA_ACCEPTING_STATES( LCN : in TCB_PTR) is
  3073.          UMESSAGE : USER_MESSAGE;
  3074.          NULL_BUFF : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3075.          SOCKET_PARAMS : TCB_PTR;
  3076.         begin
  3077.          QUEUE_CLEAR(TCP_RECEIVED_SEGMENT_QUEUE, LCN);
  3078.          -- WE HAVE NO SEND QUEUE AS SUCH. QUEUE_CLEAR(SEND_QUEUE, LCN);
  3079.          QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  3080.          QUEUE_CLEAR(TRANSMIT_QUEUE, LCN);
  3081.          QUEUE_CLEAR(TCP_RETRANSMIT_QUEUE, LCN);
  3082.          QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN);
  3083.          -- TELL USER
  3084.          --  ERROR: CONNECTION RESET 
  3085.          SOCKET_PARAMS := LCN;
  3086.          UMESSAGE := ( 16, 
  3087.                        SOCKET_PARAMS);
  3088.          MESSAGE_FOR_USER(UMESSAGE);
  3089.          LCN.STATE := CLOSED;
  3090.          -- MAY HAVE TO CLEAR THE TCB HERE.
  3091.          TCB_CLEAR(LCN);
  3092.        exception
  3093.         when constraint_error =>
  3094.          PUT_LINE("CONSTRAINT ERROR IN RESET PROCESSOR ");
  3095.          PUT_LINE("OF DATA ACCEPTING STATES");
  3096.         when others =>
  3097.          PUT_LINE("UNKNOWN ERROR IN RESET PROCESSOR ");
  3098.          PUT_LINE("OF DATA ACCEPTING STATES");
  3099.        end PROCESS_RESET_IN_DATA_ACCEPTING_STATES;
  3100.     procedure SEND_A_RESET( LCN : in TCB_PTR) is
  3101.          BUFFTYPE : SIXTEEN_BITS ;
  3102.          BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3103.          PACKED_BUFFER : PACKED_BUFFER_PTR;
  3104.          UMESSAGE : USER_MESSAGE;
  3105.          SOCKET_PARAMS : TCB_PTR;
  3106.          MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  3107.         begin
  3108.          -- GET A BUFFER
  3109.          BUFFGET(PACKED_BUFFER, BUFFTYPE);
  3110.          if PACKED_BUFFER = null then
  3111.           -- TELL USER    ERROR OUT OF BUFFERS
  3112.           SOCKET_PARAMS := LCN;
  3113.           UMESSAGE := ( 20, 
  3114.                         SOCKET_PARAMS);
  3115.           MESSAGE_FOR_USER(UMESSAGE);
  3116.          else
  3117.           PACKED_BUFFER.IN_USE := TRUE ;
  3118.           PACKED_BUFFER.STATUS := OWNER_TCP;
  3119.           -- CLEAR THE OPTIONS ARRAY 
  3120.           OPTIONS := CLEAR;
  3121.           TCP_HEADER_FORMAT(LCN, BUFPTR, RST, OPTIONS);
  3122.           -- HERE WE MUST SET UP THE SECURITY OPTIONS FOR IP
  3123.           OPTIONS := TCP_SECURITY_OPTIONS;
  3124.           -- PACK UP A BUFFER
  3125.           PACK_BUFFER_INTO_BIT_STREAM(BUFPTR, PACKED_BUFFER);
  3126.           LEN := BUFPTR.DATA_OFFSET * 4;
  3127.                     SEND_IP( LCN.DESTINATION_ADDRESS,
  3128.                    LCN.SOURCE_ADDRESS,
  3129.                    TOS,
  3130.                    TTL,
  3131.                    PACKED_BUFFER,
  3132.                    LEN,
  3133.                    IDENT,
  3134.                    DONT_FRAGMENT,
  3135.                    OPTIONS,
  3136.                    RESULT );
  3137. -- UPDATE SEND NEXT IS UNECESSARY.
  3138.           ---  LCN.SND_NXT := LCN.SND_NXT + 1;
  3139. --          if RESULT /= OK then
  3140.            -- TELL USER WE ARE    OUT OF SPACE
  3141. --           SOCKET_PARAMS.LCN := LCN;
  3142. --           SOCKET_PARAMS.FOREIGN_NET_HOST := LCN.DESTINATION_ADDRESS;
  3143. --           SOCKET_PARAMS.FOREIGN_PORT := LCN.FOREIGN_PORT;
  3144. --           UMESSAGE := ( 21, 
  3145. --                         SOCKET_PARAMS);
  3146. --           MESSAGE_FOR_USER(UMESSAGE);
  3147. --          end if;
  3148.          end if;
  3149.         exception
  3150.          when constraint_error =>
  3151.           PUT_LINE("CONSTRAINT ERROR IN SEND A RESET");
  3152.          when others =>
  3153.           PUT_LINE("UNKNOWN ERROR IN SEND A RESET");
  3154.         end SEND_A_RESET;
  3155.     procedure FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES
  3156.             (LCN : in out TCB_PTR; 
  3157.                              BUFPTR : in out 
  3158.                                T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3159.         begin
  3160.          T_TCP_ARRIVES_1.FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES (LCN, BUFPTR);
  3161.         end FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES;
  3162.     procedure PROCESS_SEGMENT_TEXT( LCN : in TCB_PTR; 
  3163.                                         BUFPTR : in out 
  3164.                          T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3165.         begin
  3166.           T_TCP_ARRIVES_1.PROCESS_SEGMENT_TEXT (LCN, BUFPTR) ;
  3167.         end PROCESS_SEGMENT_TEXT;
  3168.     procedure PROCESS_URGENT_FLAG
  3169.             (LCN : in TCB_PTR; BUFPTR : in out 
  3170.                         T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3171.         begin
  3172.           T_TCP_ARRIVES_1.PROCESS_URGENT_FLAG (LCN, BUFPTR) ;
  3173.         end PROCESS_URGENT_FLAG;
  3174.     procedure PROCESS_A_FIN
  3175.      (LCN : in out TCB_PTR; BUFPTR : in out 
  3176.                         T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3177.         
  3178.         begin 
  3179.           T_TCP_ARRIVES_1.PROCESS_A_FIN (LCN, BUFPTR) ;
  3180.         end PROCESS_A_FIN;
  3181. procedure SEND_A_PIGGYBACKED_ACK( LCN : in out TCB_PTR) is
  3182.  begin
  3183.    T_TCP_ARRIVES_1.SEND_A_PIGGYBACKED_ACK (LCN) ;
  3184.  end SEND_A_PIGGYBACKED_ACK;
  3185. procedure SEND_FROM_TRANSMIT_QUEUE(LCN : in out TCB_PTR) is
  3186.         
  3187.   begin
  3188.     T_TCP_ARRIVES_1.SEND_FROM_TRANSMIT_QUEUE (LCN) ;
  3189.   end SEND_FROM_TRANSMIT_QUEUE;
  3190. function UNPACK( PACKED_BUFFER : in PACKED_BUFFER_PTR; 
  3191.                  TOTAL_DATA_BYTES : in SIXTEEN_BITS ) return 
  3192.                       T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER is
  3193.  begin
  3194.   RETURN T_TCP_ARRIVES_1.UNPACK (PACKED_BUFFER, TOTAL_DATA_BYTES) ;
  3195.  end UNPACK;
  3196.     
  3197.     procedure PROCESS_COMMON_ACK( LCN : in TCB_PTR; 
  3198.                                       BUFPTR : in 
  3199.                          T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3200.                           RESULT : out T_TCP_ARRIVES_1.RES) is
  3201.         begin
  3202.           T_TCP_ARRIVES_1.PROCESS_COMMON_ACK ( LCN, 
  3203.                                              BUFPTR,
  3204.                                              RESULT) ;
  3205.         end PROCESS_COMMON_ACK;
  3206.     procedure ENTER_ESTABLISHED_STATE_PROCESSING
  3207.                 ( LCN : in TCB_PTR; BUFPTR : in out
  3208.                    T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3209.     begin
  3210.           T_TCP_ARRIVES_1.ENTER_ESTABLISHED_STATE_PROCESSING (LCN,
  3211.                                                             BUFPTR) ;
  3212.     end ENTER_ESTABLISHED_STATE_PROCESSING;
  3213.     
  3214.         procedure SEND_A_SYN_AND_ACK( LCN : in TCB_PTR) is
  3215.     
  3216.         BUFFTYPE : SIXTEEN_BITS ;
  3217.     BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3218.     PACKED_BUFFER : PACKED_BUFFER_PTR;
  3219.     UMESSAGE : USER_MESSAGE;
  3220.     Q_ITEM : STD_Q_ITEM;
  3221.         SOCKET_PARAMS : TCB_PTR;
  3222.         MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  3223.     
  3224.         begin
  3225.      -- CLEAR THE OPTIONS ARRAY AND THE NECESSARY 
  3226.      -- EXTRA HEADER OCTETS GET ADDED IN.
  3227.      --TEXT_IO.PUT_LINE("IN SEND A SYN AND ACK");
  3228.          BUFFGET(PACKED_BUFFER, BUFFTYPE);
  3229.      if PACKED_BUFFER = null then
  3230.           -- TELL USER    ERROR OUT OF BUFFERS
  3231.           TEXT_IO.PUT_LINE("OUT OF BUFFERS SEND A SYN ACK");
  3232.           SOCKET_PARAMS := LCN;
  3233.           UMESSAGE := ( 20, 
  3234.                         SOCKET_PARAMS);
  3235.         MESSAGE_FOR_USER(UMESSAGE);
  3236.      else
  3237.         PACKED_BUFFER.IN_USE := TRUE;
  3238.           PACKED_BUFFER.STATUS := OWNER_TCP;
  3239.           TCP_HEADER_FORMAT(LCN, BUFPTR, SYN_ACK, OPTIONS);
  3240.         -- HERE WE MUST SET UP THE SECURITY OPTIONS FOR IP
  3241.         OPTIONS := TCP_SECURITY_OPTIONS;
  3242.         -- PACK A BUFFER
  3243.         PACK_BUFFER_INTO_BIT_STREAM(BUFPTR, PACKED_BUFFER);
  3244.         LEN := BUFPTR.DATA_OFFSET * 4;
  3245.           SEND_IP( LCN.SOURCE_ADDRESS,
  3246.                    LCN.DESTINATION_ADDRESS,
  3247.                    TOS,
  3248.                    TTL,
  3249.                    PACKED_BUFFER,
  3250.                    LEN,
  3251.                    IDENT,
  3252.                    DONT_FRAGMENT,
  3253.                    OPTIONS,
  3254.                    RESULT );
  3255.                    
  3256. --        if RESULT = OK then
  3257.            -- PUT BUFFER ON THE RETRANSMISSION QUEUE.
  3258.            LCN.SND_NXT := LCN.SND_NXT + MODULAR_CONVERT( SIXTEEN_BITS (1) ) ;
  3259.            Q_ITEM := (PACKED_BUFFER,  NULL_UNPACKED_BUFFER, LEN);
  3260.            QUEUE_ADD(TCP_RETRANSMIT_QUEUE, LCN, Q_ITEM);
  3261. --        else
  3262. --           -- TELL USER WE ARE    OUT OF SPACE
  3263. --           SOCKET_PARAMS.LCN := LCN;
  3264. --           SOCKET_PARAMS.FOREIGN_NET_HOST := LCN.DESTINATION_ADDRESS;
  3265. --           SOCKET_PARAMS.FOREIGN_PORT := LCN.FOREIGN_PORT;
  3266. --           UMESSAGE := ( 22,
  3267. --                         SOCKET_PARAMS);
  3268. --           MESSAGE_FOR_USER(UMESSAGE);
  3269. --        end if;
  3270.      end if;
  3271.     exception
  3272.       when constraint_error =>
  3273.          PUT_LINE("CONSTRAINT ERROR IN SEND A SYN AND ACK");
  3274.       when others =>
  3275.          PUT_LINE("UNKNOWN ERROR IN SEND A SYN AND ACK");
  3276.     end SEND_A_SYN_AND_ACK;
  3277.     
  3278.         procedure BAD_SYN_HANDLER( LCN : in TCB_PTR; 
  3279.                                    BUFPTR : in out 
  3280.                             T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3281.     UMESSAGE : USER_MESSAGE;
  3282.         NULL_BUFF : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3283.         SOCKET_PARAMS : TCB_PTR;
  3284.     begin
  3285.      -- THE SYN SHOULD BE IN THE WINDOW OR WE WOULD NOT BE HERE
  3286.        if (BUFPTR.SEQ_NUM >= LCN.RCV_NXT) 
  3287.         and (BUFPTR.SEQ_NUM <= 
  3288.            LCN.RCV_NXT +
  3289.            LCN.RCV_WINDOW) then
  3290.           SEND_A_RESET(LCN);
  3291.       -- CLEAR THE QUEUES OUT
  3292.          QUEUE_CLEAR(TCP_RECEIVED_SEGMENT_QUEUE, LCN);
  3293.           -- WE HAVE NO SEND QUEUE AS SUCH. QUEUE_CLEAR(SEND_QUEUE, LCN);
  3294.          QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  3295.          QUEUE_CLEAR(TRANSMIT_QUEUE, LCN);
  3296.          QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN);
  3297.          QUEUE_CLEAR(TCP_RETRANSMIT_QUEUE, LCN);
  3298.           -- TELL USER
  3299.           --  ERROR: CONNECTION RESET 
  3300.           SOCKET_PARAMS := LCN;
  3301.           UMESSAGE := ( 16, 
  3302.                         SOCKET_PARAMS);
  3303.           MESSAGE_FOR_USER(UMESSAGE);
  3304.           LCN.STATE := CLOSED;
  3305.           -- MAY HAVE TO CLEAR THE TCB HERE.
  3306.          TCB_CLEAR(LCN);
  3307.        else
  3308.           -- ERROR: WE'VE MADE A MISTAKE
  3309.           TCP_ERROR(9);
  3310.        end if;
  3311.     exception
  3312.       when constraint_error =>
  3313.          PUT_LINE("CONSTRAINT ERROR IN BAD SYN HANDLER");
  3314.       when others =>
  3315.          PUT_LINE("UNKNOWN ERROR IN BAD SYN HANDLER");
  3316.     end BAD_SYN_HANDLER;
  3317.     procedure SEND_A_RESET_AND_ACK( LCN : in TCB_PTR) is
  3318.     BUFFTYPE : SIXTEEN_BITS ;
  3319.     BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3320.     PACKED_BUFFER : PACKED_BUFFER_PTR;
  3321.     UMESSAGE : USER_MESSAGE;
  3322.         SOCKET_PARAMS : TCB_PTR;
  3323.         MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  3324.     begin
  3325.      -- GET A BUFFER
  3326.      BUFFGET(PACKED_BUFFER,    BUFFTYPE);
  3327.      if PACKED_BUFFER = null then
  3328.         -- TELL USER    ERROR OUT OF BUFFERS
  3329.           SOCKET_PARAMS := LCN;
  3330.         UMESSAGE := ( 20, 
  3331.                         SOCKET_PARAMS);
  3332.         MESSAGE_FOR_USER(UMESSAGE);
  3333.      else
  3334.         PACKED_BUFFER.IN_USE := TRUE;
  3335.           PACKED_BUFFER.STATUS := OWNER_TCP;
  3336.           -- CLEAR THE OPTIONS ARRAY 
  3337.         OPTIONS := CLEAR;
  3338.         TCP_HEADER_FORMAT(LCN, BUFPTR, RST_ACK, OPTIONS);
  3339.         -- HERE WE MUST SET UP THE SECURITY OPTIONS FOR IP
  3340.         OPTIONS := TCP_SECURITY_OPTIONS;
  3341.         -- PACK BUFFER UP
  3342.         PACK_BUFFER_INTO_BIT_STREAM(BUFPTR, PACKED_BUFFER);
  3343.         -- THE LENGTH OF THE BUFFER WILL BE HEADER LENGTH ONLY
  3344.           SEND_IP( LCN.DESTINATION_ADDRESS,
  3345.                    LCN.SOURCE_ADDRESS,
  3346.                    TOS,
  3347.                    TTL,
  3348.                    PACKED_BUFFER,
  3349.                    LEN,
  3350.                    IDENT,
  3351.                    DONT_FRAGMENT,
  3352.                    OPTIONS,
  3353.                    RESULT );
  3354. --      if RESULT = OK then
  3355.        -- UPDATE SEND NEXT. NOT REALLY NECESSARY.
  3356. --       null;
  3357. --      else
  3358. --           -- TELL USER WE ARE    OUT OF SPACE
  3359. --           SOCKET_PARAMS.LCN := LCN;
  3360. --           SOCKET_PARAMS.FOREIGN_NET_HOST := LCN.DESTINATION_ADDRESS;
  3361. --           SOCKET_PARAMS.FOREIGN_PORT := LCN.FOREIGN_PORT;
  3362. --           UMESSAGE := ( 22,
  3363. --                         SOCKET_PARAMS);
  3364. --           MESSAGE_FOR_USER(UMESSAGE);
  3365. --          end if;
  3366.      end if;
  3367.         exception
  3368.       when constraint_error =>
  3369.          PUT_LINE("CONSTRAINT ERROR IN SEND A RESET AND ACK");
  3370.       when others =>
  3371.          PUT_LINE("UNKNOWN ERROR IN SEND A RESET AND ACK");
  3372.     end SEND_A_RESET_AND_ACK;
  3373. end TCP_ARRIVES_PERIPHERALS;
  3374. --::::::::::::::
  3375. --per1b.txt
  3376. --::::::::::::::
  3377. -----------------------------------------------------------------------
  3378. --
  3379. --         DoD Protocols    NA-00008-200       80-01186-100(-)
  3380. --         E-Systems, Inc.  August 07, 1985
  3381. --
  3382. --         per1b.txt       Author : Jim Baldo
  3383. --
  3384. -----------------------------------------------------------------------
  3385. with WITH_ULP_COMMUNICATE;      use WITH_ULP_COMMUNICATE;
  3386. with TCP_GLOBALS;        use TCP_GLOBALS;
  3387. with QUEUES;            use QUEUES;
  3388. with T_TCP_GLOBALS_DATA_STRUCTURES;
  3389. use T_TCP_GLOBALS_DATA_STRUCTURES;
  3390. with BUFFER_DATA;        use BUFFER_DATA;
  3391.         
  3392.                 package    T_TCP_ARRIVES_1 is
  3393.     
  3394.         ----------------------------------------------------------
  3395.     --This implementation is for use with the Telesoft Ada  --
  3396.     --compiler version 1.5 .                                --
  3397.     ----------------------------------------------------------
  3398. ------------------------------------------------------------------------------
  3399. -- THIS    PACKAGE    CONTAINS SOME OF THE PROCEDURES AND FUNCTIONS NECESSARY FOR --
  3400. -- PROCESSING ARRIVED SEGMENTS.    PCKG. REQUIRED TO REDUCE FILE SIZE          --
  3401. ------------------------------------------------------------------------------
  3402. type RES is (GOOD, BAD);
  3403. --***********************GLOBAL ROUTINES********************************
  3404. procedure FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES
  3405.                               ( LCN : in out TCB_PTR; 
  3406.                             BUFPTR : in out BUFFER_POINTER);
  3407.     --This procedure checks to see if the fin bit is set. If the fin is 
  3408.     --set it then puts the TCB in the close-wait state.
  3409. procedure PROCESS_SEGMENT_TEXT( LCN : in TCB_PTR; 
  3410.                                 BUFPTR : in out BUFFER_POINTER);
  3411.     --This procedure will determine if text exists and if so fill as many
  3412.     --receive buffers as it can and return them to the user. Any data it 
  3413.     --can not return it will queue up.
  3414. procedure PROCESS_URGENT_FLAG( LCN : in TCB_PTR; 
  3415.                                BUFPTR : in out BUFFER_POINTER);
  3416.     --This procedure checks the urgent bit and if set, it will notify the 
  3417.     --user of urgent data (if the urgent pointer is in advance of the data 
  3418.     --and the user has not already been notified).
  3419. procedure PROCESS_A_FIN( LCN : in out TCB_PTR; 
  3420.                          BUFPTR : in out BUFFER_POINTER);
  3421.     --This procedure will notify the user that the connection is closing,
  3422.     --and return all receives with data if possible. It will also ensure
  3423.     --that an ack was or will be sent for the fin.
  3424. procedure SEND_A_PIGGYBACKED_ACK( LCN : in out TCB_PTR);
  3425.     --This procedure will send an ack together with data (if available) 
  3426.     --to the IP for processing. It will also try to clear the transmit 
  3427.     --queue of data.  By sending it. It will update everything necessary 
  3428.     --in the TCB.
  3429. procedure SEND_FROM_TRANSMIT_QUEUE( LCN : in out TCB_PTR);
  3430.     --This procedure will send any segments from the transmit queue that
  3431.     --will fit in the window. It will format them for transmission.  It 
  3432.     --will check upon emptying its queue for the close pending flag and 
  3433.     --take appropriate action.
  3434. function UNPACK( PACKED_BUFFER : in PACKED_BUFFER_PTR; 
  3435.                  TOTAL_DATA_BYTES : in SIXTEEN_BITS ) return BUFFER_POINTER;
  3436.     --This function will take an array of system.bytes (a bit stream) and
  3437.     --unpack this into an easy to use record. It uses the generic
  3438.     --function unchecked conversion via several functions to move the bits 
  3439.     --into the record fields. The system bytes are considered to be 
  3440.     --integers. We simply move the proper number of bits into the proper 
  3441.     --fields in the record.
  3442. procedure PROCESS_COMMON_ACK( LCN : in TCB_PTR; 
  3443.                               BUFPTR : in BUFFER_POINTER;
  3444.                     RESULT : out RES);
  3445.     --This procedure does all the processing for an arrived ack in the 
  3446.     --established state as per the specification. This processing is 
  3447.     --common to the other states also.
  3448. procedure ENTER_ESTABLISHED_STATE_PROCESSING( LCN : in TCB_PTR; 
  3449.                                               BUFPTR : in out BUFFER_POINTER);
  3450.     --This procedure will perform all the processing of a segment in the
  3451.     --established state, beginning with the check of the urgent flag.
  3452.     --It will also process all the data on the TCP received segment queue.
  3453. -- *******************************************************************
  3454. RESULTS    : RES;
  3455. BUFFTYPE : CONSTANT SIXTEEN_BITS  := 1; -- ONLY ONE TYPE OF BUFFER FOR NOW.
  3456. GLOBAL_PACKED_BUFFER : PACKED_BUFFER_PTR;
  3457. end T_TCP_ARRIVES_1 ;
  3458. with IP_GLOBALS ;        use IP_GLOBALS ;
  3459. with TEXT_IO;                   use TEXT_IO, INTEGER_IO;
  3460. with SYSTEM;
  3461. with UNCHECKED_CONVERSION;
  3462. with MODULO;            use MODULO;
  3463. with WITH_IP_COMMUNICATE;       use WITH_IP_COMMUNICATE;
  3464. with WITH_TCP_COMMUNICATE;    use WITH_TCP_COMMUNICATE;
  3465. with TCB_ALLOCATOR;        use TCB_ALLOCATOR;
  3466.         
  3467.                 package    body T_TCP_ARRIVES_1 is
  3468. procedure FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES( LCN : in out TCB_PTR; 
  3469.                                                       BUFPTR : in out 
  3470.                                T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3471.         
  3472. begin
  3473.  if BUFPTR.FIN = BIT_SET then
  3474.   PROCESS_A_FIN(LCN, BUFPTR);
  3475.   LCN.STATE := CLOSE_WAIT;
  3476.  end if;
  3477. exception
  3478.  when constraint_error =>
  3479.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN FIN CHECKER");
  3480.  when others =>
  3481.   TEXT_IO.PUT_LINE("UNKNOWN ERROR IN FIN CHECKER");
  3482. end FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES;
  3483.     
  3484. procedure PROCESS_SEGMENT_TEXT( LCN : in TCB_PTR; 
  3485.                                 BUFPTR : in out 
  3486.                  T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3487.         
  3488. NEW_DATA : SIXTEEN_BITS  := BUFPTR.DATA_LEN;
  3489. NULL_BUFFER : PACKED_BUFFER_PTR := NULL;
  3490. PACKED_BUFF, RECEIVE_BUFFER, 
  3491. QUEUED_DATA_BUFFER : PACKED_BUFFER_PTR;
  3492. BUFFTYPE, LENGTH, DATA_LENGTH : SIXTEEN_BITS ;
  3493. UMESSAGE : USER_MESSAGE;
  3494. Q_ITEM : STD_Q_ITEM;
  3495. LCN_OUT : TCB_PTR := LCN; -- NECESSARY TO PASS OUT THE LCN
  3496. DATA_QUEUED_FOR_USER : BOOLEAN := TRUE;
  3497. SOCKET_PARAMS : TCB_PTR;
  3498. begin
  3499.  while not QUEUE_EMPTY(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN_OUT) 
  3500.    and then (NOT QUEUE_EMPTY(RECEIVE_QUEUE, LCN_OUT)) loop 
  3501.   -- SO DATA EXISTS AND A RECEIVE
  3502.   -- GET A BUFFER OFF OF THE PROCESSED QUEUE
  3503.   QUEUE_GET(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN, Q_ITEM);
  3504.   QUEUED_DATA_BUFFER := Q_ITEM.BUFFER;
  3505.   DATA_LENGTH := Q_ITEM.LENGTH;
  3506.   QUEUE_GET(RECEIVE_QUEUE, LCN, Q_ITEM);
  3507.   RECEIVE_BUFFER := Q_ITEM.BUFFER;
  3508.   LENGTH := Q_ITEM.LENGTH;
  3509.   if RECEIVE_BUFFER /= null then 
  3510.    -- SHOULD NEVER HAPPEN THAT IT IS NULL
  3511.    -- FILL A RECEIVE BUFFER AND RETURN IT TO THE USER
  3512.    INSERT_TEXT_IN_BUFFER(LENGTH, RECEIVE_BUFFER, DATA_LENGTH, 
  3513.                          QUEUED_DATA_BUFFER);
  3514.    -- SET UP MESSAGE
  3515.    SOCKET_PARAMS := LCN;
  3516.    UMESSAGE := ( 10, 
  3517.                  SOCKET_PARAMS,
  3518.                  RECEIVE_BUFFER);
  3519.    MESSAGE_FOR_USER(UMESSAGE);
  3520.    -- FREE UP THE BUFFER FROM THE PROCESSED Q SINCE ONE EXISTS.
  3521.    BUFFREE(QUEUED_DATA_BUFFER, BUFFTYPE);
  3522.    -- GO TRY TO GET A NEW ONE.
  3523.   else
  3524.    -- PUT IT BACK ON THE QUEUE
  3525.    -- RESTORE THE Q_ITEM.
  3526.    Q_ITEM.BUFFER := QUEUED_DATA_BUFFER;
  3527.    Q_ITEM.LENGTH := DATA_LENGTH;
  3528.    QUEUE_ADD_TO_FRONT(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN, Q_ITEM);
  3529.    TEXT_IO.PUT_LINE("A STRANGE RESULT IN PROCESS TEXT");
  3530.   end if;
  3531.  end loop;
  3532.  if NEW_DATA > 0 then
  3533.   QUEUE_GET(RECEIVE_QUEUE, LCN, Q_ITEM);
  3534.   RECEIVE_BUFFER := Q_ITEM.BUFFER;
  3535.   LENGTH := Q_ITEM.LENGTH;
  3536.   if RECEIVE_BUFFER /= null then -- WE GOT ONE
  3537.    -- PUT IN THE DATA
  3538.    RECEIVE_BUFFER.BYTE
  3539.     (RECEIVE_BUFFER.TCP_PTR..RECEIVE_BUFFER.TCP_PTR
  3540.                 + NEW_DATA - 1) := BUFPTR.DATA(1..NEW_DATA);
  3541.    RECEIVE_BUFFER.TELNET_PTR := RECEIVE_BUFFER.TCP_PTR + NEW_DATA - 1;
  3542.    if BUFPTR.PUSH_FLAG = BIT_SET then
  3543.     -- NOTIFY USER WHEN DATA IS RETURNED
  3544.     -- SET UP PROPER MESSAGE RECORD
  3545.     SOCKET_PARAMS := LCN;
  3546.     UMESSAGE := ( 19, 
  3547.                   SOCKET_PARAMS,
  3548.                   NULL_BUFFER);
  3549.     MESSAGE_FOR_USER(UMESSAGE);
  3550.    end if;
  3551.    -- GIVE IT TO THE USER
  3552.    -- SET UP MESSAGE
  3553.    SOCKET_PARAMS := LCN;
  3554.    UMESSAGE := ( 10, 
  3555.                  SOCKET_PARAMS,
  3556.                  RECEIVE_BUFFER);
  3557.    MESSAGE_FOR_USER(UMESSAGE);
  3558.   else
  3559.    -- TRY TO QUEUE IT ON UP
  3560.    BUFFGET(PACKED_BUFF, BUFFTYPE);
  3561.    if PACKED_BUFF = null then
  3562.     TCP_ERROR(7);
  3563.     DATA_QUEUED_FOR_USER := FALSE;
  3564.    else
  3565.     -- SET UP THE POINTER AND INSERT ALL THE DATA.
  3566.     PACKED_BUFF.STATUS := OWNER_TCP;
  3567.     PACKED_BUFF.IN_USE := TRUE;
  3568.     PACKED_BUFF.TCP_PTR := 10;
  3569.     -- PUT THE DATA IN THE BUFFER
  3570.     PACKED_BUFF.BYTE(10..9+NEW_DATA) := 
  3571.         BUFPTR.DATA(1..NEW_DATA);
  3572.     Q_ITEM := 
  3573.      (PACKED_BUFF,  NULL_UNPACKED_BUFFER, NEW_DATA);
  3574.     QUEUE_ADD(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN, Q_ITEM);
  3575.    end if;
  3576.   end if;
  3577.  end if;
  3578.  -- IF WE GOT SOME TEXT WE WILL UPDATE RCV_NXT 
  3579.  -- AND SEND A PIGGYBACKED ACK.
  3580.  if NEW_DATA > 0 and (DATA_QUEUED_FOR_USER) then
  3581.   LCN.RCV_NXT := LCN.RCV_NXT + NEW_DATA;
  3582.  if BUFPTR.FIN = BIT_SET then 
  3583.   -- ADVANCE RCV NEXT OVER THE FIN ALSO. THIS WILL
  3584.   -- CAUSE IT TO ALSO BE ACKED.
  3585.   LCN.RCV_NXT := LCN.RCV_NXT + MODULAR_CONVERT( SIXTEEN_BITS( 1 ) ) ;
  3586.  end if;
  3587.  SEND_A_PIGGYBACKED_ACK(LCN_OUT);
  3588. end if;
  3589. exception
  3590. when constraint_error =>
  3591.  TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN PROCESS SEGMENT TEXT");
  3592.  INTEGER_IO.PUT(RECEIVE_BUFFER.TCP_PTR);
  3593.  INTEGER_IO.PUT(NEW_DATA);
  3594.  TEXT_IO.PUT_LINE("");
  3595. when others =>
  3596.  TEXT_IO.PUT_LINE("ERROR IN PROCESS SEGMENT TEXT");
  3597. end PROCESS_SEGMENT_TEXT;
  3598.     
  3599. procedure PROCESS_URGENT_FLAG
  3600.                 (LCN : in TCB_PTR; BUFPTR : in out 
  3601.                 T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3602. UMESSAGE : USER_MESSAGE;
  3603. SOCKET_PARAMS : TCB_PTR;
  3604.         
  3605. begin
  3606.  if BUFPTR.URG_FLAG = BIT_SET then
  3607.   if LCN.RCV_URGENT_POINTER < BUFPTR.URG_PTR then
  3608.    LCN.RCV_URGENT_POINTER := BUFPTR.URG_PTR;
  3609.   end if;
  3610.   if (LCN.USER_NOTIFICATION = FALSE) 
  3611.     and (LCN.RCV_URGENT_POINTER
  3612.     > BUFPTR.DATA_LEN) then
  3613.    -- TELL USER
  3614.    -- URGENT DATA IS ON THE WAY.
  3615.    SOCKET_PARAMS := LCN;
  3616.    UMESSAGE := ( 7, 
  3617.                  SOCKET_PARAMS);
  3618.    MESSAGE_FOR_USER(UMESSAGE);
  3619.    LCN.USER_NOTIFICATION := TRUE;
  3620.   end if;
  3621.  else
  3622.   LCN.USER_NOTIFICATION := FALSE;
  3623.  end if;
  3624. exception
  3625.  when constraint_error =>
  3626.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN PROCESS URGENT FLAG");
  3627.  when others =>
  3628.   TEXT_IO.PUT_LINE("UNKNOWN ERROR IN PROCESS URGENT FLAG");
  3629. end PROCESS_URGENT_FLAG;
  3630.     
  3631. procedure PROCESS_A_FIN( LCN : in out TCB_PTR; 
  3632.                          BUFPTR : in out 
  3633.                         T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  3634.         
  3635. UMESSAGE : USER_MESSAGE ;
  3636. LENGTH, DATA_LENGTH, INDEX, INDEX1 : SIXTEEN_BITS ;
  3637. RECEIVED_PACKED_BUFFER, PACKED_BUFFER : PACKED_BUFFER_PTR ;
  3638. BUFFTYPE : SIXTEEN_BITS ;
  3639. Q_ITEM : STD_Q_ITEM ;
  3640. SOCKET_PARAMS : TCB_PTR ;
  3641. begin 
  3642.  -- NOTE THAT THE FIN IMPLIES A PUSH FUNCTION 
  3643.  -- WHICH WE CURRENTLY DO NOT IMPLEMENT.
  3644.  -- TELL USER CONNECTION CLOSING IF HE HAS 
  3645.  -- NOT ALREADY REQUESTED A CLOSE.
  3646.  if LCN.STATE /= T_TCP_GLOBALS_DATA_STRUCTURES.FIN_WAIT_1 and 
  3647.    (LCN.STATE /= T_TCP_GLOBALS_DATA_STRUCTURES.FIN_WAIT_2) then
  3648.   SOCKET_PARAMS := LCN;
  3649.   UMESSAGE := ( 6, 
  3650.                 SOCKET_PARAMS);
  3651.   MESSAGE_FOR_USER(UMESSAGE);
  3652.  end if;
  3653.  QUEUE_GET(RECEIVE_QUEUE, LCN, Q_ITEM);
  3654.  RECEIVED_PACKED_BUFFER := Q_ITEM.BUFFER;
  3655.  LENGTH := Q_ITEM.LENGTH;
  3656.  while RECEIVED_PACKED_BUFFER /= null loop
  3657.   QUEUE_GET(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN, Q_ITEM);
  3658.   PACKED_BUFFER := Q_ITEM.BUFFER;
  3659.   DATA_LENGTH := Q_ITEM.LENGTH;
  3660.   if PACKED_BUFFER /= null then
  3661.    -- FILL RECEIVE BUFFER WITH DATA, INDICATE A 
  3662.    -- PUSH AND DELETE DATA FROM Q.
  3663.    -- A PUSH IS AUTOMATICALLY IMPLIED AND Q ROUTINE 
  3664.    -- PERFORMS DELETE.   RETURN THE DATA
  3665.    INSERT_TEXT_IN_BUFFER(LENGTH, RECEIVED_PACKED_BUFFER, 
  3666.     DATA_LENGTH,PACKED_BUFFER);
  3667.    -- FREE UP THE UNEEDED BUFFER FROM PROCESSED Q.
  3668.    PACKED_BUFFER.STATUS := NONE;
  3669.    BUFFREE(PACKED_BUFFER, BUFFTYPE);
  3670.    -- GET THE NEXT RECEIVE.
  3671.    QUEUE_GET(RECEIVE_QUEUE, LCN, Q_ITEM);
  3672.    RECEIVED_PACKED_BUFFER := Q_ITEM.BUFFER;
  3673.    LENGTH := Q_ITEM.LENGTH;
  3674.   else -- PUT RECEIVE BACK ON QUEUE
  3675.    Q_ITEM := (RECEIVED_PACKED_BUFFER, 
  3676.      NULL_UNPACKED_BUFFER, LENGTH);
  3677.    QUEUE_ADD_TO_FRONT(RECEIVE_QUEUE, LCN, Q_ITEM);
  3678.    RECEIVED_PACKED_BUFFER := NULL; -- DID NOT GET ANY TEXT
  3679.   end if;
  3680.  end loop;
  3681.  -- DETERMINE IF FIN WAS ACKED PREVIOUSLY, 
  3682.  -- IF NOT ADVANCE RCV.NXT AND ACK IT
  3683.  if LCN.RCV_NXT <= BUFPTR.SEQ_NUM then
  3684.   -- ADVANCE IT AND SEND AN ACK
  3685.   LCN.RCV_NXT := LCN.RCV_NXT + MODULAR_CONVERT( SIXTEEN_BITS ( 1 ) ) ;
  3686.   SEND_A_PIGGYBACKED_ACK(LCN);
  3687.  end if;
  3688. exception
  3689.  when constraint_error =>
  3690.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN PROCESS A FIN");
  3691.  when others =>
  3692.   TEXT_IO.PUT_LINE("UNKNOWN ERROR IN PROCESS A FIN");
  3693. end PROCESS_A_FIN;
  3694. procedure SEND_A_PIGGYBACKED_ACK( LCN : in out TCB_PTR) is
  3695. TRANS_BUFFER : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3696. LENGTH, BUFFTYPE : SIXTEEN_BITS ;
  3697. QUEUE_EMPTY : BOOLEAN;
  3698. TYPE_FLAG : HEADER_TYPE;
  3699. PACKED_BUFFER : PACKED_BUFFER_PTR;
  3700. Q_ITEM : STD_Q_ITEM;
  3701. ACK_BUFFER_EXISTS : BOOLEAN := TRUE;
  3702. MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  3703.  
  3704.  procedure SET_UP_TO_SEND_AN_ACK is
  3705.      -- EVERTHING IS EXTERNAL TO THIS PROCEDURE. 
  3706.      -- WHICH GETS A BUFFER,SETS THE TYPE FLAG AND UPDATES SND_NXT.
  3707.  begin
  3708.   -- MUST GET A BUFFER
  3709.   BUFFGET(PACKED_BUFFER, BUFFTYPE);
  3710.   if PACKED_BUFFER = null then
  3711.    --WE HAVE A BAD ERROR
  3712.    TCP_ERROR(7);
  3713.    ACK_BUFFER_EXISTS := FALSE;
  3714.   else
  3715.    PACKED_BUFFER.IN_USE := FALSE;
  3716.    PACKED_BUFFER.STATUS := NONE;
  3717.    TYPE_FLAG := ACK;
  3718.   end if;
  3719.  end SET_UP_TO_SEND_AN_ACK;
  3720.  
  3721. begin
  3722.  -- GET A BUFFER FROM THE TRANSMIT QUEUE IF POSSIBLE.
  3723.  QUEUE_GET(TRANSMIT_QUEUE, LCN, Q_ITEM);
  3724.  PACKED_BUFFER := Q_ITEM.BUFFER;
  3725.  LENGTH := Q_ITEM.LENGTH;
  3726.  QUEUE_EMPTY := PACKED_BUFFER = null;
  3727.  if not QUEUE_EMPTY then
  3728.   if LCN.SND_WND + LCN.SND_UNA >= 
  3729.    (LENGTH + LCN.SND_NXT) then
  3730.     --IT IS OFF THE QUEUE
  3731.     TYPE_FLAG := SEG_ACK;
  3732.    else -- SEND THE ACK ANYWAY
  3733.     -- PUT THE BUFFER BACK ON THE QUEUE.
  3734.     QUEUE_ADD_TO_FRONT(TRANSMIT_QUEUE, LCN, Q_ITEM);
  3735.     -- THIS PROCEDURE GETS A BUFFER AND DOES THE 
  3736.     -- OTHER NECESSARY THINGS TO SEND AN ACK ONLY.
  3737.     SET_UP_TO_SEND_AN_ACK;
  3738.    end if;
  3739.   else -- JUST SEND AN ACK
  3740.    -- THIS PROCEDURE GETS A BUFFER AND DOES THE OTHER 
  3741.    -- NECESSARY THINGS TO SEND AN ACK ONLY.
  3742.    SET_UP_TO_SEND_AN_ACK;
  3743.   end if;
  3744.    -- NOW WE SEND OUT AN ACK OR PIGGYBACKED ACK
  3745.    -- CLEAR OPTIONS ARRAY
  3746.    if ACK_BUFFER_EXISTS then -- DO IT
  3747.     OPTIONS := CLEAR;
  3748.     TCP_HEADER_FORMAT(LCN, TRANS_BUFFER, TYPE_FLAG, OPTIONS);
  3749.     -- HERE WE MUST SET UP THE SECURITY OPTIONS FOR IP
  3750.     OPTIONS := TCP_SECURITY_OPTIONS;
  3751.     -- PACK THE BUFFER
  3752.     PACK_BUFFER_INTO_BIT_STREAM(TRANS_BUFFER, PACKED_BUFFER);
  3753.     LEN := TRANS_BUFFER.DATA_OFFSET * 4 + LENGTH;
  3754.     SEND_IP( LCN.SOURCE_ADDRESS,
  3755.              LCN.DESTINATION_ADDRESS,
  3756.              TOS,
  3757.              TTL,
  3758.              PACKED_BUFFER,
  3759.              LEN,
  3760.              IDENT,
  3761.              DONT_FRAGMENT,
  3762.              OPTIONS,
  3763.              RESULT );
  3764.      -- UPDATE SND_NXT 
  3765.      -- WE DO NOT CHANGE THE SEQUENCE NUMBER IF WE ONLY SEND AN ACK
  3766.      if LENGTH > 0 then
  3767.       LCN.SND_NXT := LCN.SND_NXT + LENGTH;
  3768.       -- A PIGGYBACKED ACK WAS SENT
  3769.      end if;
  3770.      if TYPE_FLAG = SEG_ACK then
  3771.       -- PUT IT ON THE RETRANSMIT QUEUE
  3772.       Q_ITEM :=(PACKED_BUFFER, NULL_UNPACKED_BUFFER, LEN);
  3773.       QUEUE_ADD(TCP_RETRANSMIT_QUEUE, LCN, Q_ITEM);
  3774.      end if;
  3775.      -- SEE IF WE CAN SEND SOME MORE SEGMENTS FROM THE TRANSMIT Q.
  3776.      if NOT QUEUE_EMPTY then
  3777.       SEND_FROM_TRANSMIT_QUEUE(LCN);
  3778.      end if;
  3779.     end if;
  3780.    exception
  3781.     when others =>
  3782.      TEXT_IO.PUT_LINE("PROBLEM IN PIGGYBACKED ACK ROUTINE");
  3783.    end SEND_A_PIGGYBACKED_ACK;
  3784.     
  3785. procedure SEND_FROM_TRANSMIT_QUEUE(LCN : in out TCB_PTR) is
  3786. TRANS_BUFFER : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3787. CAN_SEND : BOOLEAN := TRUE;
  3788. PACKED_BUFF : PACKED_BUFFER_PTR;
  3789. DATA_LENGTH, INDEX : SIXTEEN_BITS ;
  3790. Q_ITEM : STD_Q_ITEM;
  3791. MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  3792.   
  3793. begin
  3794.  -- TRY TO GET THE INITIAL BUFFER OF DATA FOR TRANSMIT.
  3795.  -- DATA LENGTH WILL BE THE NUMBER OF DATA OCTETS IN THE BUFFER. 
  3796.  -- THEY WILL BE THE ONLY THINGS IN THE BUFFER.
  3797.  QUEUE_GET(TRANSMIT_QUEUE, LCN, Q_ITEM);
  3798.  PACKED_BUFF := Q_ITEM.BUFFER;
  3799.  DATA_LENGTH := Q_ITEM.LENGTH;
  3800.  while PACKED_BUFF /= null and CAN_SEND loop
  3801.   if LCN.SND_WND + LCN.SND_UNA >= 
  3802.    (LCN.SND_NXT + DATA_LENGTH) then 
  3803.    -- WE CAN SEND IT.
  3804.    -- CLEAR OPTIONS ARRAY. IF ANY OPTIONS WENT 
  3805.    -- HERE WE WOULD ADD TO THE HEADER LENGTH APPROPRIATELY.
  3806.    OPTIONS := CLEAR;
  3807.    -- PUT THE DATA IN THE BUFFER.
  3808.    -- CURRENTLY MAX OF ONE OCTET SO JUST PUT IT IN.
  3809.    INDEX := PACKED_BUFF.TCP_PTR;
  3810.    TRANS_BUFFER.DATA(1..DATA_LENGTH) := 
  3811.     PACKED_BUFF.BYTE(INDEX..INDEX + DATA_LENGTH - 1);
  3812.    TCP_HEADER_FORMAT(LCN, TRANS_BUFFER, SEGMENT, OPTIONS);
  3813.    -- HERE WE MUST SET UP THE SECURITY OPTIONS FOR IP
  3814.    OPTIONS := TCP_SECURITY_OPTIONS;
  3815.    -- PACK THE BUFFER
  3816.    PACK_BUFFER_INTO_BIT_STREAM(TRANS_BUFFER, PACKED_BUFF);
  3817.    LEN := TRANS_BUFFER.DATA_OFFSET * 4 + DATA_LENGTH; 
  3818.    -- TOTAL TCP LENGTH
  3819.    SEND_IP( LCN.SOURCE_ADDRESS,
  3820.             LCN.DESTINATION_ADDRESS,
  3821.             TOS,
  3822.             TTL,
  3823.             PACKED_BUFF,
  3824.             LEN,
  3825.             IDENT,
  3826.             DONT_FRAGMENT,
  3827.             OPTIONS,
  3828.             RESULT );
  3829. -- UPDATE SND_NXT 
  3830. LCN.SND_NXT := LCN.SND_NXT + 
  3831. TRANS_BUFFER.DATA_LEN;
  3832. -- PUT IT ON THE RETRANSMIT QUEUE
  3833. Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER,LEN);
  3834. QUEUE_ADD(TCP_RETRANSMIT_QUEUE, LCN, Q_ITEM);
  3835. -- GET ANOTHER BUNCH OF DATA TO BE SENT
  3836. QUEUE_GET(TRANSMIT_QUEUE, LCN, Q_ITEM);
  3837. PACKED_BUFF := Q_ITEM.BUFFER;
  3838. DATA_LENGTH := Q_ITEM.LENGTH;
  3839. else
  3840. CAN_SEND := FALSE;
  3841. -- PUT IT BACK ON THE QUEUE IN THE FIRST SPOT
  3842. QUEUE_ADD_TO_FRONT(TRANSMIT_QUEUE, LCN, Q_ITEM);
  3843. end if;
  3844. end loop;
  3845. if QUEUE_EMPTY(TRANSMIT_QUEUE, LCN) then
  3846. -- CHECK FOR CLOSE PENDING
  3847. if LCN.CLOSE_PENDING then
  3848. if LCN.STATE = T_TCP_GLOBALS_DATA_STRUCTURES.CLOSE_WAIT then
  3849. LCN.STATE := CLOSING;
  3850. else
  3851. LCN.STATE := T_TCP_GLOBALS_DATA_STRUCTURES.FIN_WAIT_1;
  3852. end if;
  3853. end if;
  3854. end if;
  3855. exception 
  3856. when constraint_error =>
  3857. TEXT_IO.PUT_LINE("A CONSTRAINT ERROR IN SEND ");
  3858. TEXT_IO.PUT_LINE("FROM TRANSMIT QUEUE");
  3859. when others =>
  3860.  TEXT_IO.PUT_LINE("AN UNKNOWN ERROR IN SEND FROM TRANSMIT QUEUE");
  3861. end SEND_FROM_TRANSMIT_QUEUE;
  3862. function UNPACK( PACKED_BUFFER : in PACKED_BUFFER_PTR; 
  3863.                  TOTAL_DATA_BYTES : in SIXTEEN_BITS ) return 
  3864.                       T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER is
  3865.          
  3866. type ARRAY_OF_BITS is array(1..6) of SIXTEEN_BITS ;
  3867. UNPACKED_BUFFER : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  3868. INDEX : SIXTEEN_BITS  := PACKED_BUFFER.TCP_PTR;
  3869. BIT_ARRAY : ARRAY_OF_BITS;
  3870. TCP_DATA_BYTES : SIXTEEN_BITS  := TOTAL_DATA_BYTES;
  3871.  function CONVERT_BYTE_TO_BITS( LENGTH : SIXTEEN_BITS ; BYTE : SYSTEM_BYTE)
  3872.                          return ARRAY_OF_BITS is
  3873.             
  3874.  --   THIS FUNCTION IS CALLED TO CONVERT A BYTE INTO ITS 
  3875.  -- COMPONENT 'LENGTH' BITS
  3876.  --
  3877.  --   AN ARRAY OF BITS. EACH ELEMENT OF THE ARRAY IS EITHER 0 OR 1. 
  3878.  --  IT IS 0 IF
  3879.  --   THE CORRESPONDING BIT IN BYTE IS NOT SET AND ONE OTHERWISE.
  3880.  --
  3881.  -- PROCESSING :
  3882.  --
  3883.  --   IF THE BYTE'S VALUE IS GREATER THAT 2**LENGTH-1 AND IF SO IT 
  3884.  --   KNOWS THAT THE BIT IS SET. IT THEN DECREMENTS LENGTH AND 
  3885.  --   SUBTRACTS 2**LENGTH-1 FROM BYTE IF THE BIT WAS SET. THIS PROCESS 
  3886.  --   IS CONTINUED UNTIL 0 IS REACHED.
  3887.  --
  3888.  -- RESTRICTIONS :
  3889.  --
  3890. TEMP : SIXTEEN_BITS  := SIXTEEN_BITS  ( BYTE ) ;
  3891. BIT_ARRAY : ARRAY_OF_BITS;
  3892. begin
  3893.  for I in reverse 0..LENGTH-1 loop
  3894.   if TEMP >=  2 ** I  then
  3895.    BIT_ARRAY( I + 1 ) := 1;
  3896.    TEMP := TEMP - 2 ** I ;
  3897.   else
  3898.    BIT_ARRAY( I + 1 ) := 0;
  3899.   end if;
  3900.  end loop;
  3901.  return BIT_ARRAY;
  3902. exception
  3903.  when others => 
  3904.   TEXT_IO.PUT_LINE("ERROR IN UNPACK CONVERT BYTES TO BITS");
  3905.   INTEGER_IO.PUT(INDEX);
  3906. end CONVERT_BYTE_TO_BITS;
  3907.          
  3908. function CONVERTED_LONG_INTEGER( INDEX : in SIXTEEN_BITS ) return 
  3909.                                                  THIRTYTWO_BITS is
  3910.                 
  3911.        --   THIS FUNCTION TAKES FOUR SYSTEM.BYTES FROM THE ARRAY POINTED TO BY
  3912.        --   PACKED_BUFFER AND MOVES THEM INTO A LONG_INTEGER WITH THE FUNCTION
  3913.        --   UNCHECKED_CONVERSION. IT FIRST MOVES THE SYSTEM BYTES INTO A 
  3914.        --   TEMPORARY ARRAY OF FOUR SYSTEM BYTES AND PUTS THESE IN A ONE 
  3915.        --   ELEMENT LONG_INTEGER ARRAY.
  3916. type HOLD_LONG_INTEGER is array(1..1) of THIRTYTWO_BITS ;
  3917. type FOUR_BYTES is array(1..4) of SYSTEM.BYTE;
  3918. function CONVERT_BYTES_TO_LONG_INTEGER is new 
  3919.          UNCHECKED_CONVERSION(FOUR_BYTES,HOLD_LONG_INTEGER);
  3920. HOLD_LONG_INT : HOLD_LONG_INTEGER;
  3921. FOUR_BYTE_HOLDER : FOUR_BYTES;
  3922. begin
  3923.  for I in 1..4 loop
  3924.   FOUR_BYTE_HOLDER(5 - I) := PACKED_BUFFER.BYTE( INDEX + SIXTEEN_BITS(I) - 1 ) ;
  3925.  end loop;
  3926.  HOLD_LONG_INT := 
  3927.  CONVERT_BYTES_TO_LONG_INTEGER(FOUR_BYTE_HOLDER);
  3928.  return HOLD_LONG_INT(1);
  3929. exception
  3930.  when others => 
  3931.   TEXT_IO.PUT_LINE("ERROR IN UNPACK CONVERTED LONG INTEGER");
  3932.   INTEGER_IO.PUT(INDEX);
  3933. end CONVERTED_LONG_INTEGER;
  3934. function CONVERTED_INTEGER( INDEX : in SIXTEEN_BITS ) return SIXTEEN_BITS  is
  3935.     --   THIS FUNCTION USES UNCHECKED_CONVERSION TO ALLOW AN ARRAY OF TWO 
  3936.     --   SYSTEM BYTES TO BE PLACED IN A ONE ELEMENT INTEGER ARRAY. THIS 
  3937.     --   ARRAY ELEMENT IS THEN RETURNED.
  3938.  
  3939.  type TWO_BYTES is array(1..2) of SYSTEM.BYTE;
  3940.  type HOLD_AN_INTEGER is array(1..1) of SIXTEEN_BITS ;
  3941.  function CONVERT_BYTES_TO_INTEGER is new 
  3942.           UNCHECKED_CONVERSION(TWO_BYTES,HOLD_AN_INTEGER);
  3943.  TWO_BYTE_HOLDER : TWO_BYTES;
  3944.  HOLD_INTEGER : HOLD_AN_INTEGER;
  3945.  
  3946.  begin
  3947.   TWO_BYTE_HOLDER(1) := PACKED_BUFFER.BYTE( INDEX + SIXTEEN_BITS(2) - 1 ) ;
  3948.   TWO_BYTE_HOLDER(2) := PACKED_BUFFER.BYTE( INDEX + SIXTEEN_BITS(1) - 1 ) ;
  3949.   HOLD_INTEGER := CONVERT_BYTES_TO_INTEGER(TWO_BYTE_HOLDER);
  3950.   return HOLD_INTEGER(1);
  3951.  exception
  3952.   when others => 
  3953.    TEXT_IO.PUT_LINE("ERROR IN UNPACK CONVERTED INTEGER");
  3954.    INTEGER_IO.PUT(INDEX);
  3955.   end CONVERTED_INTEGER;
  3956. begin -- MAIN
  3957.  -- PUT UNPACKED DATA IN THE BUFFER
  3958.  --NEW_LINE;
  3959.  --TEXT_IO.PUT_LINE("UNPACKING THE TCP_HEADER");
  3960.  UNPACKED_BUFFER.SOURCE_PORT := CONVERTED_INTEGER(INDEX);
  3961.  --TEXT_IO.PUT_LINE("SOURCE_PORT := ");
  3962.  --INTEGER_IO.PUT(UNPACKED_BUFFER.SOURCE_PORT);
  3963.  --NEW_LINE;
  3964.  INDEX := INDEX + 2;
  3965.  UNPACKED_BUFFER.DESTINATION_PORT := CONVERTED_INTEGER(INDEX);
  3966.  INDEX := INDEX + 2;
  3967.  UNPACKED_BUFFER.SEQ_NUM := MODULAR_CONVERT(CONVERTED_LONG_INTEGER(INDEX));
  3968.  INDEX := INDEX + 4;
  3969.  UNPACKED_BUFFER.ACK_NUM := MODULAR_CONVERT(CONVERTED_LONG_INTEGER(INDEX));
  3970.  INDEX := INDEX + 4;
  3971.  UNPACKED_BUFFER.DATA_OFFSET :=  SIXTEEN_BITS(PACKED_BUFFER.BYTE(INDEX))/ 
  3972.                                  (2**4) ;
  3973.                                                   -- THE HIGH 4 BITS
  3974.  INDEX := INDEX + 1;
  3975.  -- SET THE TCP FLAGS
  3976.  BIT_ARRAY := CONVERT_BYTE_TO_BITS(6, PACKED_BUFFER.BYTE(INDEX));
  3977.  UNPACKED_BUFFER.URG_FLAG := BIT_ARRAY(6);
  3978.  UNPACKED_BUFFER.ACK := BIT_ARRAY(5);
  3979.  UNPACKED_BUFFER.PUSH_FLAG := BIT_ARRAY(4);
  3980.  UNPACKED_BUFFER.RST := BIT_ARRAY(3);
  3981.  UNPACKED_BUFFER.SYN := BIT_ARRAY(2);
  3982.  UNPACKED_BUFFER.FIN := BIT_ARRAY(1);
  3983.  INDEX := INDEX + 1;
  3984.  UNPACKED_BUFFER.WINDOW := CONVERTED_INTEGER(INDEX);
  3985.  INDEX := INDEX + 2;
  3986.  UNPACKED_BUFFER.TCP_CSUM := CONVERTED_INTEGER(INDEX);
  3987.  INDEX := INDEX + 2;
  3988.  UNPACKED_BUFFER.URG_PTR := CONVERTED_INTEGER(INDEX);
  3989.  INDEX := INDEX +2;
  3990.  -- HERE WE WOULD CONVERT THE CURRENTLY UNIMPLEMENTED 
  3991.  -- OPTIONS.
  3992.  if UNPACKED_BUFFER.DATA_OFFSET > 5 then
  3993.   TEXT_IO.PUT_LINE("ERROR IN UNPACKING A BUFFER");
  3994.   TCP_ERROR(10);
  3995.  end if;
  3996.  -- UNPACK THE DATA
  3997.  TCP_DATA_BYTES := TCP_DATA_BYTES - UNPACKED_BUFFER.DATA_OFFSET * 4; -- WE
  3998.  UNPACKED_BUFFER.DATA_LEN := 
  3999.          TCP_DATA_BYTES;-- SET UP THE DATA LENGTH IN BUFFER
  4000.  -- ARE PASSED THE TOTAL BYTES(OCTETS) IN THE TCP. 
  4001.  -- WE ONLY WANT DATA.
  4002.  for I in 1..TCP_DATA_BYTES loop
  4003.   UNPACKED_BUFFER.DATA(I) := PACKED_BUFFER.BYTE(INDEX+I-1);
  4004.  end loop;
  4005.  return UNPACKED_BUFFER;
  4006. exception
  4007.  when others => 
  4008.   TEXT_IO.PUT_LINE("ERROR IN UNPACK MAIN");
  4009.   INTEGER_IO.PUT(INDEX);
  4010. end UNPACK;
  4011.     
  4012. procedure PROCESS_COMMON_ACK( LCN : in TCB_PTR; 
  4013.                               BUFPTR : in 
  4014.                  T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  4015.                               RESULT : out RES) is
  4016. LOC_CON_NAME : TCB_PTR := LCN;
  4017. NULL_ITEM : STD_Q_ITEM := (NULL,  NULL_UNPACKED_BUFFER, 0);
  4018. begin
  4019.  RESULT := GOOD;
  4020.  if BUFPTR.ACK_NUM > LCN.SND_NXT then
  4021.   -- IT ACKS SOMETHING NOT YET SENT
  4022.   SEND_A_PIGGYBACKED_ACK(LOC_CON_NAME);
  4023.   RESULT := BAD;
  4024.  else
  4025.   if BUFPTR.ACK_NUM <= LCN.SND_UNA then  
  4026.    -- IGNORE IT, SINCE IT IS A DUPLICATE.
  4027.    -- THE SEGMENT IS OK, HOWEVER. SO THE RESULT IS GOOD.
  4028.    RESULT := GOOD;
  4029.   else
  4030.    -- UPDATE THE SENT UNACKNOWLEDGED FIELD OF THE TCB.
  4031.    LCN.SND_UNA := BUFPTR.ACK_NUM;
  4032.    -- REMOVE ALL BUFFERS THAT ARE FULLY ACKNOWLEDGED 
  4033.    -- FROM THE RETRANS QUEUE.
  4034.    -- RETURN SEND BUFFERS TO USER WITH OK RESPONSE. 
  4035.    -- THESE ARE BOTH DONE BY RETRANSMIT QUEUE.
  4036.    DELETE_FROM_RETRANS_QUEUE(LCN, LCN.SND_UNA);
  4037.    if (LCN.SND_WL1 < BUFPTR.SEQ_NUM) 
  4038.     or ((LCN.SND_WL1 = 
  4039.     BUFPTR.SEQ_NUM) and
  4040.     (LCN.SND_WL2 <= BUFPTR.ACK_NUM))  then
  4041.     LCN.SND_WND := BUFPTR.WINDOW;
  4042.     LCN.SND_WL1 := BUFPTR.SEQ_NUM;
  4043.     LCN.SND_WL2 := BUFPTR.ACK_NUM;
  4044.    end if;
  4045.    -- SEE IF WE CAN SEND ANYTHING WITHIN THE SEND WINDOW 
  4046.    -- FROM THE TRANSMIT Q
  4047.    SEND_FROM_TRANSMIT_QUEUE(LOC_CON_NAME);
  4048.   end if;
  4049.  end if;
  4050. exception
  4051.  when constraint_error =>
  4052.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN PROCESS COMMON ACK");
  4053.  when others =>
  4054.   TEXT_IO.PUT_LINE("UNKNOWN ERROR IN PROCESS COMMON ACK");
  4055. end PROCESS_COMMON_ACK;
  4056. procedure ENTER_ESTABLISHED_STATE_PROCESSING( LCN : in TCB_PTR; 
  4057.                                               BUFPTR : in out
  4058.                    T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER) is
  4059. MORE_THAN_ONCE : BOOLEAN := FALSE;
  4060. NEW_LCN : TCB_PTR;
  4061. ITEM : STD_Q_ITEM := (NULL, NULL_UNPACKED_BUFFER, 0);
  4062. TEMP_BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  4063. begin
  4064.  LCN.CONNECTION_STATUS := CONNECTION_OPEN;
  4065.  NEW_LCN := LCN; 
  4066.  -- NECESSARY FOR A IN OUT PARAM. IN FIN CHECK CALL.
  4067.  TEMP_BUFPTR := BUFPTR;-- SAVE THE BUFFER.
  4068.  -- PROCESS THE REST OF FIRST BUFFER AND 
  4069.  -- THEN ALL PARTIALLY PROCESSED BUFFERS
  4070.  -- ON THE TCP_RETRANSMIT_QUEUE
  4071.  while not MORE_THAN_ONCE or (ITEM.LENGTH > 0 ) loop
  4072.   PROCESS_URGENT_FLAG(LCN, BUFPTR);
  4073.   PROCESS_SEGMENT_TEXT(LCN, BUFPTR);
  4074.   FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES(NEW_LCN, BUFPTR);
  4075.   -- CHECK THE RECEIVED SEGMENT QUEUE TO 
  4076.   -- DETERMINE IF THERE ARE ANY SEG
  4077.   -- THAT NEED CONTINUED PROCESSING ON IT.
  4078.   QUEUE_GET(TCP_RECEIVED_SEGMENT_QUEUE, LCN, ITEM);
  4079.   MORE_THAN_ONCE := TRUE;
  4080.   BUFPTR := ITEM.UNPACKED_BUFFER;
  4081.  end loop;
  4082.  BUFPTR := TEMP_BUFPTR; -- RESTORE THE BUFFER
  4083.  -- HERE WE WILL TRANSMIT ALL DATA WAITING 
  4084.  -- TO GO ON THE SEND QUEUE
  4085.  SEND_FROM_TRANSMIT_QUEUE(NEW_LCN);
  4086. exception
  4087.  when constraint_error =>
  4088.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN ENTER ESTABLISHED ");
  4089.   TEXT_IO.PUT_LINE("STATE PROCESSING");
  4090.  when others =>
  4091.   TEXT_IO.PUT_LINE("UNKNOWN ERROR IN ENTER ESTABLISHED ");
  4092.   TEXT_IO.PUT_LINE("STATE PROCESSING");
  4093. end ENTER_ESTABLISHED_STATE_PROCESSING;
  4094. end T_tcp_arrives_1 ;
  4095. --::::::::::::::
  4096. --reassem.txt
  4097. --::::::::::::::
  4098. -----------------------------------------------------------------------
  4099. --
  4100. --         DoD Protocols    NA-00008-200       80-01187-100(-)
  4101. --         E-Systems, Inc.  August 07, 1985
  4102. --
  4103. --         reassem.txt       Author : Jim Baldo
  4104. --
  4105. -----------------------------------------------------------------------
  4106. with SYSTEM;                use SYSTEM;
  4107. with BUFFER_DATA;            use BUFFER_DATA;
  4108. with IP_GLOBALS;            use IP_GLOBALS;
  4109.         package REASSEMBLY_UTILITIES is
  4110.     ----------------------------------------------------------
  4111.     --This implementation is for use with the DEC/Ada       --
  4112.     --compiler.                                             --
  4113.     ----------------------------------------------------------
  4114. ------------------------------------------------------------------------------
  4115. --This package contains the necessary functions and subprograms needed      --
  4116. --to support the reassembly mechnism of IP as specified by MIL-STD-1777.    --
  4117. ------------------------------------------------------------------------------
  4118. MAXIMUM_DATA_RECEIVED_IN_FRAGMENT : constant SIXTEEN_BITS  := 512;
  4119. MAXIMUM_DATAGRAM_SIZE : constant SIXTEEN_BITS  := 576;
  4120. type STATE_NAME_TYPE is ( INACTIVE, REASSEMBLING );
  4121. type DATA_AREA is array(1..MAXIMUM_DATA_RECEIVED_IN_FRAGMENT) of SYSTEM.BYTE;
  4122. type BIT_MAP is array(1..MAXIMUM_DATAGRAM_SIZE) of SIXTEEN_BITS ;
  4123. subtype PROTOCOL_TYPE is SIXTEEN_BITS ; 
  4124.      --should be a set of DoD accepted protocols
  4125. subtype IDENTIFICATION_TYPE is SIXTEEN_BITS ; --should have a range constraint
  4126. type BUFID_TYPE is
  4127.   record
  4128.     SOURCE : THIRTYTWO_BITS ;
  4129.     DESTINATION : THIRTYTWO_BITS ;
  4130.     PROTOCOL : PROTOCOL_TYPE;
  4131.     IDENTIFICATION : IDENTIFICATION_TYPE;
  4132.   end record;
  4133. type YES_OR_NO is (YES,NO);
  4134. MAXIMUM_REASSEMBLY_TIMEOUT : constant SIXTEEN_BITS := 225;
  4135. subtype TIMER_TYPE is SIXTEEN_BITS range 15..MAXIMUM_REASSEMBLY_TIMEOUT;
  4136. type REASSEMBLY_TABLE_TYPE;
  4137. type REASSEMBLY_TABLE_POINTER is access REASSEMBLY_TABLE_TYPE;
  4138. type REASSEMBLY_TABLE_TYPE is
  4139.   record
  4140.     PRIOR_ENTRY_REASSEMBLY_TABLE : REASSEMBLY_TABLE_POINTER;
  4141.     REASSEMBLY_DATAGRAM : BUFFER_DATA.PACKED_BUFFER_PTR;
  4142.     NEXT_ENTRY_REASSEMBLY_TABLE : REASSEMBLY_TABLE_POINTER;
  4143.       -- reassembly information
  4144.     BUFID : BUFID_TYPE;
  4145.     STATE_NAME : STATE_NAME_TYPE := INACTIVE;
  4146.     HAS_FRAGMENT_ZERO_ARRIVED : BOOLEAN := FALSE;
  4147.     REASSEMBLY_MAP : BIT_MAP;
  4148.     TIMER : TIMER_TYPE := 15;
  4149.     TOTAL_DATA_LENGTH :SIXTEEN_BITS  range 1..MAXIMUM_DATAGRAM_SIZE;
  4150.     DATA : DATA_AREA;
  4151.     HEADER : IP_GLOBALS.BUFFER_POINTER;
  4152.   end record;
  4153. type REASSEMBLY_ERROR_TYPE is
  4154.         (NO_MORE_FREE_BUFFER_SPACE,NO_ERROR,NO_MORE_REASSEMBLY_BUFFER_SPACE);
  4155. --******************
  4156. --* USER Semantics *
  4157. --******************
  4158. --This function will return a true value if the incoming datagram
  4159. --is part of a fragment.
  4160.   function A_FRAG
  4161.     ( PACKED_BUFFER : in BUFFER_DATA.PACKED_BUFFER_PTR;
  4162.       BUFPTR :  in IP_GLOBALS.BUFFER_POINTER )
  4163.         return YES_OR_NO;
  4164. --**************************
  4165. --* PACKAGE BODY Semantics *
  4166. --**************************
  4167. --The following algorithm is completly compatible with MIL-STD-1777
  4168. --section 9.4.6.2.1.
  4169. --
  4170. --  Data examine:
  4171. --    FROM_SNP.DTGM.FRAGMENT_OFFSET
  4172. --    FROM_SNP.DTGM.MORE_FRAG_FLAG
  4173. --
  4174. --    if ((FROM_SNP.DTGM.FRAGMENT_OFFSET = 0)
  4175. --      and (FROM_SNP.DTGM.MORE_FRAG_FLAG = 0))
  4176. --      then return false
  4177. --      else return true;
  4178. --    end if;
  4179. --******************
  4180. --* USER Semantics *
  4181. --******************
  4182. --This function will return a true value if the incoming datagram
  4183. --completes the fragment being reassembled.
  4184.   function REASS_DONE
  4185.     ( REASSEMBLY_BUFFER : in REASSEMBLY_TABLE_POINTER;
  4186.       BUFPTR : IP_GLOBALS.BUFFER_POINTER )
  4187.         return YES_OR_NO;
  4188. --**************************
  4189. --* PACKAGE BODY Semantics *
  4190. --**************************
  4191. --  The total data length of the original datagram, as computed
  4192. --  from "tail" fragment, must be known before completion is
  4193. --  possible.
  4194. --
  4195. --  Data examined:
  4196. --    STATE_VECTOR.REASSEMBLY_MAP
  4197. --    STATE_VECTOR.TOTAL_DATA_LENGTH
  4198. --    FROM_SNP.DTGM.TOTAL_LENGTH
  4199. --    FROM_SNP.DTGM.MORE_FRAG_FLAG
  4200. --    FROM_SNP.DTGM.HEADER_LENGTH
  4201. --
  4202. --  if ( STATE_VECTOR.TOTAL_DATA_LENGTH = 0 ) then
  4203. --    Check incoming datagram for "tail."
  4204. --    if ( FROM_SNP.DTGM.MORE_FRAG_FLAG = false ) then
  4205. --      Compute total data length and see if data in
  4206. --      this fragment fill out reasembly map.
  4207. --      if ( STATE_VECTOR.REASEMBLY_MAP from 0 to
  4208. --         (((FROM_SNP.DTGM.TOTAL_LENGTH -
  4209. --            (FROM_SNP.DTGM.HEADER_LENGTH*4) + 7 ) / 8 )
  4210. --          + 7 ) / 8  is set )
  4211. --      then return true;
  4212. --      end if;
  4213. --    else
  4214. --      Reassembly cannot be complete if total data length
  4215. --      unknown.
  4216. --      return false;
  4217. --    end if;
  4218. --  else
  4219. --    Total data length is already known.  See if data in this
  4220. --    fragment fill out reassembly map.
  4221. --    if ( all reassembly map from 0 to                                 
  4222. --      (STATE_VECTOR.TOTAL_DATA_LENGTH + 7 ) / 8 is set )
  4223. --    then
  4224. --      return YES;
  4225. --    else
  4226. --      return NO;
  4227. --  end if;
  4228. --******************
  4229. --* USER Semantics *
  4230. --******************
  4231. --This subprogram will generate an error datgram to the source IP informing
  4232. --it of the datagram's expiration during reassembly.
  4233.   procedure REASSEMBLY_TIMEOUT
  4234.     ( REASSEMBLY_DATAGRAM_THAT_TIMED_OUT : in out REASSEMBLY_TABLE_POINTER;
  4235.       BUFPTR : in IP_GLOBALS.BUFFER_POINTER );
  4236. --**************************
  4237. --* PACKAGE BODY Semantics *
  4238. --**************************
  4239. --
  4240. --  Data examined:
  4241. --    STATE_VECTOR.HEADER
  4242. --    STATE_VECTOR.DATA
  4243. --
  4244. --  Data modified:
  4245. --    TO_SNP.DTGM    TO_SNP.TYPE_OF_SERVICE_INDICATORS
  4246. --    TO_SNP.LENGTH    TO_SNP.HEADER_LENGTH
  4247. --
  4248. --  Format and transmit an error datagram to the source IP.
  4249. --
  4250. --  TO_SNP.DTGM.VERSION := 4; -- standard IP version
  4251. --  TO_SNP.DTGM.HEADER_LENGTH := 5; -- standard header size
  4252. --  TO_SNP.DTGM.TYPE_OF_SERVICE := 0; -- routine service quality
  4253. --  TO_SNP.DTGM.IDENTIFICATION := new value selected
  4254. --  TO_SNP.DTGM.MORE_FRAG_FLAG := false;
  4255. --  TO_SNP.DTGM.DONT_FRAG_FLAG := false;
  4256. --  TO_SNP.DTGM.FRAGMENT_OFFSET := 0;
  4257. --  TO_SNP.DTGM.TIME_TO_LIVE := 60;
  4258. --  TO_SNP.DTGM.PROTOCOL := this number will be assigned
  4259. --        by the DoD Executive Agent for
  4260. --        Protocols;
  4261. --  TO_SNP.DTGM.SOURCE_ADDR := STATE_VECTOR.HEADER.DESTINATION_ADDR;
  4262. --  TO_SNP.DTGM.DESTINATION_ADDR := STATE_VECTOR.HEADER.SOURCE_ADDR;
  4263. --  If the fragment received is the first fragment, then the data section
  4264. --  caries the ICMP error message, the header of the timed-out datagram,
  4265. --  and its first 64 bytes of data.  If fragment zero is not available
  4266. --  then no time exceeded need be sent at all.
  4267. --
  4268. --  TO_SNP.DTGM.DATA[0] := 12; -- ICMP type = Time Exceeded
  4269. --  TO_SNP.DTGM.DATA[1] := 1; -- Code = fragment reassembly timeout
  4270. --
  4271. --  Copy in the timed-out datagram's header plus the first
  4272. --  64 bytes of its data section (asumed to be of length "N" ).
  4273. --
  4274. --  TO_SNP.DTGM.DATA[8..N+3] := STATE_VECTOR[0..N-1];
  4275. --  TO_SNP.DTGM.TOTAL_LENGTH := TO_SNP.HEADER_LENGTH * 4 + N + 8;
  4276. --  COMPUTE_ICMP_CHECKSUM;
  4277. --
  4278. --  Compute datagram's header checksum, determine the route for the 
  4279. --  datagram, the type of service indicators, and the datagram size 
  4280. --  for the SNP.
  4281. --
  4282. --  COMPUTE_CHECKSUM;
  4283. --  TO_SNP.TYPE_OF_SERVICE_INDICATORS := 0;
  4284. --  TO_SNP.LENGTH := TO_SNP.DTGM.TOTAL_LENGTH;
  4285. --  ROUTE;
  4286. --
  4287. --  Request the execution environment to pass the contents of
  4288. --  TO_SNP to the local subnet protocol for transmision.
  4289. --
  4290. --  TRANSFER TO_SNP to the SNP.
  4291. --******************
  4292. --* USER Semantics *
  4293. --******************
  4294. --This subprogram will add a fragment to a reassembling datagram.
  4295.   procedure REASSEMBLY
  4296.     ( PACKED_BUFFER : in out BUFFER_DATA.PACKED_BUFFER_PTR;
  4297.       REASSEMBLY_TABLE_ELEMENT : in out REASSEMBLY_TABLE_POINTER;
  4298.       BUFPTR : IP_GLOBALS.BUFFER_POINTER );
  4299. --**************************
  4300. --* PACKAGE BODY Semantics *
  4301. --**************************
  4302. --The following algorithm is completly compatible with MIL-STD-1777
  4303. --section 9.4.6.2.2.
  4304. --
  4305. --  Data examined:
  4306. --    FROM_SNP.DTGM
  4307. --
  4308. --  Data modified:
  4309. --    STATE_VECTOR.REASSEMBLY_MAP
  4310. --    STATE_VECTOR.TIMER
  4311. --    STATE_VECTOR.TOTAL_DATA_LENGTH
  4312. --    STATE_VECTOR.HEADER
  4313. --    STATE_VECTOR.DATA
  4314. --
  4315. --  Local variables:
  4316. --    j -- loop counter
  4317. --    DATA_IN_FRAG -- the number of octets of data in received
  4318. --           -- fragment
  4319. --
  4320. --  DATA_IN_FRAG := ( FROM_SNP.DTGM.TOTAL_LENGTH - FROM_SNP.
  4321. --      DTGM.HEADER_LENGTH*4 );
  4322. --
  4323. --  Put data in its relative position in the data area of the state 
  4324. --  vector.
  4325. --  
  4326. --  STATE_VECTOR.DATA[FROM_SNP.DTGM.FRAGMENT_OFFSET*8..
  4327. --    FROM_SNP.DTGM.FRAGMENT_OFFSET*8+DATA_IN_FRAG] :=
  4328. --      FROM SNP.DTGM.DATA[0..DATA_IN_FRAG-1];
  4329. --
  4330. --  Fill in the corresponding entries of the reassembly map
  4331. --  frpresenting each 8-octet unit of received data.
  4332. --
  4333. --  for j in ( FOR_SNP.DTGM.FRAGMENT_OFFSET ) ..
  4334. --     (( FROM_SNP.DTGM.FRAGMENT_OFFSET + DATA_IN_FRAG +
  4335. --     7)/8 ) loop
  4336. --    STATE_VECTOR.REASSEMBLY_MAP[J] := 1;
  4337. --  end if;
  4338. --
  4339. --  Compute the total datagram length from the "tail-end"
  4340. --  fragment.
  4341. --
  4342. --  if ( FROM_SNP.DTGM.MORE_FRAG_FLAG = false )
  4343. --  then STATE_VECTOR.TOTAL_DATA_LENGTH :=
  4344. --    FROM_SNP.DTGM.FRAGMENT_OFFSET*8 +
  4345. --    DATA_IN_FRAG;
  4346. --  end if;
  4347. --
  4348. --  Record the header of the "head-end" fragment.
  4349. --
  4350. --  if ( FROM_SNP.DTGM.FRAGMENT_OFFSET = 0 )
  4351. --    then STATE_VECTOR.HEADER := FROM_SNP.DTGM;
  4352. --  end if;
  4353. --
  4354. --  Reset the reassembly timer if its current value is less
  4355. --  than the time-to-live field of the received datagram.
  4356. --
  4357. --  if ( STATE_VECTOR.TIMER < FROM_SNP.DTGM.TIME_TO_LIVE )
  4358. --    then STATE_VECTOR.TIMER := MAXIMUM
  4359. --      (FROM_SNP.DTGM.TIME_TO_LIVE, STATE_VECTOR.TIMER );
  4360. --
  4361. --  Mandatory Requirements
  4362. --    a.) IP module must have the capacity to receive a
  4363. --        datagram of 576 octets in length(either in one piece
  4364. --        or in fragments).
  4365. --    b.) if (FROM_SNP.DTGM.FRAGMENT_OFFSET = 0 ) then
  4366. --           fragment header becomes the header of the
  4367. --           reassembling datagram
  4368. --    c.) The total length of the reassembling datagram is calculated
  4369. --        from the fragment with FROM_SNP.DTGM.MORE_FRAG_FLAG 
  4370. --        equal to zero(i.e., the "tail-end" fragment ).
  4371. --    d.) A reassembly timer is associated with each datagram 
  4372. --        being reassembled.  The current recommendation for the
  4373. --        initial timer setting is 15 seconds.  Note that the choice
  4374. --        of this parameter value is related to the buffer capacity
  4375. --        available and the data rate of the transmission medium.
  4376. --    e.) As each fragment arrives, the reassembly timer is reset
  4377. --        to:  STATE_VECTOR.TIMER := MAXIMUM
  4378. --      (FROM_SNP.DTGM.TIME_TO_LIVE, STATE_VECTOR.TIMER );
  4379. --
  4380. --    f.) The first fragment of the datagram being reassembled must
  4381. --        contain all options, except padding and no-op octets.
  4382. --    g.) The SOURCE_ADDR, DESTINATION_ADDR, PROTOCOL, and IDENTIFIER
  4383. --        of the first fragment received must be recorded.  All 
  4384. --        subsequent fragments' SOURCE_ADDR, DESTINATION_ADDR, 
  4385. --        PROTOCOL, and IDENTIFIER will be compared against those
  4386. --        recorded.
  4387. --    h.) As each fragment arrives, the security and precedence
  4388. --        fields, if available, must be checked.  If the security
  4389. --        level of the fragment does not match the security level
  4390. --        of datagram or if the precedence level of the fragment
  4391. --        does not match the precedence level of the datagram, the
  4392. --        datagram being assembled is discarded.  Also, an error
  4393. --        datagram is returned to the source IP to report the 
  4394. --        "mismatched security/precedence" error.
  4395. --    i.) If the reassembly timer expires, the datagram being
  4396. --        reassembled is discarded.  Also, an error datagram is 
  4397. --        returned to the source IP to report the "time exceeded
  4398. --        during reassembly" error.
  4399. --******************
  4400. --* USER Semantics *
  4401. --******************
  4402. --This subprogram transforms a datagram that has been reassembled in the 
  4403. --state vector into interface parameters and data, then delivers them to a
  4404. --ULP.
  4405.   procedure REASSEMBLED_DELIVERY
  4406.     ( PACKED_BUFFER : in BUFFER_DATA.PACKED_BUFFER_PTR );
  4407. --**************************
  4408. --* PACKAGE BODY Semantics *
  4409. --**************************
  4410. --  Data examined:
  4411. --
  4412. --    STATE_VECTOR.HEADER.DESTINATION_ADDR
  4413. --    STATE_VECTOR.HEADER.SOURCE_ADDR
  4414. --    STATE_VECTOR.HEADER.PROTOCOL
  4415. --    STATE_VECTOR.HEADER.TYPE_OF_SERVICE
  4416. --    STATE_VECTOR.HEADER.HEADER_LENGTH
  4417. --    STATE_VECTOR.HEADER.TOTAL_LENGTH
  4418. --    STATE_VECTOR.HEADER.OPTIONS
  4419. --    STATE_VECTOR.DATA
  4420. --
  4421. --  Data modified:
  4422. --
  4423. --    TO_ULP.DESTINATION_ADDR    TO_ULP.LENGTH
  4424. --    TO_ULP.SOURCE_ADDR    TO_ULP.DATA
  4425. --    TO_ULP.PROTOCOL      TO_ULP.OPTIONS
  4426. --    TO_ULP.TYPE_OF_SERVICE
  4427. --
  4428. --  TO_ULP.DESTINATION_ADDR := STATE_VECTOR.HEADER.DESTINATION_ADDR;
  4429. --  TO_ULP.SOURCE_ADDR := STATE_VECTOR.HEADER.SOURCE_ADDR;
  4430. --  TO_ULP.PROTOCOL := STATE_VECTOR.HEADER.PROTOCOL;
  4431. --  TO_ULP.TYPE_OF_SERVICE := STATE_VECTOR.HEADER.TYPE_OF_SERVICE;
  4432. --  TO_ULP.LENGTH := STATE_VECTOR.HEADER.TOTAL_LENGTH -
  4433. --           STATE_VECTOR.HEADER.HEADER_LENGTH * 4;
  4434. --  TO_ULP.OPTIONS := STATE_VECTOR.HEADER.OPTIONS;
  4435. --  TO_ULP.DATA := STATE_VECTOR.DATA;
  4436. --******************
  4437. --* USER Semantics *
  4438. --******************
  4439. --This subprogram decomposes a datagram arriving from a remote IP into 
  4440. --interface parameters and data and delivers them to the destination ULP.
  4441.   procedure REMOTE_DELIVERY
  4442.     ( PACKED_BUFFER : in BUFFER_DATA.PACKED_BUFFER_PTR );
  4443. --**************************
  4444. --* PACKAGE BODY Semantics *
  4445. --**************************
  4446. --
  4447. --  Data examined:
  4448. --    FROM_SNP.DTGM.SOURCE_ADDR
  4449. --    FROM_SNP.DTGM.DESTINATION_ADDR
  4450. --    FROM_SNP.DTGM.PROTOCOL
  4451. --    FROM_SNP.DTGM.TYPE_OF_SERVICE
  4452. --    FROM_SNP.DTGM.TOTAL_LENGTH
  4453. --    FROM_SNP.DTGM.HEADER_LENGTH
  4454. --    FROM_SNP.DTGM.DATA
  4455. --    FROM_SNP.DTGM.OPTIONS
  4456. --
  4457. --  Data modified:
  4458. --    TO_ULP.DESTINATION_ADDR    TO_ULP.LENGTH
  4459. --    TO_ULP.SOURCE_ADDR    TO_ULP.DATA
  4460. --    TO_ULP.PROTOCOL      TO_ULP.OPTIONS
  4461. --    TO_ULP.TYPE_OF_SERVICE
  4462. --
  4463. --  TO_ULP.DESTINATION_ADDR := FROM_SNP.DTGM.DESTINATION_ADDR;
  4464. --  TO_ULP.SOURCE_ADDR := FROM_SNP.DTGM.SOURCE_ADDR;
  4465. --  TO_ULP.PROTOCOL := FROM_SNP.DTGM.PROTOCOL;
  4466. --  TO_ULP.TYPE_OF_SERVICE := FROM_SNP.DTGM.TYPE_OF_SERVICE;
  4467. --  TO_ULP.LENGTH := FROM_SNP.DTGM.TOTAL_LENGTH - 
  4468. --        FROM_SNP.DTGM.HEADER_LENGTH * 4;
  4469. --  TO_ULP.DATA := FROM_SNP.DTGM.DATA;
  4470. --  TO_ULP.OPTIONS := FROM_SNP.DTGM.OPTIONS;  
  4471. --**************************
  4472. --* PACKAGE BODY SEMANTICS *
  4473. --**************************
  4474. --This procedure is invoked upon system intialization or recovery
  4475. --to initialize the reassembly queue
  4476.   procedure INITIALIZE_REASSEMBLY_QUEUE;
  4477. end REASSEMBLY_UTILITIES;
  4478. with IP_UNPACK_AND_PACK_UTILITIES;
  4479. with UNCHECKED_CONVERSION;
  4480. with TEXT_IO;    use TEXT_IO, INTEGER_IO ;
  4481. with IP_GLOBALS;
  4482. with UTILITIES_FOR_ICMP;
  4483.         package body REASSEMBLY_UTILITIES is
  4484.     ---------------------------------------------------------
  4485.     --This implementation is for the DEC/Ada compiler      --
  4486.     ---------------------------------------------------------
  4487. FREE_LIST_REASSEMBLY_ELEMENTS : REASSEMBLY_TABLE_POINTER;
  4488. TOP_OF_REASSEMBLY_TABLE_POINTER : REASSEMBLY_TABLE_POINTER;
  4489. COUNTER_REASSEMBLY_ENTRIES : SIXTEEN_BITS  range 0..20;
  4490. TOP_OF_REASSEMBLY_FREE_LIST : REASSEMBLY_TABLE_POINTER;
  4491. REASSEMBLY_FREE_LIST_ELEMENT_COUNT : SIXTEEN_BITS  range 0..20;
  4492. MAXIMUM_TABLE_SIZE : constant SIXTEEN_BITS  := 20;
  4493.   procedure INITIALIZE_REASSEMBLY_QUEUE is
  4494.     --This procedure is invoked upon system intialization or recovery
  4495.     --to initialize the reassembly queue
  4496.   NEW_ELEMENT : REASSEMBLY_TABLE_POINTER;
  4497.   LIST_GENERATOR : REASSEMBLY_TABLE_POINTER;
  4498.   begin
  4499.     REASSEMBLY_FREE_LIST_ELEMENT_COUNT := 20;
  4500.     COUNTER_REASSEMBLY_ENTRIES := 0;
  4501.     TOP_OF_REASSEMBLY_TABLE_POINTER := null;
  4502.     TOP_OF_REASSEMBLY_FREE_LIST := new REASSEMBLY_TABLE_TYPE;
  4503.     TOP_OF_REASSEMBLY_FREE_LIST .PRIOR_ENTRY_REASSEMBLY_TABLE := null;
  4504.     TOP_OF_REASSEMBLY_FREE_LIST .NEXT_ENTRY_REASSEMBLY_TABLE := null;
  4505.     -- To be used durning FREE_LIST construction
  4506.     LIST_GENERATOR := TOP_OF_REASSEMBLY_FREE_LIST;
  4507.     -- Set up free queue list
  4508.     for I in 2..MAXIMUM_TABLE_SIZE loop
  4509.       NEW_ELEMENT := new REASSEMBLY_TABLE_TYPE;
  4510.       LIST_GENERATOR.NEXT_ENTRY_REASSEMBLY_TABLE := NEW_ELEMENT;
  4511.       NEW_ELEMENT.PRIOR_ENTRY_REASSEMBLY_TABLE := 
  4512.         LIST_GENERATOR;
  4513.       NEW_ELEMENT.NEXT_ENTRY_REASSEMBLY_TABLE := null;
  4514.       LIST_GENERATOR := NEW_ELEMENT;
  4515.     end loop;
  4516.     exception
  4517.       when CONSTRAINT_ERROR =>
  4518.         TEXT_IO.PUT_LINE("CONSTRAINT ERROR in package REASSEMBLY_UTILITIES ");
  4519.         TEXT_IO.PUT_LINE("procedure INITIALIZE_REASSEMBLY_QUEUE ");
  4520.       when others =>
  4521.         TEXT_IO.PUT_LINE("ERROR in package REASSEMBLY_UTILITIES ");
  4522.         TEXT_IO.PUT_LINE("procedure INITIALIZE_REASSEMBLY_QUEUE ");
  4523.   end INITIALIZE_REASSEMBLY_QUEUE;
  4524.   function OBTAIN_TOP_OF_REASSEMBLY_TABLE return 
  4525.     REASSEMBLY_TABLE_POINTER is
  4526.   begin
  4527.     return TOP_OF_REASSEMBLY_TABLE_POINTER;
  4528.   exception
  4529.     when CONSTRAINT_ERROR =>
  4530.     TEXT_IO.PUT_LINE("CONSTRAINT ERROR in package REASSEMBLY_UTILITIES ");
  4531.     TEXT_IO.PUT_LINE("procedure OBTAIN_TOP_OF_REASSEMBLY_TABLE ");
  4532.     when others =>
  4533.       TEXT_IO.PUT_LINE("ERROR in package REASSEMBLY_UTILITIES ");
  4534.       TEXT_IO.PUT_LINE("procedure OBTAIN_TOP_OF_REASSEMBLY_TABLE ");
  4535.   end OBTAIN_TOP_OF_REASSEMBLY_TABLE;
  4536.   procedure ADD_ENTRY_TO_REASSEMBLY_TABLE(NEW_DATAGRAM_FRAGMENT :  
  4537.   REASSEMBLY_TABLE_POINTER;
  4538.     ERROR : out REASSEMBLY_ERROR_TYPE) is
  4539.   begin
  4540.     if COUNTER_REASSEMBLY_ENTRIES < 20 then
  4541.       ERROR := NO_ERROR;
  4542.       COUNTER_REASSEMBLY_ENTRIES := COUNTER_REASSEMBLY_ENTRIES + 1;
  4543.       NEW_DATAGRAM_FRAGMENT.PRIOR_ENTRY_REASSEMBLY_TABLE := null;
  4544.       NEW_DATAGRAM_FRAGMENT.NEXT_ENTRY_REASSEMBLY_TABLE := 
  4545.       TOP_OF_REASSEMBLY_TABLE_POINTER;
  4546.       TOP_OF_REASSEMBLY_TABLE_POINTER := NEW_DATAGRAM_FRAGMENT;
  4547.     else
  4548.       -- reassembly resources full
  4549.       -- send ICMP message
  4550.       ERROR := NO_MORE_REASSEMBLY_BUFFER_SPACE;
  4551.     end if;
  4552.   exception
  4553.     when CONSTRAINT_ERROR =>
  4554.     TEXT_IO.PUT_LINE("CONSTRAINT ERROR in package REASSEMBLY_UTILITIES ");
  4555.     TEXT_IO.PUT_LINE("procedure ADD_ENTRY_TO_REASSEMBLY_TABLE ");
  4556.     when others =>
  4557.       TEXT_IO.PUT_LINE("ERROR in package REASSEMBLY_UTILITIES ");
  4558.       TEXT_IO.PUT_LINE("procedure ADD_ENTRY_TO_REASSEMBLY_TABLE ");
  4559.   end ADD_ENTRY_TO_REASSEMBLY_TABLE;
  4560.   procedure DELETE_ENTRY_FROM_REASSEMBLY_TABLE(DATAGRAM : 
  4561.   in out REASSEMBLY_TABLE_POINTER) is
  4562.     procedure ADD_REASSEMBLY_ELEMENT_TO_FREE_LIST is
  4563.     begin
  4564.       REASSEMBLY_FREE_LIST_ELEMENT_COUNT := REASSEMBLY_FREE_LIST_ELEMENT_COUNT +
  4565.  1;
  4566.       TOP_OF_REASSEMBLY_FREE_LIST.PRIOR_ENTRY_REASSEMBLY_TABLE :=
  4567.         DATAGRAM;
  4568.       DATAGRAM.NEXT_ENTRY_REASSEMBLY_TABLE :=
  4569.         TOP_OF_REASSEMBLY_FREE_LIST;
  4570.       TOP_OF_REASSEMBLY_FREE_LIST := DATAGRAM;
  4571.       TOP_OF_REASSEMBLY_FREE_LIST.PRIOR_ENTRY_REASSEMBLY_TABLE :=
  4572.         null;
  4573.     exception
  4574.       when CONSTRAINT_ERROR =>
  4575.     TEXT_IO.PUT_LINE("CONSTRAINT ERROR in package REASSEMBLY_UTILITIES ");
  4576.     TEXT_IO.PUT_LINE("procedure ADD_REASSEMBLY_ELEMENT_TO_FREE_LIST ");
  4577.       when others =>
  4578.       TEXT_IO.PUT_LINE("ERROR in package REASSEMBLY_UTILITIES ");
  4579.       TEXT_IO.PUT_LINE("procedure ADD_REASSEMBLY_ELEMENT_TO_FREE_LIST ");
  4580.     end ADD_REASSEMBLY_ELEMENT_TO_FREE_LIST;
  4581.   begin
  4582.     COUNTER_REASSEMBLY_ENTRIES := COUNTER_REASSEMBLY_ENTRIES - 1;
  4583.     DATAGRAM.PRIOR_ENTRY_REASSEMBLY_TABLE.NEXT_ENTRY_REASSEMBLY_TABLE :=
  4584.       DATAGRAM.NEXT_ENTRY_REASSEMBLY_TABLE;
  4585.     ADD_REASSEMBLY_ELEMENT_TO_FREE_LIST;
  4586.   exception
  4587.     when CONSTRAINT_ERROR =>
  4588.     TEXT_IO.PUT_LINE("CONSTRAINT ERROR in package REASSEMBLY_UTILITIES ");
  4589.     TEXT_IO.PUT_LINE("procedure DELETE_ENTRY_FROM_REASSEMBLY_TABLE ");
  4590.     when others =>
  4591.       TEXT_IO.PUT_LINE("ERROR in package REASSEMBLY_UTILITIES ");
  4592.       TEXT_IO.PUT_LINE("procedure DELETE_ENTRY_FROM_REASSEMBLY_TABLE ");
  4593.   end DELETE_ENTRY_FROM_REASSEMBLY_TABLE;
  4594.   procedure GET_REASSEMBLY_STRUCTURE( REASSEMBLY_STRUCTURE : 
  4595.                                       in out REASSEMBLY_TABLE_POINTER;
  4596.                                       ERROR : out REASSEMBLY_ERROR_TYPE) is
  4597.     procedure DELETE_REASSEMBLY_STRUCTURE_FROM_FREE_LIST is
  4598.     
  4599.     begin
  4600.       if REASSEMBLY_FREE_LIST_ELEMENT_COUNT > 0 then
  4601.         ERROR := NO_ERROR;
  4602.         REASSEMBLY_FREE_LIST_ELEMENT_COUNT := REASSEMBLY_FREE_LIST_ELEMENT_COUNT
  4603.  -1;
  4604.         TOP_OF_REASSEMBLY_FREE_LIST :=  
  4605.           TOP_OF_REASSEMBLY_FREE_LIST.NEXT_ENTRY_REASSEMBLY_TABLE;
  4606.         TOP_OF_REASSEMBLY_FREE_LIST.PRIOR_ENTRY_REASSEMBLY_TABLE := null;
  4607.       else
  4608.         -- no more buffer space to perform reassembly
  4609.         -- send ICMP message
  4610.         ERROR := NO_MORE_FREE_BUFFER_SPACE;
  4611.       end if;
  4612.     exception
  4613.       when CONSTRAINT_ERROR =>
  4614.     TEXT_IO.PUT_LINE("CONSTRAINT ERROR in package REASSEMBLY_UTILITIES ");
  4615.     TEXT_IO.PUT_LINE("procedure DELETE_REASSEMBLY_STRUCTURE_FROM_FREE_LIST ");
  4616.       when others =>
  4617.       TEXT_IO.PUT_LINE("ERROR in package REASSEMBLY_UTILITIES ");
  4618.       TEXT_IO.PUT_LINE("procedure DELETE_REASSEMBLY_STRUCTURE_FROM_FREE_LIST ");
  4619.     end DELETE_REASSEMBLY_STRUCTURE_FROM_FREE_LIST;
  4620.   
  4621.   begin
  4622.     REASSEMBLY_STRUCTURE := TOP_OF_REASSEMBLY_FREE_LIST;
  4623.     DELETE_REASSEMBLY_STRUCTURE_FROM_FREE_LIST;
  4624.     REASSEMBLY_STRUCTURE.PRIOR_ENTRY_REASSEMBLY_TABLE := null;
  4625.     REASSEMBLY_STRUCTURE.NEXT_ENTRY_REASSEMBLY_TABLE := null;
  4626.   exception
  4627.     when CONSTRAINT_ERROR =>
  4628.     TEXT_IO.PUT_LINE("CONSTRAINT ERROR in package REASSEMBLY_UTILITIES ");
  4629.     TEXT_IO.PUT_LINE("procedure GET_REASSEMBLY_STRUCTURE ");
  4630.     when others =>
  4631.       TEXT_IO.PUT_LINE("ERROR in package REASSEMBLY_UTILITIES ");
  4632.       TEXT_IO.PUT_LINE("procedure GET_REASSEMBLY_STRUCTURE ");
  4633.   end GET_REASSEMBLY_STRUCTURE;
  4634.   function A_FRAG( PACKED_BUFFER : in BUFFER_DATA.PACKED_BUFFER_PTR;
  4635.                    BUFPTR : in IP_GLOBALS.BUFFER_POINTER )
  4636.                                              return YES_OR_NO is
  4637.   begin
  4638.     if (BUFPTR.FRAG_OFFSET = 0) and (BUFPTR.FLAGS = 2) then
  4639.       return NO;
  4640.     elsif (BUFPTR.FLAGS = 1) or (BUFPTR.FLAGS = 0) then
  4641.       return YES;
  4642.     else
  4643.       NEW_LINE;
  4644.       TEXT_IO.PUT("Flag error := ");
  4645.       INTEGER_IO.PUT(BUFPTR.FLAGS);
  4646.       NEW_LINE;
  4647.       TEXT_IO.PUT_LINE("function A_FRAG package REASSEMBLY_UTILITIES ");
  4648.       return NO;
  4649.     end if;
  4650.   end A_FRAG;
  4651.   function REASS_DONE
  4652.     ( REASSEMBLY_BUFFER : in REASSEMBLY_TABLE_POINTER;
  4653.       BUFPTR : IP_GLOBALS.BUFFER_POINTER )
  4654.         return YES_OR_NO is
  4655.   begin
  4656.     if REASSEMBLY_BUFFER.TOTAL_DATA_LENGTH = 0 then
  4657.       -- check incoming datagram for "tail"
  4658.       if BUFPTR.FLAGS = 0 then
  4659.         REASSEMBLY_BUFFER.TOTAL_DATA_LENGTH := BUFPTR.FRAG_OFFSET + 
  4660.         (BUFPTR.TOT_LEN - BUFPTR.IHL);
  4661.         for I in BUFPTR.FRAG_OFFSET..(BUFPTR.FRAG_OFFSET + 
  4662.         (BUFPTR.TOT_LEN - BUFPTR.IHL)) loop
  4663.           REASSEMBLY_BUFFER.REASSEMBLY_MAP(I) := 1;
  4664.         end loop;
  4665.         for I in 1..REASSEMBLY_BUFFER.TOTAL_DATA_LENGTH loop
  4666.           if REASSEMBLY_BUFFER.REASSEMBLY_MAP(I) = 1 then
  4667.             null;
  4668.           else
  4669.             return NO;
  4670.           end if;
  4671.         end loop;
  4672.         return YES;
  4673.       else
  4674.         return NO;
  4675.       end if;
  4676.     else
  4677.       for I in 1..REASSEMBLY_BUFFER.TOTAL_DATA_LENGTH loop
  4678.         if REASSEMBLY_BUFFER.REASSEMBLY_MAP(I) = 1 then
  4679.           null;
  4680.         else
  4681.           return NO;
  4682.         end if;
  4683.       end loop;
  4684.       return YES;
  4685.     end if;
  4686.   exception
  4687.     when CONSTRAINT_ERROR =>
  4688.       TEXT_IO.PUT_LINE(" CONSTRAINT_ERROR in package REASSEMBLY_UTILITIES ");
  4689.       TEXT_IO.PUT_LINE("procedure REASS_DONE ");
  4690.     when others =>
  4691.       TEXT_IO.PUT_LINE(" UNKNOWN ERROR in package  REASSEMBLY_UTILITIES ");
  4692.       TEXT_IO.PUT_LINE("procedure REASS_DONE ");
  4693.   end REASS_DONE;
  4694.   procedure REASSEMBLY_TIMEOUT
  4695.     ( REASSEMBLY_DATAGRAM_THAT_TIMED_OUT : in out REASSEMBLY_TABLE_POINTER;
  4696.       BUFPTR : in IP_GLOBALS.BUFFER_POINTER ) is
  4697.   type TELEGOOFUP is array(1..1) of SIXTEEN_BITS ;
  4698.           -- Currently necessary for
  4699.           -- implementation restriction
  4700.   type TWO_BYTE is array(1..2) of SYSTEM.BYTE;
  4701.   function CONVERT_TO_TWO_BYTES is new
  4702.   UNCHECKED_CONVERSION(TELEGOOFUP, TWO_BYTE);
  4703.   WORD_TO_CONVERT : TELEGOOFUP;
  4704.   TEMP : TWO_BYTE;
  4705.   ICMP_MESSAGE : BUFFER_DATA.PACKED_BUFFER_PTR;
  4706.   ICMP_BUFPTR : IP_GLOBALS.BUFFER_POINTER;
  4707.   ICMP_HEADER_POINTER : SIXTEEN_BITS  range 20..60;
  4708.   IP_HEADER_POINTER : SIXTEEN_BITS  := 0;
  4709.   IHL_IN_OCTETS : SIXTEEN_BITS  range 20..60;
  4710.   BUFFER_TYPE : SIXTEEN_BITS  := 0;
  4711.   begin
  4712.     BUFFER_DATA.BUFFGET(ICMP_MESSAGE,BUFFER_TYPE);
  4713.     if REASSEMBLY_DATAGRAM_THAT_TIMED_OUT.HAS_FRAGMENT_ZERO_ARRIVED = 
  4714.      TRUE then
  4715.       ICMP_BUFPTR.VERSION := 4;
  4716.       ICMP_BUFPTR.IHL := 5;
  4717.       ICMP_BUFPTR.TOS := 0;
  4718.       ICMP_BUFPTR.ID := 0; -- Temporary; need to implement some type of ID gener
  4719. --ation
  4720.       ICMP_BUFPTR.FLAGS := 2; 
  4721.            -- MORE_FRAG_FLAG = FALSE AND DONT_FRAG_FLAG = FALSE
  4722.       ICMP_BUFPTR.FRAG_OFFSET := 0;
  4723.       ICMP_BUFPTR.TTL := 60;
  4724.       ICMP_BUFPTR.PROT := 1;
  4725.       ICMP_BUFPTR.SOURCE := BUFPTR.DEST;
  4726.       ICMP_BUFPTR.DEST := BUFPTR.SOURCE;
  4727.       --
  4728.       IP_HEADER_POINTER := 
  4729.       REASSEMBLY_DATAGRAM_THAT_TIMED_OUT.REASSEMBLY_DATAGRAM.IP_PTR;
  4730.       -- Convert IHL from 32-bit word size to 8-bit OCTETS
  4731.       IHL_IN_OCTETS := BUFPTR.IHL * 4;
  4732.       -- Calculate position of ICMP header
  4733.       ICMP_HEADER_POINTER := IP_HEADER_POINTER + IHL_IN_OCTETS;
  4734.       -- Load Time Exceeded Message Type
  4735.       ICMP_MESSAGE.BYTE(ICMP_HEADER_POINTER) := 11;
  4736.       -- Load code(fragment reassembly time exceeded)
  4737.       ICMP_MESSAGE.BYTE(ICMP_HEADER_POINTER + 1) := 1;
  4738.       -- Telesoft does not support packed aggregates
  4739.       for I in 0..5 loop
  4740.         ICMP_MESSAGE.BYTE(ICMP_HEADER_POINTER + 2 + 
  4741.                          SIXTEEN_BITS ( I ) ) := 0;
  4742.       end loop;
  4743.       -- load internet header and 64 bits of original datagram
  4744.         -- Telesoft does not support packed aggregates
  4745.       for I in 0..IHL_IN_OCTETS + 64 loop
  4746.         ICMP_MESSAGE.BYTE(ICMP_HEADER_POINTER + 8 + 
  4747.             SIXTEEN_BITS ( I ) ) := 
  4748.         REASSEMBLY_DATAGRAM_THAT_TIMED_OUT.REASSEMBLY_DATAGRAM.BYTE
  4749.         (ICMP_HEADER_POINTER + I);
  4750.       end loop;
  4751.       -- Calculate ICMP checksum
  4752.       WORD_TO_CONVERT(1) := UTILITIES_FOR_ICMP.ICMP_CHECKSUM
  4753.             (ICMP_HEADER_POINTER,
  4754.             (ICMP_HEADER_POINTER + ICMP_BUFPTR.TOT_LEN),
  4755.             ICMP_MESSAGE);
  4756.       TEMP := CONVERT_TO_TWO_BYTES(WORD_TO_CONVERT);
  4757.       ICMP_MESSAGE.BYTE(ICMP_HEADER_POINTER + 2) := TEMP(2);
  4758.       ICMP_MESSAGE.BYTE(ICMP_HEADER_POINTER + 3) := TEMP(1);
  4759.       IP_UNPACK_AND_PACK_UTILITIES.PACK_BUFFER_INTO_BIT_STREAM
  4760.         (ICMP_BUFPTR,ICMP_MESSAGE);
  4761.       -- Send ICMP message to subnet protocol
  4762.       UTILITIES_FOR_ICMP.SEND_ICMP_MESSAGE(ICMP_MESSAGE);
  4763.       -- release reassembly resoures
  4764.       DELETE_ENTRY_FROM_REASSEMBLY_TABLE(REASSEMBLY_DATAGRAM_THAT_TIMED_OUT);
  4765.     else
  4766.       -- no time exceeded message will be sent
  4767.       -- release reassembly resoures
  4768.       DELETE_ENTRY_FROM_REASSEMBLY_TABLE(REASSEMBLY_DATAGRAM_THAT_TIMED_OUT);
  4769.     end if;
  4770.   exception
  4771.     when CONSTRAINT_ERROR =>
  4772.       TEXT_IO.PUT_LINE(" CONSTRAINT_ERROR in package REASSEMBLY_UTILITIES ");
  4773.       TEXT_IO.PUT_LINE("procedure REASSEMBLY_TIMEOUT ");
  4774.     when others =>
  4775.       TEXT_IO.PUT_LINE(" UNKNOWN ERROR in package  REASSEMBLY_UTILITIES ");
  4776.       TEXT_IO.PUT_LINE("procedure REASSEMBLY_TIMEOUT ");
  4777.   end REASSEMBLY_TIMEOUT;  
  4778.   procedure REASSEMBLY( PACKED_BUFFER : in out BUFFER_DATA.PACKED_BUFFER_PTR;
  4779.                      REASSEMBLY_TABLE_ELEMENT : in out REASSEMBLY_TABLE_POINTER;
  4780.                         BUFPTR : IP_GLOBALS.BUFFER_POINTER ) is
  4781.   INCOMING_DATAGRAM_BUFID : BUFID_TYPE;
  4782.   DATA_IN_FRAG : SIXTEEN_BITS  := 0;
  4783.   ERROR : REASSEMBLY_ERROR_TYPE := NO_ERROR;
  4784.   BUFFER_TYPE : SIXTEEN_BITS  := 0;
  4785.     procedure STUFF_DATA_FROM_FRAGMENT is
  4786.     
  4787.     begin
  4788.       for I in 0..DATA_IN_FRAG loop
  4789.         REASSEMBLY_TABLE_ELEMENT.DATA(BUFPTR.FRAG_OFFSET + I + 1) :=
  4790.           PACKED_BUFFER.BYTE(PACKED_BUFFER.IP_PTR + (BUFPTR.IHL * 4) + I);
  4791.       end loop;
  4792.     exception
  4793.     when CONSTRAINT_ERROR =>
  4794.         NEW_LINE;
  4795.                 TEXT_IO.PUT(
  4796.                       "CONSTRAINT ERROR procedure STUFF_DATA_FROM_FRAGMENT");
  4797.         NEW_LINE;
  4798.         TEXT_IO.PUT("package REASSEMBLY UTILITIES");
  4799.     end STUFF_DATA_FROM_FRAGMENT;
  4800.     procedure SET_BIT_MAP is
  4801.     begin
  4802.       for I in 0..DATA_IN_FRAG loop
  4803.         REASSEMBLY_TABLE_ELEMENT.REASSEMBLY_MAP(BUFPTR.FRAG_OFFSET + I + 1) 
  4804.         := 1;
  4805.       end loop;
  4806.     exception
  4807.     when CONSTRAINT_ERROR =>
  4808.         NEW_LINE;
  4809.         TEXT_IO.PUT("CONSTRAINT ERROR procedure SET_BIT_MAP ");
  4810.         NEW_LINE;
  4811.         TEXT_IO.PUT("package REASSEMBLY UTILITIES");
  4812.     end SET_BIT_MAP;
  4813.   begin
  4814.     DATA_IN_FRAG := BUFPTR.TOT_LEN - BUFPTR.IHL * 4;
  4815.     INCOMING_DATAGRAM_BUFID := 
  4816.     (BUFPTR.SOURCE,BUFPTR.DEST,BUFPTR.PROT,BUFPTR.ID);
  4817.     REASSEMBLY_TABLE_ELEMENT := TOP_OF_REASSEMBLY_TABLE_POINTER;
  4818.     --REMOVE
  4819.     NEW_LINE;
  4820.     TEXT_IO.PUT("WE ARE REASSEMBLY");
  4821.     NEW_LINE;
  4822.     --REMOVE
  4823.     while not(REASSEMBLY_TABLE_ELEMENT = null) and then
  4824.     not(REASSEMBLY_TABLE_ELEMENT.BUFID = INCOMING_DATAGRAM_BUFID) loop
  4825.       REASSEMBLY_TABLE_ELEMENT := 
  4826.         REASSEMBLY_TABLE_ELEMENT.NEXT_ENTRY_REASSEMBLY_TABLE;
  4827.     end loop;
  4828.     if (REASSEMBLY_TABLE_ELEMENT /= null) and (BUFPTR.TTL > 0) then
  4829.       -- store data
  4830.       STUFF_DATA_FROM_FRAGMENT;
  4831.       -- set bitmap
  4832.       SET_BIT_MAP;
  4833.       if not(REASSEMBLY_TABLE_ELEMENT.HAS_FRAGMENT_ZERO_ARRIVED) then
  4834.         -- here's the tail
  4835.         REASSEMBLY_TABLE_ELEMENT.TOTAL_DATA_LENGTH := 
  4836.           BUFPTR.FRAG_OFFSET + (BUFPTR.TOT_LEN - BUFPTR.IHL);
  4837.         REASSEMBLY_TABLE_ELEMENT.HAS_FRAGMENT_ZERO_ARRIVED := TRUE;
  4838.         REASSEMBLY_TABLE_ELEMENT.HEADER := 
  4839.         IP_UNPACK_AND_PACK_UTILITIES.UNPACK(PACKED_BUFFER);
  4840.       end if;
  4841.       -- reset reassembly timer if its current value is less
  4842.       -- than the time-to-live field of the recieved datagram
  4843.       if REASSEMBLY_TABLE_ELEMENT.TIMER < BUFPTR.TTL then
  4844.         REASSEMBLY_TABLE_ELEMENT.TIMER := 15;
  4845.       end if;
  4846.     elsif (REASSEMBLY_TABLE_ELEMENT = null) and (BUFPTR.TTL > 0) then
  4847.       -- fragment is a new fragmented datagram
  4848.       -- obtain fragment buffer
  4849.       GET_REASSEMBLY_STRUCTURE(REASSEMBLY_TABLE_ELEMENT,ERROR);
  4850.       if ERROR = NO_ERROR then
  4851.         REASSEMBLY_TABLE_ELEMENT.STATE_NAME := INACTIVE;
  4852.         REASSEMBLY_TABLE_ELEMENT.BUFID := INCOMING_DATAGRAM_BUFID;
  4853.         -- store data
  4854.         STUFF_DATA_FROM_FRAGMENT;
  4855.         -- set bitmap
  4856.         SET_BIT_MAP;
  4857.       elsif (ERROR = NO_MORE_FREE_BUFFER_SPACE) then
  4858.         -- send ICMP message
  4859.         null;
  4860.       else
  4861.         -- we should never get here!!!
  4862.         null;
  4863.       end if;
  4864.     elsif (REASSEMBLY_TABLE_ELEMENT /= null) and not(BUFPTR.TTL > 0) then
  4865.       REASSEMBLY_TIMEOUT(REASSEMBLY_TABLE_ELEMENT,BUFPTR);
  4866.       BUFFER_DATA.BUFFREE(PACKED_BUFFER,BUFFER_TYPE);
  4867.       DELETE_ENTRY_FROM_REASSEMBLY_TABLE(REASSEMBLY_TABLE_ELEMENT);
  4868.     else
  4869.       -- should never get here
  4870.       null;
  4871.     end if;          
  4872.   end REASSEMBLY;
  4873.   procedure REASSEMBLED_DELIVERY
  4874.     ( PACKED_BUFFER : in BUFFER_DATA.PACKED_BUFFER_PTR ) is
  4875.   begin
  4876.     null;
  4877.   end REASSEMBLED_DELIVERY;
  4878.   procedure REMOTE_DELIVERY
  4879.     ( PACKED_BUFFER : in BUFFER_DATA.PACKED_BUFFER_PTR ) is
  4880.   begin
  4881.     null;
  4882.   end REMOTE_DELIVERY;
  4883. end REASSEMBLY_UTILITIES;
  4884. --::::::::::::::
  4885. --rtc.txt
  4886. --::::::::::::::
  4887. -----------------------------------------------------------------------
  4888. --
  4889. --         DoD Protocols    NA-00008-200       80-01188-100(-)
  4890. --         E-Systems, Inc.  August 07, 1985
  4891. --
  4892. --         rtc.txt       Author : Jim Baldo
  4893. --
  4894. -----------------------------------------------------------------------
  4895. (*ada dummy*)
  4896. (*asm68 body*)
  4897. * ADA SPECIFICATION
  4898. -- Dummy Ada Specifiction for assembly language body
  4899. package T_REAL_TIME_CLOCK  is
  4900.  procedure START;
  4901.  
  4902.  procedure STOP;
  4903.  
  4904.  procedure READ(TICKS : out LONG_INTEGER);
  4905.  
  4906. end T_REAL_TIME_CLOCK;
  4907. * ADA DUMMY BODY
  4908. package body T_REAL_TIME_CLOCK  is
  4909.  procedure START is
  4910.  
  4911.  begin
  4912.   null;
  4913.  end START;
  4914.  
  4915.  procedure STOP is
  4916.  
  4917.  begin
  4918.   null;
  4919.  end STOP;
  4920.  
  4921.  procedure READ(TICKS : out LONG_INTEGER) is
  4922.  
  4923.  begin
  4924.   null;
  4925.  end READ;
  4926. end T_REAL_TIME_CLOCK;
  4927. -- Real Time Clock
  4928. * ASM68 BODY
  4929.         
  4930.         .asection REAL_TIME_CLOCK
  4931.         .run_relocate
  4932.         ;.INCLUDE MOD:A68/MACLIB
  4933. ;
  4934.         STARTCOD
  4935. ;
  4936.         SETSTKSPACE     24
  4937. ;
  4938.  MS1HIGH:       .EQU    3       ; 1 MSEC VALUE (HIGH BYTE)
  4939.  MS1LOW:        .EQU    32.     ; 1MSEC VALUE (LOW BYTE);
  4940.  T1CNTLOW:      .EQU    0F00048 ; TIMER1 COUNTER REG (LOW BYTE)
  4941.  T1CNTHIGH:     .EQU    0F0004A ; TIMER1 COUNTER REG (HIGH BYTE)
  4942.  T1LATCHLOW:    .EQU    0F0004C ; TIMER1 LATCH REG (LOW BYTE)
  4943.  T1LATCHHIGH:   .EQU    000004e ; TIMER1 LATCH REG (HIGH BYTE)
  4944.  AUXREG:        .EQU    0F00056 ; AUXILLIARY CONTROL REG
  4945.  INTENABLE:     .EQU    0F0005C ; INTERRUPT ENABLE REG
  4946.  LEVEL1:        .EQU    64      ; LEVEL 1 INTERRUPT VECTOR ADDR (TIMER)D
  4947.  ;
  4948.  ;      procedure START;
  4949.  ;
  4950.  START:
  4951.         MOVEM.L D0/A6,-(SP)     ; SAVE REGS
  4952.         BSR     STOPCLK         ; IF RUNNING THEN STOP IT
  4953.         LEA     RUNNING,A6      ; 
  4954.         MOVE.B  #1,(A6)         ; NOW SET RUNNING FLAG
  4955.         MOVE.B  #40,INTENABLE.L ; DISABLE INTERRUPTS
  4956.         LEA     VECTORSAVE,A6   ; POINT TO SAVE AREA
  4957.         MOVE.L  LEVEL1,(A6)     ; SAVE PREVIOIUS INTERRUPT VECTOR
  4958.         LEA     ISS,A6          ; POINT A6 TO OUR ROUTINE
  4959.         MOVE.L  A6,LEVEL1       ; REPLACE INTERRUPT VECTOR
  4960.         LEA     COUNT,A6        ;START CLOCK WITH ZERO
  4961.         CLR.L   (A6)            
  4962.  ; SET THE INTERVAL - NOW USE 1MSEC
  4963.         MOVEQ   #MS1LOW,D0      ; FETCH COUNT 'INTERVAL'
  4964.         MOVE.B  D0,T1CNTLOW.L   ; INIT LOW COUNTER & LATCH
  4965.         MOVE.B  D0,T1LATCHLOW.L
  4966.         MOVEQ   #MS1HIGH,D0     ; GET HIGH BYTE
  4967.         MOVE.B  D0,T1CNTHIGH.L  ; INIT HIGH BYTES
  4968.         MOVE.B  D0,T1LATCHHIGH.L
  4969.         MOVE.B  #40,AUXREG.L    ; SET TIMER FOR CONTINUOUS MODE
  4970.         MOVE.B  #0C0,INTENABLE.L; ENABLE INTERRUPTS
  4971.         MOVEM.L (SP)+,D0/A6     ; RESTORE REGS
  4972.         RTS
  4973.  ;
  4974.  ; procedure STOP
  4975.  ;
  4976.  STOPCLK:
  4977.         MOVE.L  A6,-(SP)        ; SAVE REGS
  4978.         LEA     RUNNING,A6      ; SEE IF ALREADY RUNNING
  4979.         TST.B   (A6)
  4980.         BEQ.B   STOPCLK90       ; GO ON IF NOT
  4981.         CLR.B   (A6)            ; SHUT OFF RUNNING
  4982.         MOVE.B  #40,INTENABLE.L ; DISABLE INTERRUPTS
  4983.         MOVE.L  VECTORSAVE,LEVEL1; RESTORE VECTOR
  4984.  STOPCLK90:
  4985.         MOVEA.L (SP)+,A6        ; RESTORE VECTOR
  4986.         RTS
  4987.  ;
  4988.  ; procedure READ(TICKS : out LONG_INTEGER);   -- CALL FROM ADA
  4989.  ;
  4990.  READ:
  4991.         MOVE.L  A6,-(SP)        ; SAVE REGS
  4992.         MOVEA.L 08(SP),A6       ; GET ADDRESS OF 'TICKS'
  4993.         MOVE.L  COUNT,(A6)      ; GET ROOL-OVER COUNT
  4994.         MOVEA.L (SP)+,A6        ; RESTORE REGS
  4995.         MOVE.L  (SP)+,(SP)      ; MOVE RETURN ADDRESS (TRASH PARAMETER)
  4996.         RTS
  4997.  ;
  4998.  ; CLOCK INTERRUPT SERVICE SUBROUTINE
  4999.  ;
  5000.  ISS:
  5001.         MOVE.L  A6,-(SP)
  5002.         LEA     COUNT,A6
  5003.         ADDQ.L  #1,(A6)         ; UPDATE ROLL OVER COUNT
  5004.         TST.B   T1CNTLOW.L       ; CLEAR INTERRUPT
  5005.         MOVEA.L (SP)+,A6        ; AND EXIT
  5006.         RTE
  5007.  ;
  5008.  ; DATA AREA
  5009.  ;
  5010.  VECTORSAVE:    .LONG   0       ; AREA TO SAVE LEVEL1 VECTOR
  5011.  COUNT:         .LONG   0       ; ROLLOVER COUNTER
  5012.  RUNNING:       .BYTE   0       ; RUNNING FLAG
  5013.                 .ALIGN  2
  5014.  CODINIT
  5015.  CODTERM
  5016.         BSR     STOPCLK         ; STOP EVERYTHING
  5017.  CODENDTERM
  5018.  PROCBRANCH     READ
  5019.  PROCBRANCH     STOPCLK
  5020.  PROCBRANCH     START
  5021.  CODWRAPUP
  5022.         .END
  5023.         
  5024. --::::::::::::::
  5025. --segarrive.txt
  5026. --::::::::::::::
  5027. -----------------------------------------------------------------------
  5028. --
  5029. --         DoD Protocols    NA-00008-200       80-01189-100(-)
  5030. --         E-Systems, Inc.  August 07, 1985
  5031. --
  5032. --         segarrive.txt       Author : Jim Baldo
  5033. --
  5034. -----------------------------------------------------------------------
  5035. with WITH_TCP_COMMUNICATE;        use WITH_TCP_COMMUNICATE;
  5036. with BUFFER_DATA;            use BUFFER_DATA;
  5037. --with T_TCP_GLOBALS_DATA_STRUCTURES;    use T_TCP_GLOBALS_DATA_STRUCTURES;
  5038.         package    TCP_SEGMENT_ARRIVES_PROCESSING is
  5039.     -------------------------------------------------------------
  5040.     --This implementation is for use with the DEC/Ada          --
  5041.     --compiler .                                               --
  5042.     -------------------------------------------------------------
  5043. -------------------------------------------------------------------------------
  5044. -- THIS    PACKAGE    CONTAINS ALL THE PROCEDURES AND    FUNCTIONS NECESSARY FOR      --
  5045. -- PROCESSING ARRIVED SEGMENTS.    IT ALSO    CONTAINS THE HEADER FORMAT ROUTINE.  --
  5046. -------------------------------------------------------------------------------
  5047. procedure TCP_SEG_ARRIVE( PACKED_BUFFER    : in out PACKED_BUFFER_PTR; 
  5048.                       BYTE_COUNT : in SIXTEEN_BITS ;
  5049.                       SOURCE_FROM_IP, DEST : in THIRTYTWO_BITS ; 
  5050.                       PROT, TOS_IP : in SIXTEEN_BITS ;
  5051.                       SECURITY_OP : in SECURITY_OPTION_TYPE);
  5052.     --This procedure will take a segment and determine what LCN, if any it
  5053.     --belongs to. It will check if it is a valid segment in terms of 
  5054.     --sequence number and if the checksum is valid.  It will also determine
  5055.     --that the address is for us.  If so it will cause the required 
  5056.     --processing for the state to be done, by calling the proper routine.
  5057. end TCP_SEGMENT_ARRIVES_PROCESSING;
  5058. with WITH_IP_COMMUNICATE;               use WITH_IP_COMMUNICATE;
  5059. with WITH_ULP_COMMUNICATE;              use WITH_ULP_COMMUNICATE;
  5060. with T_TCP_GLOBALS_DATA_STRUCTURES;    use T_TCP_GLOBALS_DATA_STRUCTURES;
  5061. with QUEUES;                use QUEUES;
  5062. with TCP_GLOBALS;            use TCP_GLOBALS;
  5063. with IP_GLOBALS ;            use IP_GLOBALS ;
  5064. with TEXT_IO;                           use TEXT_IO, INTEGER_IO;
  5065. with TCP_ARRIVES_PERIPHERALS;        use TCP_ARRIVES_PERIPHERALS;
  5066. with MODULO;                use MODULO;
  5067. with TCB_ALLOCATOR;            use TCB_ALLOCATOR;
  5068. WITH TCP_SEG_ARRIVE ;                 USE TCP_SEG_ARRIVE ;
  5069. with T_TCP_ARRIVES_1;                   use T_TCP_ARRIVES_1;
  5070.     
  5071.         package    body TCP_SEGMENT_ARRIVES_PROCESSING is
  5072. PROCEDURE TCP_SEG_ARRIVE(PACKED_BUFFER    : in out PACKED_BUFFER_PTR; 
  5073.              BYTE_COUNT : in SIXTEEN_BITS ;
  5074.                      SOURCE_FROM_IP, DEST : in THIRTYTWO_BITS ; 
  5075.                          PROT, TOS_IP : in SIXTEEN_BITS ;
  5076.                      SECURITY_OP : in SECURITY_OPTION_TYPE) is
  5077.     --This procedure is called by the TCP controller when it gets an 
  5078.     --arrived segment.  Here the appropriate processor is called.
  5079. LCN_LIST : TCB_PTR;
  5080. TCP_LENGTH, BUFFTYPE : SIXTEEN_BITS ;
  5081. NOT_VALID_ADDRESS : BOOLEAN := TRUE;
  5082. BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5083. PROCEDURE SEQUENCE_NUMBER_CHECKER( LCN : in TCB_PTR; 
  5084.                                    BUFPTR : in 
  5085.                          T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5086.                    RESULT : in out RES; 
  5087.                                    TCP_LENGTH : in out SIXTEEN_BITS ) is
  5088. DATA_LENGTH : SIXTEEN_BITS ;
  5089. begin
  5090.  DATA_LENGTH := TCP_LENGTH - BUFPTR.DATA_OFFSET * 4;
  5091.  if LCN.RCV_WINDOW > 0 then
  5092.   if BUFPTR.SEQ_NUM = LCN.RCV_NXT then
  5093.    if BUFPTR.SEQ_NUM + DATA_LENGTH <= LCN.RCV_NXT + LCN.RCV_WINDOW
  5094.                                     then
  5095.     RESULT := GOOD;
  5096.    else
  5097.     RESULT := GOOD;
  5098.     DATA_LENGTH := LCN.RCV_WINDOW;
  5099.     TCP_LENGTH := DATA_LENGTH + BUFPTR.DATA_OFFSET * 4;
  5100.    end if;
  5101.   elsif (BUFPTR.SEQ_NUM < LCN.RCV_NXT) and 
  5102.          BUFPTR.SEQ_NUM + DATA_LENGTH > LCN.RCV_NXT then
  5103.    -- IT'S PARTLY IN THE WINDOW. THIS SHOULD NOT CURRENTLY HAPPEN!
  5104.    TCP_ERROR(6);
  5105.    RESULT := BAD;
  5106.   elsif BUFPTR.SEQ_NUM < LCN.RCV_NXT + LCN.RCV_WINDOW then
  5107.    -- SOME OF IT IS IN THE WINDOW IT JUST DOES NOT START IN THE WINDOW.
  5108.    -- WE CURRENTLY IGNORE THIS.
  5109.    RESULT := BAD;
  5110.   else
  5111.   RESULT := BAD;
  5112.   end if;
  5113.  elsif TCP_LENGTH = BUFPTR.DATA_OFFSET * 4 then
  5114.   -- A ZERO LENGTH SEGMENT PROBABLY AN ACK.
  5115.   RESULT := GOOD;
  5116.  else
  5117.   -- A SEGMENT WITH DATA ON AN EMPTY WINDOW.
  5118.   RESULT := BAD;
  5119.  end if;
  5120. end SEQUENCE_NUMBER_CHECKER;
  5121. procedure SEND_ACK_OF_UNACCEPTABLE_SEGMENT is
  5122. RESULT : WITH_IP_COMMUNICATE.RESULT_TYPE;
  5123. MESSAGE_FOR_IP : WITH_IP_COMMUNICATE.IP_MESSAGE ;
  5124. begin
  5125. -- WE WILL SEND OUT AN ACK IN THE SAME PACKED BUFFER IT ARRIVED IN.
  5126. OPTIONS := CLEAR;
  5127. TCP_HEADER_FORMAT(LCN, BUFPTR, ACK, OPTIONS);
  5128. -- REUSE THE BUFFER. SO WE MUST RESET ITS POINTER.
  5129. PACKED_BUFFER.TCP_PTR := 255;
  5130. -- ZERO OUT THE DATA LENGTH OF THE BUFFER.
  5131. BUFPTR.DATA_LEN := 0;
  5132. PACK_BUFFER_INTO_BIT_STREAM(BUFPTR, PACKED_BUFFER);
  5133. OPTIONS := TCP_SECURITY_OPTIONS;
  5134. SEND_IP( LCN.SOURCE_ADDRESS,
  5135.          LCN.DESTINATION_ADDRESS,
  5136.          TOS,
  5137.          TTL,
  5138.          PACKED_BUFFER,
  5139.          BUFPTR.DATA_OFFSET * 4,
  5140.          IDENT,
  5141.          DONT_FRAGMENT,
  5142.          OPTIONS,
  5143.          RESULT);
  5144. -- NO UPDATE OF THE SEQUENCE NUMBER
  5145. TCP_ERROR(13);-- NOTE AN INVALID SEQUENCE NUMBER ARRIVED
  5146. end SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5147. begin
  5148. -- UNPACK THE BUFFER
  5149. BUFPTR := TCP_ARRIVES_PERIPHERALS.UNPACK(PACKED_BUFFER, BYTE_COUNT); 
  5150. -- NEEDS THE DATA COUNT.
  5151. -- DETERMINE WHETHER CHECKSUM IS VALID. 
  5152. IF BUFPTR.TCP_CSUM /= CHECKSUM(BYTE_COUNT, PACKED_BUFFER, DEST, SOURCE_FROM_IP,
  5153.                    PROT) THEN
  5154.   -- RELEASE BUFFER
  5155.   PUT_LINE("BAD CHECKSUM IN SEGARIV");---DEBUG
  5156.   TEXT_IO.LONG_INTEGER_IO.PUT(SOURCE_FROM_IP);
  5157.   PUT_LINE(""); -- WHY 128 LOST ON ABORT.
  5158.   TEXT_IO.INTEGER_IO.PUT(BUFPTR.TCP_CSUM);
  5159.   TEXT_IO.INTEGER_IO.PUT( CHECKSUM(BYTE_COUNT, 
  5160.                   PACKED_BUFFER, 
  5161.                   DEST, 
  5162.                   SOURCE_FROM_IP,
  5163.           PROT));---DEBUG
  5164.   PUT_LINE("POINTER AND BYTE COUNT");
  5165.   TEXT_IO.INTEGER_IO.PUT(PACKED_BUFFER.TCP_PTR);
  5166.   TEXT_IO.INTEGER_IO.PUT(BYTE_COUNT);
  5167.   TCP_ERROR(15);
  5168.   BUFFREE(PACKED_BUFFER, BUFFTYPE);
  5169. ELSE
  5170.   -- SET UP THE GLOBAL PSEUDO HEADER
  5171.   FOR I IN 1..9 LOOP
  5172.     SECURITY(I) := SECURITY_OP ( SIXTEEN_BITS ( I ) ) ;
  5173.   END LOOP;
  5174.   IP_TOS := TOS_IP;
  5175.   SOURCE := SOURCE_FROM_IP;
  5176.   DESTINATION := DEST;
  5177.   --  MATCH UP    SEGMENT    WITH A LCN (HENCE A TCB)
  5178.   LCN_LIST := OBTAIN_HEAD_OF_LCN_IN_USE_QUEUE;
  5179.   while LCN_LIST /= null loop
  5180.    -- CHECK FOR A VALID SOCKET.
  5181.    if LCN_LIST.SOURCE_ADDRESS = DEST and 
  5182.        (BUFPTR.DESTINATION_PORT = LCN_LIST.LOCAL_PORT) then
  5183.     LCN := LCN_LIST; -- SET GLOBAL LCN
  5184.     NOT_VALID_ADDRESS := FALSE;
  5185.     exit;
  5186.    else --obtain next LCN
  5187.     LCN_LIST := LCN_LIST.NEXT;
  5188.    end if;
  5189.   end loop;
  5190. -- DETERMINE IF THE FOREIGN PORT AND SOURCE ARE THE ONE FOR THE OBSERVED LCN  
  5191.   if LCN /= null then
  5192.    IF LCN.STATE /= T_TCP_GLOBALS_DATA_STRUCTURES.CLOSED AND
  5193.         (LCN.STATE /= T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN) THEN
  5194.      IF LCN.DESTINATION_ADDRESS /= SOURCE_FROM_IP OR (LCN.FOREIGN_PORT
  5195.         /= BUFPTR.SOURCE_PORT) THEN
  5196.        NOT_VALID_ADDRESS := TRUE;
  5197.      END IF;
  5198.    END IF;
  5199.   end if;
  5200.   if NOT_VALID_ADDRESS then -- NOT FOR US
  5201.     -- RELEASE BUFFER
  5202.     PUT_LINE("GOT A PACKET NOT FOR US IN SEGARIV");
  5203.     --TCP_ERROR(16);
  5204.     PACKED_BUFFER.IN_USE := FALSE;
  5205.     PACKED_BUFFER.STATUS := NONE;
  5206.     BUFFREE(PACKED_BUFFER, BUFFTYPE);
  5207.   else
  5208.     -- RESTART THE CONNECTION TIMEOUT TIMER.
  5209.     START_TIMER(LCN, TIMEOUT_TIMER);
  5210.     -- SET UP GLOBAL BUFFER POINTER FOR DELETE PRIVLEDGE IN ALL ROUTINES
  5211.     TCP_ARRIVES_PERIPHERALS.GLOBAL_PACKED_BUFFER := PACKED_BUFFER;
  5212.     -- PUT DATA    LENGTH IN THE BUFFER
  5213.     BUFPTR.DATA_LEN := BYTE_COUNT - BUFPTR.DATA_OFFSET * 4;
  5214.     TCP_LENGTH := BYTE_COUNT; -- THE LENGTH OF SEGMENT AND DATA
  5215.     case LCN.STATE    is
  5216.       when CLOSED => SEG_ARRIVED_IN_CLOSED_STATE( BUFPTR, 
  5217.                                                   BYTE_COUNT,
  5218.                                           SOURCE_FROM_IP, 
  5219.                                                   DEST);
  5220.     
  5221.       when T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN =>
  5222.                 SEG_ARRIVED_IN_LISTEN_STATE( BUFPTR, 
  5223.                                              BYTE_COUNT,
  5224.                          SOURCE_FROM_IP);   
  5225.       when SYN_SENT => SEG_ARRIVED_IN_SYN_SENT_STATE( BUFPTR, 
  5226.                                                       BYTE_COUNT);
  5227.     
  5228.       when SYN_RECEIVED    => SEQUENCE_NUMBER_CHECKER( LCN,
  5229.                                                  BUFPTR,    
  5230.                                                TCP_ARRIVES_PERIPHERALS.RESULTS, 
  5231.                                         TCP_LENGTH);
  5232.              if TCP_ARRIVES_PERIPHERALS.RESULTS = T_TCP_ARRIVES_1.GOOD then
  5233.              
  5234.                  SEG_ARRIVED_IN_SYN_RECEIVED_STATE( BUFPTR, 
  5235.                                                                 TCP_LENGTH);
  5236.                else
  5237.                  SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5238.                end if;
  5239.     
  5240.        when ESTABLISHED => SEQUENCE_NUMBER_CHECKER( LCN, 
  5241.                                                     BUFPTR, 
  5242.                                TCP_ARRIVES_PERIPHERALS.RESULTS, 
  5243.                                                     TCP_LENGTH);
  5244.          if TCP_ARRIVES_PERIPHERALS.RESULTS = T_TCP_ARRIVES_1.GOOD then
  5245.                            SEG_ARRIVED_IN_ESTABLISHED_STATE( BUFPTR, 
  5246.                                                              TCP_LENGTH);
  5247.               else
  5248.                  SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5249.               end if;
  5250.     
  5251.       WHEN FIN_WAIT_1 => SEQUENCE_NUMBER_CHECKER( LCN, 
  5252.                                                   BUFPTR, 
  5253.                          TCP_ARRIVES_PERIPHERALS.RESULTS, 
  5254.                                                   TCP_LENGTH);
  5255.               IF TCP_ARRIVES_PERIPHERALS.RESULTS = T_TCP_ARRIVES_1.GOOD THEN
  5256.                 SEG_ARRIVED_IN_FIN_WAIT_1_STATE(BUFPTR, TCP_LENGTH);
  5257.              ELSE
  5258.                  SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5259.              END IF;
  5260.     
  5261.       WHEN FIN_WAIT_2 => SEQUENCE_NUMBER_CHECKER
  5262.                  (LCN, BUFPTR, TCP_ARRIVES_PERIPHERALS.RESULTS, TCP_LENGTH);
  5263.       IF TCP_ARRIVES_PERIPHERALS.RESULTS = T_TCP_ARRIVES_1.GOOD THEN
  5264.                SEG_ARRIVED_IN_FIN_WAIT_2_STATE(BUFPTR, TCP_LENGTH);
  5265.              ELSE
  5266.                  SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5267.              END IF;
  5268.     
  5269.       WHEN CLOSE_WAIT => SEQUENCE_NUMBER_CHECKER
  5270.              (LCN, BUFPTR, TCP_ARRIVES_PERIPHERALS.RESULTS, TCP_LENGTH);
  5271.         IF TCP_ARRIVES_PERIPHERALS.RESULTS = T_TCP_ARRIVES_1.GOOD THEN
  5272.                SEG_ARRIVED_IN_CLOSE_WAIT_STATE(BUFPTR, TCP_LENGTH);
  5273.              ELSE
  5274.                  SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5275.              END IF;
  5276.       when CLOSING => SEQUENCE_NUMBER_CHECKER( LCN, 
  5277.                                                BUFPTR, 
  5278.                       TCP_ARRIVES_PERIPHERALS.RESULTS, 
  5279.                                                TCP_LENGTH);
  5280.       if TCP_ARRIVES_PERIPHERALS.RESULTS = T_TCP_ARRIVES_1.GOOD    then
  5281.                SEG_ARRIVED_IN_CLOSING_STATE( BUFPTR, 
  5282.                                                      TCP_LENGTH);
  5283.               else
  5284.                SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5285.               end if;
  5286.     
  5287.       when LAST_ACK => SEQUENCE_NUMBER_CHECKER( LCN, 
  5288.                                                 BUFPTR, 
  5289.                    TCP_ARRIVES_PERIPHERALS.RESULTS, 
  5290.                                                 TCP_LENGTH);
  5291.        if TCP_ARRIVES_PERIPHERALS.RESULTS = T_TCP_ARRIVES_1.GOOD then
  5292.             SEG_ARRIVED_IN_LAST_ACK_STATE( BUFPTR, 
  5293.                                                        TCP_LENGTH);
  5294.                else
  5295.                 SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5296.                end if;
  5297.     
  5298.       when TIME_WAIT =>    SEQUENCE_NUMBER_CHECKER( LCN,
  5299.                                                  BUFPTR, 
  5300.                           TCP_ARRIVES_PERIPHERALS.RESULTS, 
  5301.                                                  TCP_LENGTH);
  5302.            if TCP_ARRIVES_PERIPHERALS.RESULTS = T_TCP_ARRIVES_1.GOOD then
  5303.              SEG_ARRIVED_IN_TIME_WAIT_STATE( BUFPTR, 
  5304.                                                          TCP_LENGTH);
  5305.             else
  5306.              if BUFPTR.SEQ_NUM < LCN.RCV_NXT and
  5307.                  BUFPTR.FIN = BIT_SET then
  5308.                   -- RESTART THE TIMEOUT TIMER SINCE AN OLD FIN CAME 
  5309.                           -- IN
  5310.                   START_TIMER(LCN, TIMEOUT_TIMER);
  5311.                  end if;
  5312.                      SEND_ACK_OF_UNACCEPTABLE_SEGMENT;
  5313.             end if;
  5314.     end    case;
  5315.   end if;
  5316. end if;
  5317.     
  5318. EXCEPTION
  5319.   WHEN CONSTRAINT_ERROR =>
  5320.    PUT_LINE("CONSTRAINT ERROR OCCURRED IN SEGARIV PACKAGE");
  5321.   WHEN OTHERS =>
  5322.    PUT_LINE("PROBLEM IN SEGARIV");
  5323. END TCP_SEG_ARRIVE;
  5324. END TCP_SEGMENT_ARRIVES_PROCESSING;
  5325. --::::::::::::::
  5326. --segarrive1.txt
  5327. --::::::::::::::
  5328. -----------------------------------------------------------------------
  5329. --
  5330. --         DoD Protocols    NA-00008-200       80-01190-100(-)
  5331. --         E-Systems, Inc.  August 07, 1985
  5332. --
  5333. --         segarrive1.txt       Author : Jim Baldo
  5334. --
  5335. -----------------------------------------------------------------------
  5336. with T_TCP_GLOBALS_DATA_STRUCTURES;
  5337. use T_TCP_GLOBALS_DATA_STRUCTURES;
  5338. with WITH_TCP_COMMUNICATE;              use WITH_TCP_COMMUNICATE;
  5339. with BUFFER_DATA;                       use BUFFER_DATA;
  5340.                         package TCP_SEG_ARRIVE is
  5341.                         
  5342. -------------------------------------------------------------
  5343. --This implementation is for use with the Telesoft/Ada     --
  5344. --compiler .                                               --
  5345. -------------------------------------------------------------
  5346. -------------------------------------------------------------------------------
  5347. -- THIS    PACKAGE    CONTAINS ALL THE PROCEDURES AND    FUNCTIONS NECESSARY FOR      --
  5348. -- PROCESSING ARRIVED SEGMENTS.    IT ALSO    CONTAINS THE HEADER FORMAT ROUTINE.  --
  5349. -------------------------------------------------------------------------------
  5350. procedure SEG_ARRIVED_IN_CLOSED_STATE( BUFPTR : in out 
  5351.                                        T_TCP_GLOBALS_DATA_STRUCTURES.
  5352.                                           BUFFER_POINTER;
  5353.                        BYTE_COUNT : in SIXTEEN_BITS ; 
  5354.                                        SOURCE, DESTINATION : 
  5355.                                         in THIRTYTWO_BITS );
  5356. procedure SEG_ARRIVED_IN_LISTEN_STATE( BUFPTR : in out T_TCP_GLOBALS_DATA_STRUCTURES.
  5357.                                                 BUFFER_POINTER;
  5358.                        BYTE_COUNT : in SIXTEEN_BITS ; 
  5359.                                        SOURCE : in THIRTYTWO_BITS ) ;
  5360. procedure SEG_ARRIVED_IN_SYN_SENT_STATE( BUFPTR : in out 
  5361.                           T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5362.                      BYTE_COUNT : in SIXTEEN_BITS ) ;
  5363. procedure SEG_ARRIVED_IN_SYN_RECEIVED_STATE( BUFPTR : in out 
  5364.                                    T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5365.                              BYTE_COUNT : in SIXTEEN_BITS ) ;
  5366. PROCEDURE SEG_ARRIVED_IN_ESTABLISHED_STATE( BUFPTR : in out 
  5367.                                   T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5368.                             BYTE_COUNT : in SIXTEEN_BITS ) ;
  5369. PROCEDURE SEG_ARRIVED_IN_FIN_WAIT_1_STATE( BUFPTR : in out 
  5370.                                   T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5371.                            BYTE_COUNT : in SIXTEEN_BITS ) ;
  5372. procedure SEG_ARRIVED_IN_FIN_WAIT_2_STATE( BUFPTR : in out 
  5373.                                   T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5374.                            BYTE_COUNT : in SIXTEEN_BITS ) ;
  5375. procedure SEG_ARRIVED_IN_CLOSE_WAIT_STATE( BUFPTR : in out 
  5376.                                  T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5377.                            BYTE_COUNT : in SIXTEEN_BITS ) ;
  5378. procedure SEG_ARRIVED_IN_CLOSING_STATE( BUFPTR : in out 
  5379.                            T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5380.                          BYTE_COUNT : in SIXTEEN_BITS ) ;
  5381. PROCEDURE SEG_ARRIVED_IN_LAST_ACK_STATE( BUFPTR : in out 
  5382.                              T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5383.                          BYTE_COUNT : in SIXTEEN_BITS ) ;
  5384. PROCEDURE SEG_ARRIVED_IN_TIME_WAIT_STATE( BUFPTR : in out 
  5385.                                 T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5386.                           BYTE_COUNT : in SIXTEEN_BITS ) ;
  5387. end TCP_SEG_ARRIVE;
  5388. with T_TCP_ARRIVES_1;
  5389. with TEXT_IO;           use TEXT_IO;
  5390. with QUEUES;            use QUEUES;
  5391. with TCP_GLOBALS;       use TCP_GLOBALS;
  5392. with IP_GLOBALS;        use IP_GLOBALS;
  5393. with WITH_ULP_COMMUNICATE;
  5394. use WITH_ULP_COMMUNICATE;
  5395. with TCB_ALLOCATOR;     use TCB_ALLOCATOR;
  5396. with TCP_ARRIVES_PERIPHERALS;
  5397. use TCP_ARRIVES_PERIPHERALS;
  5398. with MODULO;            use MODULO;
  5399. package body TCP_SEG_ARRIVE is
  5400. procedure SEG_ARRIVED_IN_CLOSED_STATE( BUFPTR : in out 
  5401.                                        T_TCP_GLOBALS_DATA_STRUCTURES.
  5402.                                           BUFFER_POINTER;
  5403.                        BYTE_COUNT : in SIXTEEN_BITS ; 
  5404.                                        SOURCE, DESTINATION : 
  5405.                                         in THIRTYTWO_BITS ) is
  5406. --   THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVED CONTROLLER    WHEN A SEGMENT
  5407. --   ARRIVES WITH NO CONNECTION    AT ATTEMPT BY THE USER (I.E. THE CLOSED    STATE).
  5408. -- PROCESSING :
  5409. --
  5410. --   THIS PROCEDURE WILL IGNORE    A RESET    FROM THE REMOTE    HOST. IF THE SEGMENT
  5411. --   IS    NOT A RESET THEN A RESET WILL BE FORMED    AND SENT TO THE    REMOTE HOST.
  5412. --
  5413. BUFFTYPE : SIXTEEN_BITS ;
  5414. BEGIN
  5415. IF BUFPTR.RST =    BIT_SET     THEN -- THE SEGMENT IS    A RESET, IGNORE    IT.
  5416.   -- RELEASE BUFFER
  5417.   GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5418.   GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5419.   BUFFREE(GLOBAL_PACKED_BUFFER, BUFFTYPE);
  5420. ELSE --    SEND A RESET
  5421. -- USE THE SAME    BUFFER
  5422. -- SET UP THE RESERVE TCB (NUMBER 5)
  5423.   RESERVE.RCV_NXT := BUFPTR.ACK_NUM;
  5424.   RESERVE.SND_NXT := BUFPTR.SEQ_NUM;
  5425.   RESERVE.SOURCE_ADDRESS := DESTINATION;
  5426.   RESERVE.DESTINATION_ADDRESS := SOURCE;
  5427.   RESERVE.LOCAL_PORT := BUFPTR.DESTINATION_PORT;
  5428.   RESERVE.FOREIGN_PORT := BUFPTR.SOURCE_PORT;
  5429.   IF  BUFPTR.ACK = BIT_SET THEN    -- ACK BIT IS    ON.
  5430. -- SEND    A RESET    OF THE FORM <SEQ=SEG.ACK> <CTL=RST>
  5431.     RESERVE.SND_NXT := BUFPTR.ACK_NUM;
  5432.     SEND_A_RESET(RESERVE);
  5433.   ELSE
  5434.   -- SEND A RESET OF THE FORM <SEQ=0> <ACK=SEG.SEQ+SEG.LEN> <CTL=RST,ACK>
  5435.     RESERVE.SND_NXT := MODULAR_CONVERT(SIXTEEN_BITS(0));
  5436.     RESERVE.RCV_NXT := BUFPTR.SEQ_NUM + BYTE_COUNT - (BUFPTR.DATA_OFFSET *
  5437.                                     4);
  5438.                     -- BYTE_COUNT IS OF DATA AND HEADER
  5439.     SEND_A_RESET_AND_ACK(RESERVE);
  5440.   END IF;
  5441. END IF;
  5442. END SEG_ARRIVED_IN_CLOSED_STATE;
  5443. procedure SEG_ARRIVED_IN_LISTEN_STATE( BUFPTR : in out T_TCP_GLOBALS_DATA_STRUCTURES.
  5444.                                                 BUFFER_POINTER;
  5445.                        BYTE_COUNT : in SIXTEEN_BITS ; 
  5446.                                        SOURCE : in THIRTYTWO_BITS ) is
  5447. --   THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVE CONTROLLER WHEN A SEGMENT
  5448. --   HAS ARRIVED WITH THE TCB IN THE LISTEN STATE. IT PERFORMS THE NECESSARY
  5449. --   PROCESSING.
  5450. BUFFTYPE : SIXTEEN_BITS ;
  5451. Q_ITEM : STD_Q_ITEM;
  5452. BEGIN
  5453. IF BUFPTR.RST =    0 THEN -- RESET    BIT NOT    SET SO GO ON.
  5454.   IF BUFPTR.ACK    = BIT_SET THEN -- SEND A RESET
  5455.     RESERVE := LCN;
  5456.     RESERVE.SND_NXT := BUFPTR.ACK_NUM;
  5457.     SEND_A_RESET(RESERVE);
  5458.   ELSIF    BUFPTR.SYN = BIT_SET THEN
  5459.     IF LCN.SECURITY /= SECURITY OR    LCN.PRECEDENCE /= IP_TOS/2**5 THEN
  5460.       -- SET UP    THE TCB
  5461.       RESERVE := LCN;
  5462.       RESERVE.SND_NXT := BUFPTR.ACK_NUM;
  5463.       SEND_A_RESET(RESERVE);
  5464.     ELSE
  5465.       IF FOREIGN_SOCKET_UNSPECIFIED(LCN) THEN  -- FILL IN REMOTE HOST PARAMETERS
  5466.     LCN.FOREIGN_PORT := BUFPTR.SOURCE_PORT;
  5467.     LCN.DESTINATION_ADDRESS :=    SOURCE;
  5468.     -- DECODE THE NET AND HOST ADDRESSES AND PUT THEM IN THE TCB
  5469.         ADDRESS_DECODER(SOURCE);
  5470.       END IF;
  5471.       IF LCN.DESTINATION_ADDRESS =    SOURCE THEN -- IT MATCHES OUR
  5472.                              -- UNSPECIFIED    OR
  5473.                              -- SPECIFIED LISTEN.
  5474.         -- START THE CONNECTION TIMEOUT TIMER
  5475.         START_TIMER(LCN, TIMEOUT_TIMER);
  5476.     LCN.RCV_NXT := BUFPTR.SEQ_NUM + MODULAR_CONVERT(SIXTEEN_BITS(1));
  5477.     LCN.INIT_RCV_SEQ_NUM := BUFPTR.SEQ_NUM;
  5478.         LCN.SND_WND := BUFPTR.WINDOW;
  5479.         LCN.SND_WL1 := BUFPTR.SEQ_NUM;
  5480.         -- ACK NUMBER HERE IS MEANINGLESS. WE MIGHT ISS - 1 IN THERE.
  5481.     -- PUT ANY OTHER TEXT OR CONTROLS ON THE RECEIVE QUEUE FOR
  5482.     --  PROCESSING IN THE ESTABLISHED STATE.
  5483.     IF BYTE_COUNT > BUFPTR.DATA_OFFSET * 4   -- THEN DATA EXISTS.
  5484.            OR (BUFPTR.RST = BIT_SET) OR (BUFPTR.FIN = BIT_SET)   THEN
  5485.           -- RESET FIELDS.
  5486.       BUFPTR.ACK := 0;
  5487.           BUFPTR.SYN := 0;
  5488.       Q_ITEM := (NULL_BUFFER, BUFPTR, BYTE_COUNT);
  5489.       QUEUE_ADD(TCP_RECEIVED_SEGMENT_QUEUE, LCN, Q_ITEM); -- QUEUE IT
  5490.         END IF;
  5491.     -- GET INITIAL SEND SEQUENCE NUMBER (ISS)
  5492.         LCN.ISS := MODULAR_CONVERT(ISS);
  5493.     LCN.SND_NXT := LCN.ISS;
  5494. -- SET UP ACK SECTION OF WINDOWS.
  5495.         LCN.SND_WL2 := LCN.ISS;
  5496.     LCN.SND_UNA := LCN.SND_NXT;
  5497.     SEND_A_SYN_AND_ACK(LCN);
  5498.     --TEXT_IO.PUT_LINE("JUST SENT SEND_A_SYN_AND_ACK");
  5499.         LCN.STATE := SYN_RECEIVED;
  5500.       ELSE -- THE SEGMENT IS NOT THE ONE WE WANT SO IGNOR IT??
  5501.     TEXT_IO.PUT_LINE("TCP_ERROR 12 SEGARRIVE IN LISTEN STATE");
  5502.         TCP_ERROR(12);
  5503.       END IF;
  5504.     END    IF;
  5505.   END IF;
  5506. END IF;
  5507. -- RELEASE BUFFER
  5508. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5509. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5510. BUFFREE(GLOBAL_PACKED_BUFFER, BUFFTYPE);
  5511. EXCEPTION
  5512.  WHEN OTHERS =>
  5513.     PUT_LINE(" AN ERROR HAS OCCURRED IN THE LISTEN STATE");
  5514. end SEG_ARRIVED_IN_LISTEN_STATE;
  5515. procedure SEG_ARRIVED_IN_SYN_SENT_STATE( BUFPTR : in out 
  5516.                           T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5517.                      BYTE_COUNT : in SIXTEEN_BITS ) is
  5518.     --THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVED CONTROLLER WHEN A 
  5519.     --SEGMENT ARRIVES IN THE SYN_SENT STATE. IT PROCESSES ACCORDING TO 
  5520.     --THE SPEC.
  5521.     --
  5522.     -- PROCESSING :
  5523.     --
  5524.     --THIS PROCEDURE IS RESPONSIBLE FOR THE PROCESSING OF A SEGMENT IN 
  5525.     --THE SYN_SENT STATE ACCORDING TO THE TCP SPECIFICATION.
  5526. BUFFTYPE : SIXTEEN_BITS ;
  5527. UMESSAGE : USER_MESSAGE;
  5528. NULL_Q_ITEM : STD_Q_ITEM := (NULL, NULL_UNPACKED_BUFFER, 0);
  5529. Q_ITEM : STD_Q_ITEM;
  5530. SOCKET_PARAMS : TCB_PTR;
  5531. begin
  5532. if BUFPTR.ACK =    BIT_SET    and then ((BUFPTR.ACK_NUM <= LCN.ISS) OR 
  5533.      (BUFPTR.ACK_NUM > LCN.SND_NXT)) then
  5534.     LCN.SND_NXT :=    BUFPTR.ACK_NUM;
  5535. --    new_line;--for debug(JB 2/17/85)
  5536. --    put_line("SEND_A_RESET");
  5537. --    new_line;
  5538.     SEND_A_RESET(LCN);
  5539. elsif BUFPTR.RST = BIT_SET then
  5540. --    new_line;--for debug(JB 2/17/85)
  5541. --    put_line("BUFPTR.RST = BIT_SET");
  5542. --    new_line;
  5543.   if BUFPTR.ACK    = BIT_SET then
  5544.     -- TELL USER
  5545.     -- ERROR: CONNECTION RESET
  5546.     SOCKET_PARAMS := LCN;
  5547.     UMESSAGE := ( 6,
  5548.                   SOCKET_PARAMS);
  5549.     MESSAGE_FOR_USER(UMESSAGE);
  5550.     -- MAY HAVE    TO ZERO    TCB
  5551.     LCN.STATE := CLOSED;
  5552.     TCB_CLEAR(LCN);
  5553.   end if;
  5554. elsif LCN.SECURITY /= SECURITY then
  5555.   -- SEND A RESET
  5556.   if BUFPTR.ACK    = BIT_SET then 
  5557.   -- USE RESERVE TCB FOR VALUES OF RESET TO BE SENT
  5558.     RESERVE := LCN;
  5559.     RESERVE.SND_NXT := BUFPTR.ACK_NUM;
  5560.     SEND_A_RESET(RESERVE);
  5561.   else
  5562.     -- USE RESERVE TCB FOR VALUES OF RESET TO BE SENT
  5563.     RESERVE := LCN;
  5564.     RESERVE.SND_NXT := MODULAR_CONVERT(SIXTEEN_BITS(0));
  5565.     RESERVE.RCV_NXT := BUFPTR.SEQ_NUM + BYTE_COUNT - (BUFPTR.DATA_OFFSET *
  5566.                                     4);
  5567.     SEND_A_RESET_AND_ACK(RESERVE);
  5568.   end if;
  5569. elsif LCN.PRECEDENCE /= IP_TOS/2**5 then
  5570. --    new_line;--for debug(JB 2/17/85)
  5571. --    put_line("PRECEDENCE");
  5572. --    new_line;
  5573.   if BUFPTR.ACK    = BIT_SET then 
  5574.   -- USE RESERVE TCB FOR VALUES OF RESET TO BE SENT
  5575.     RESERVE := LCN;
  5576.     RESERVE.SND_NXT := BUFPTR.ACK_NUM;
  5577.     SEND_A_RESET(RESERVE);
  5578.   elsif    IP_TOS/2**5 > LCN.PRECEDENCE then 
  5579.   -- HERE WE COULD RAISE THE TCB PRECEDENCE BUT WE WILL NOT CURRENTLY
  5580.   -- USE RESERVE TCB FOR VALUES OF RESET TO BE SENT
  5581.     RESERVE := LCN;
  5582.     RESERVE.SND_NXT := MODULAR_CONVERT(SIXTEEN_BITS(0));
  5583.     RESERVE.RCV_NXT := BUFPTR.SEQ_NUM + BYTE_COUNT - (BUFPTR.DATA_OFFSET *
  5584.                                     4);
  5585.     SEND_A_RESET_AND_ACK(RESERVE);
  5586.   end if;
  5587. elsif BUFPTR.SYN = BIT_SET then
  5588. --    new_line;--for debug(JB 2/17/85)
  5589. --    put_line("SYN = BIT_SET");
  5590. --    new_line;
  5591.   LCN.RCV_NXT := BUFPTR.SEQ_NUM + MODULAR_CONVERT(SIXTEEN_BITS(1));
  5592.   LCN.INIT_RCV_SEQ_NUM := BUFPTR.SEQ_NUM;
  5593. -- SET UP OUR SEND WINDOW MECHANISM IN THE TCB.
  5594.   LCN.SND_WND := BUFPTR.WINDOW;
  5595.   LCN.SND_WL1 := BUFPTR.SEQ_NUM;
  5596.   LCN.SND_WL2 := LCN.ISS;
  5597.   if BUFPTR.ACK    = BIT_SET then
  5598.    new_line;
  5599.    put_line("delete from retrans queue");
  5600.    new_line;
  5601.    LCN.SND_UNA := BUFPTR.ACK_NUM;
  5602.    -- REMOVE ALL ACKED SEGMENTS FROM THE RETRANSMISSION QUEUE
  5603.    DELETE_FROM_RETRANS_QUEUE(LCN, LCN.SND_UNA);
  5604.    -- CHANGE THE ACK NUMBER OF LAST SEG USED TO UPDATE THE WINDOW.
  5605.    LCN.SND_WL2 := BUFPTR.ACK_NUM;
  5606.   end if;
  5607.   if LCN.SND_UNA >    LCN.ISS then
  5608.     SEND_A_PIGGYBACKED_ACK(LCN);
  5609.     LCN.STATE := ESTABLISHED;
  5610.     -- TELL THE USER.
  5611.     SOCKET_PARAMS := LCN;
  5612.     UMESSAGE := ( 23,
  5613.                   SOCKET_PARAMS);
  5614.     MESSAGE_FOR_USER(UMESSAGE);
  5615.     -- HERE WE PROCESS ANY OTHER TEXT AND CONTROLS
  5616.     ENTER_ESTABLISHED_STATE_PROCESSING(LCN, BUFPTR);
  5617.   ELSE
  5618.     --    QUEUE ANY OTHER    TEXT OR    CONTROLS FOR LATER PROCESSING
  5619.     new_line;--for debug(JB 2/17/85)
  5620.     put_line("queue any other text or controls");
  5621.     new_line;
  5622.     IF BYTE_COUNT > BUFPTR.DATA_OFFSET * 4   -- THEN TEXT EXISTS    
  5623.        OR (BUFPTR.FIN = BIT_SET)   THEN
  5624.       -- CLEAR PREVIOUSLY PROCESSED FLAGS
  5625.       BUFPTR.ACK := 0;
  5626.       BUFPTR.SYN := 0;
  5627.       Q_ITEM := (NULL_BUFFER, BUFPTR, BYTE_COUNT);
  5628.       QUEUE_ADD(TCP_RECEIVED_SEGMENT_QUEUE, LCN, Q_ITEM);
  5629.     END IF;
  5630.     -- SEND A SYN, ACK
  5631.     -- THE SEQUENCE NUMBER MUST    BE ISS.
  5632.     LCN.SND_NXT :=    LCN.ISS;
  5633.     LCN.STATE := SYN_RECEIVED;
  5634.     SEND_A_SYN_AND_ACK(LCN);
  5635.   END IF;
  5636. end if;
  5637. -- RELEASE BUFFER
  5638. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5639. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5640. BUFFREE(GLOBAL_PACKED_BUFFER, BUFFTYPE);
  5641. EXCEPTION
  5642. WHEN CONSTRAINT_ERROR =>
  5643.  PUT_LINE("CONSTRAINT ERROR IN SYN SENT STATE");  
  5644. WHEN OTHERS =>
  5645.  PUT_LINE("ERROR IN SYN SENT STATE");
  5646. end SEG_ARRIVED_IN_SYN_SENT_STATE;
  5647. procedure SEG_ARRIVED_IN_SYN_RECEIVED_STATE( BUFPTR : in out 
  5648.                                    T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5649.                              BYTE_COUNT : in SIXTEEN_BITS ) is
  5650. --   THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVE PROCESSOR WHEN A SEGMENT
  5651. --   ARRIVES IN THE SYN RECEIVED STATE.
  5652. -- PROCESSING :
  5653. --
  5654. --   THIS PROCEDURE DOES ALL THE NECESSARY PROCESSING FOR AN ARRIVED SEGMENT
  5655. --   IN THE SYN RECEIVED STATE ACCORDING TO THE TCP SPECIFICATION.
  5656. --
  5657. UMESSAGE : USER_MESSAGE;
  5658. NULL_Q_ITEM : STD_Q_ITEM := (NULL, NULL_UNPACKED_BUFFER, 0);
  5659. SOCKET_PARAMS : TCB_PTR;
  5660. BEGIN
  5661. -- THE CHECKSUM AND THE SEQUENCE NUMBER HAVE ALREADY BEEN CHECKED.
  5662. IF BUFPTR.RST = BIT_SET THEN
  5663.   IF LCN.ACTIVE_PASSIVE = T_TCP_GLOBALS_DATA_STRUCTURES.PASSIVE THEN
  5664.   -- RETURN TO THE LISTEN STATE
  5665.     LCN.STATE := T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN;
  5666.   ELSE
  5667.     -- TELL USER
  5668.     -- CONNECTION REFUSED
  5669.     SOCKET_PARAMS := T_TCP_GLOBALS_DATA_STRUCTURES.LCN;
  5670.     UMESSAGE := ( 17, 
  5671.                   SOCKET_PARAMS);
  5672.     MESSAGE_FOR_USER(UMESSAGE);
  5673.     LCN.STATE := CLOSED;
  5674.     QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  5675.     -- THERE IS NO SEND Q ON THIS LEVEL. CLEAR_SEND_QUEUE(LCN);
  5676.   END IF;
  5677.   QUEUE_CLEAR(TCP_RECEIVED_SEGMENT_QUEUE, LCN);
  5678.   QUEUE_CLEAR(TCP_RETRANSMIT_QUEUE, LCN);
  5679. ELSIF LCN.SECURITY /= SECURITY OR LCN.PRECEDENCE /= IP_TOS/2**5 THEN
  5680. -- SEND A RESET
  5681.    SEND_A_RESET(LCN);
  5682. ELSIF BUFPTR.SYN = BIT_SET THEN
  5683.    BAD_SYN_HANDLER(LCN, BUFPTR);
  5684. ELSIF BUFPTR.ACK = BIT_SET THEN
  5685.    IF (LCN.SND_UNA > BUFPTR.ACK_NUM) OR
  5686.        (BUFPTR.ACK_NUM > LCN.SND_NXT)    THEN
  5687.      -- SEND A RESET
  5688.      RESERVE.SND_NXT := BUFPTR.ACK_NUM;
  5689.      SEND_A_RESET(RESERVE);
  5690.    ELSE
  5691.      LCN.STATE := ESTABLISHED;
  5692.      -- TELL THE USER CONNECTION OPEN.
  5693.      SOCKET_PARAMS := LCN;
  5694.      UMESSAGE := ( 23, 
  5695.                    SOCKET_PARAMS);
  5696.      MESSAGE_FOR_USER(UMESSAGE);
  5697.      LCN.SND_UNA := BUFPTR.ACK_NUM;  -- UPDATE UNACKNOWLEDGED NUMBER
  5698.      -- REMOVE ACKNOWLEDGED DATA FROM RETRANS QUEUE.
  5699.      DELETE_FROM_RETRANS_QUEUE(LCN, LCN.SND_UNA);
  5700.      -- DO NECESSARY ESTABLISHED STATE PROCESSING 
  5701.      ENTER_ESTABLISHED_STATE_PROCESSING(LCN, BUFPTR);
  5702.    END IF;
  5703. END IF;
  5704. -- RELEASE BUFFER
  5705. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5706. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5707. BUFFREE(GLOBAL_PACKED_BUFFER, BUFFTYPE);
  5708. END SEG_ARRIVED_IN_SYN_RECEIVED_STATE;
  5709. PROCEDURE SEG_ARRIVED_IN_ESTABLISHED_STATE( BUFPTR : in out 
  5710.                                   T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5711.                             BYTE_COUNT : in SIXTEEN_BITS ) is
  5712. -- INITIAL DESCRIPTION :
  5713. -- 
  5714. --   THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVE PROCESSOR WHEN A SEGMENT
  5715. --   ARRIVES IN THE ESTABLISHED STATE. IT WILL DO ALL THE NECESSARY PROCESSING
  5716. --   AS SPECIFIED IN THE SPEC.
  5717. -- PROCESSING :
  5718. --
  5719. --   THIS PROCEDURE DOES ALL THE NECESSARY PROCESSING FOR THE ESTABLISHED STATE
  5720. --   AS SPECIFIED IN THE TCP SPEC. IT THEN RELEASES THE BUFFER THE SEGMENT IS
  5721. --   IN. IT WILL QUEUE ANY DATA FOR THE USER TO BE ACCEPTED AT THE USERS
  5722. --   CONVENIENCE.
  5723. BUFFTYPE : SIXTEEN_BITS ;
  5724. RESULT : T_TCP_ARRIVES_1.RES;
  5725. UMESSAGE : USER_MESSAGE;
  5726. SOCKET_PARAMS : TCB_PTR;
  5727. begin
  5728. IF BUFPTR.RST = BIT_SET THEN
  5729.   PROCESS_RESET_IN_DATA_ACCEPTING_STATES(LCN);
  5730. ELSIF LCN.SECURITY /= SECURITY OR LCN.PRECEDENCE /= IP_TOS/2**5 THEN
  5731. -- CLEAR THE QUEUES
  5732.   QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  5733. -- THERE IS NO SEND QUEUE ON THIS LEVEL.  CLEAR_SEND_QUEUE(LCN);
  5734.   QUEUE_CLEAR(TCP_RETRANSMIT_QUEUE, LCN);
  5735.   QUEUE_CLEAR(TCP_RECEIVED_SEGMENT_QUEUE, LCN);
  5736.   QUEUE_CLEAR(TRANSMIT_QUEUE, LCN);
  5737.   QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN);
  5738.   -- TELL USER
  5739.   -- CONNECTION RESET
  5740.   SOCKET_PARAMS := LCN;
  5741.   UMESSAGE := ( 16,
  5742.                 SOCKET_PARAMS);
  5743.   MESSAGE_FOR_USER(UMESSAGE);
  5744.   LCN.STATE := CLOSED;
  5745.   -- MAY HAVE TO CLEAR THE TCB HERE
  5746.   TCB_CLEAR(LCN);
  5747. ELSIF BUFPTR.SYN = BIT_SET THEN
  5748.   BAD_SYN_HANDLER(LCN, BUFPTR);
  5749. ELSIF BUFPTR.ACK = BIT_SET THEN
  5750.   PROCESS_COMMON_ACK(LCN, BUFPTR, RESULT);
  5751.   IF RESULT = T_TCP_ARRIVES_1.GOOD THEN
  5752.     PROCESS_URGENT_FLAG(LCN, BUFPTR);
  5753.     PROCESS_SEGMENT_TEXT(LCN, BUFPTR);
  5754.     FIN_CHECK_FOR_ESTAB_OR_SYN_RECEIVED_STATES(LCN, BUFPTR);
  5755.   END IF;
  5756. ELSE
  5757.   TCP_ERROR(14); -- NO ACK BIT SET
  5758. END IF;
  5759. -- RELEASE BUFFER
  5760. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5761. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5762. BUFFREE(GLOBAL_PACKED_BUFFER, BUFFTYPE);
  5763. EXCEPTION
  5764. WHEN OTHERS =>
  5765.  PUT_LINE("ERROR IN ESTABLISHED STATE ARRIVE PROCESSING!");
  5766.  RAISE;  
  5767. END SEG_ARRIVED_IN_ESTABLISHED_STATE;
  5768. PROCEDURE SEG_ARRIVED_IN_FIN_WAIT_1_STATE( BUFPTR : in out 
  5769.                                   T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5770.                            BYTE_COUNT : in SIXTEEN_BITS ) is
  5771. -- INITIAL DESCRIPTION :
  5772. -- 
  5773. --   THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVED PROCESSOR TO DO ALL
  5774. --   NECESSARY PROCESSING FOR A CONNECTION IN THE FIN-WAIT-1 STATE WHEN
  5775. --   A SEGMENT ARRIVES.
  5776. -- PROCESSING :
  5777. --
  5778. --   THIS PROCEDURE WILL DO ALL NECESSARY PROCESSING FOR A SEGMENT WHICH
  5779. --   ARRIVES IN THE FIN-WAIT-1 STATE (ACCORDING TO THE SPEC). IT WILL ALSO
  5780. --   CONTINUE THE PROCESSING IN THE FIN-WAIT-2 STATE WHEN AN ACK FOR THE
  5781. --   FIN ARRIVES.
  5782. RESULT : T_TCP_ARRIVES_1.RES;
  5783. BEGIN
  5784. IF BUFPTR.RST = BIT_SET THEN
  5785.   PROCESS_RESET_IN_DATA_ACCEPTING_STATES(LCN);
  5786. ELSIF BUFPTR.SYN = BIT_SET THEN
  5787.   BAD_SYN_HANDLER(LCN, BUFPTR);
  5788. ELSIF BUFPTR.ACK = BIT_SET THEN
  5789.   PROCESS_COMMON_ACK(LCN, BUFPTR, RESULT);
  5790.   IF RESULT = T_TCP_ARRIVES_1.GOOD THEN
  5791.     IF QUEUE_EMPTY(TCP_RETRANSMIT_QUEUE, LCN) THEN -- THE FIN IS ACKNOWLEDGED
  5792.       LCN.STATE := FIN_WAIT_2;
  5793.     -- *NOW DO THE SAME PROCESSING AS THE FIN-WAIT-2 STATE.*
  5794.       PROCESS_URGENT_FLAG(LCN, BUFPTR);
  5795.       PROCESS_SEGMENT_TEXT(LCN, BUFPTR);
  5796.       IF BUFPTR.FIN = BIT_SET THEN
  5797.         PROCESS_A_FIN(LCN, BUFPTR);
  5798.         LCN.STATE := TIME_WAIT;
  5799.         QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN); 
  5800.                                                -- DELETE UNEATEN DATA
  5801.         --START THE TIME-WAIT TIMER AND TURN OFF OTHER TIMERS
  5802.     START_TIMER(LCN, TIME_WAIT_TIMER);
  5803.         --TEXT_IO.NEW_LINE;
  5804.         --TEXT_IO.PUT_LINE("JUST SET TIMER FOR CONNECTION CLOSE");
  5805.       END IF;
  5806.     ELSE -- FIN NOT ACKED SO CONTINUE ON OUR WAY.
  5807.       PROCESS_URGENT_FLAG(LCN, BUFPTR);
  5808.       PROCESS_SEGMENT_TEXT(LCN, BUFPTR);
  5809.       IF BUFPTR.FIN = BIT_SET THEN
  5810.         PROCESS_A_FIN(LCN, BUFPTR);
  5811.         LCN.STATE := CLOSING;
  5812.         QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN); 
  5813.         -- GET RID OF UNEATEN DATA
  5814.       END IF;
  5815.     END IF;
  5816.   END IF;
  5817. END IF;
  5818. -- RELEASE BUFFER
  5819. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5820. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5821. BUFFREE(GLOBAL_PACKED_BUFFER, BUFFTYPE);
  5822. end SEG_ARRIVED_IN_FIN_WAIT_1_STATE;
  5823. procedure SEG_ARRIVED_IN_FIN_WAIT_2_STATE( BUFPTR : in out 
  5824.                                   T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5825.                            BYTE_COUNT : in SIXTEEN_BITS ) is
  5826. -- INITIAL DESCRIPTION :
  5827. -- 
  5828. --   THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVE CONTROLLER TO PROCESS A
  5829. --   SEGMENT WHEN THE CONNECTION IS IN THE FIN_WAIT_2 STATE.
  5830. -- PROCESSING :
  5831. --
  5832. --   THIS PROCEDURE DOES ALL THE PROCESSING ACCORDING TO THE SPEC FOR ARRIVED
  5833. --   SEGMENTS IN THE FIN-WAIT-2 STATE.
  5834. UMESSAGE : USER_MESSAGE;
  5835. RESULT : T_TCP_ARRIVES_1.RES;
  5836. begin
  5837. IF BUFPTR.RST = BIT_SET THEN
  5838.   PROCESS_RESET_IN_DATA_ACCEPTING_STATES(LCN);
  5839. ELSIF BUFPTR.SYN = BIT_SET THEN
  5840.   BAD_SYN_HANDLER(LCN, BUFPTR);
  5841. ELSIF BUFPTR.ACK = BIT_SET THEN
  5842.   PROCESS_COMMON_ACK(LCN, BUFPTR, RESULT);
  5843.   IF RESULT = T_TCP_ARRIVES_1.GOOD THEN
  5844.     PROCESS_URGENT_FLAG(LCN, BUFPTR);
  5845.     PROCESS_SEGMENT_TEXT(LCN, BUFPTR);
  5846.     IF BUFPTR.FIN = BIT_SET THEN
  5847.       PROCESS_A_FIN(LCN, BUFPTR); -- NOTE FIN IMPLIES PUSH
  5848.       LCN.STATE := TIME_WAIT;
  5849.       QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN); 
  5850.       -- DELETE UNEATEN DATA
  5851.       --START TIME_WAIT TIMER AND TURN OFF THE OTHER TIMERS
  5852.       START_TIMER(LCN, TIME_WAIT_TIMER);
  5853.     END IF;
  5854.   END IF;
  5855. END IF;
  5856. -- RELEASE BUFFER
  5857. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5858. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5859. BUFFREE(GLOBAL_PACKED_BUFFER, BUFFTYPE);
  5860. end SEG_ARRIVED_IN_FIN_WAIT_2_STATE;
  5861. procedure SEG_ARRIVED_IN_CLOSE_WAIT_STATE( BUFPTR : in out 
  5862.                                  T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5863.                            BYTE_COUNT : in SIXTEEN_BITS ) is
  5864. -- INITIAL DESCRIPTION :
  5865. -- 
  5866. --   THIS PROCEDURE IS CALLED BY THE SEGARIV PROCESSOR TO DO THE REQUIRED
  5867. --   PROCESSING FOR AN ARRIVED SEGMENT IN THIS STATE.
  5868. -- PROCESSING :
  5869. --
  5870. --   THIS PROCEDURE PERFORMS ALL NECESSARY PROCESSING FOR THE CLOSE_WAIT STATE
  5871. --   UPON SEGMENT ARRIVAL (ACCORDING TO THE TCP SPEC).
  5872. RESULT : T_TCP_ARRIVES_1.RES;
  5873. begin
  5874. IF BUFPTR.RST = BIT_SET THEN
  5875.   PROCESS_RESET_IN_DATA_ACCEPTING_STATES(LCN);
  5876. ELSIF BUFPTR.SYN = BIT_SET THEN
  5877.   BAD_SYN_HANDLER(LCN, BUFPTR);
  5878. ELSIF BUFPTR.ACK = BIT_SET THEN
  5879.   PROCESS_COMMON_ACK(LCN, BUFPTR, RESULT);
  5880.   -- WE WILL IGNORE ANY URGENT BITS SET
  5881.   -- WE WILL (AS PER THE SPEC) IGNORE ANY TEXT
  5882.   -- WE WILL ALSO NOT WORRY IF THIS IS A REDUNDANT FIN.
  5883. END IF;
  5884. -- RELEASE BUFFER
  5885. BUFFREE(GLOBAL_PACKED_BUFFER, BUFFTYPE);
  5886. end SEG_ARRIVED_IN_CLOSE_WAIT_STATE;
  5887. procedure SEG_ARRIVED_IN_CLOSING_STATE( BUFPTR : in out 
  5888.                            T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5889.                          BYTE_COUNT : in SIXTEEN_BITS ) is
  5890. -- INITIAL DESCRIPTION :
  5891. -- 
  5892. --   THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVE PROCESSOR TO PROCESS AN
  5893. --   ARRIVED SEGMENT IN THE CLOSING STATE.
  5894. -- PROCESSING :
  5895. --
  5896. --   THIS PROCEDURE WILL DO ALL THE PROCESSING FOR AN ARRIVED SEGMENT,
  5897. --   ACCORDING TO THE SPEC, WHEN THE CONNECTION IS IN THE CLOSING STATE.
  5898. RESULT : T_TCP_ARRIVES_1.RES;
  5899. begin
  5900. IF BUFPTR.RST = BIT_SET THEN
  5901.   LCN.STATE := CLOSED;
  5902.   -- HERE WE MAY HAVE TO CLEAR THE TCB.
  5903.   TCB_CLEAR(LCN);
  5904. ELSIF BUFPTR.SYN = BIT_SET THEN
  5905.   BAD_SYN_HANDLER(LCN, BUFPTR);
  5906. ELSIF BUFPTR.ACK = BIT_SET THEN
  5907.   PROCESS_COMMON_ACK(LCN, BUFPTR, RESULT);
  5908.   IF (RESULT = T_TCP_ARRIVES_1.GOOD) AND 
  5909.   QUEUE_EMPTY(TCP_RETRANSMIT_QUEUE, LCN) THEN 
  5910.   -- OUR FIN HAS BEEN ACKNOWLEDGED
  5911.     LCN.STATE := TIME_WAIT;
  5912.     QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN); -- DELETE UNEATEN DATA
  5913.     -- STOP OTHER TIMERS AND START TIME_WAIT TIMER
  5914.     START_TIMER(LCN, TIME_WAIT_TIMER);
  5915.   END IF;
  5916. -- ALL OTHER CONTROL BITS CAN BE IGNORED.
  5917. -- TEXT ALSO.
  5918. END IF;
  5919. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5920. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5921. BUFFREE(GLOBAL_PACKED_BUFFER, 0);
  5922. END SEG_ARRIVED_IN_CLOSING_STATE;
  5923. PROCEDURE SEG_ARRIVED_IN_LAST_ACK_STATE( BUFPTR : in out 
  5924.                              T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5925.                          BYTE_COUNT : in SIXTEEN_BITS ) is
  5926. -- INITIAL DESCRIPTION :
  5927. -- 
  5928. --   THIS PROCEDURE IS CALLED WHEN A SEGMENT ARRIVES WITH THE CONNECTION IN THE
  5929. --   LAST-ACK STATE.
  5930. -- PROCESSING :
  5931. --
  5932. --   THIS PROCEDURE DOES ALL THE PROCESSING FOR A SEGMENT THAT ARRIVES WITH A
  5933. --   CONNECTION IN THE LAST-ACK STATE. IF THE FIN IS ACKED THE CONNECTION IS
  5934. --   CLOSED.
  5935. UMESSAGE : USER_MESSAGE;
  5936. SOCKET_PARAMS : TCB_PTR;
  5937. BEGIN
  5938. IF BUFPTR.RST = BIT_SET THEN
  5939.   LCN.STATE := CLOSED;
  5940.   -- THE TCB MAY HAVE TO BE CLEARED HERE.
  5941.   TCB_CLEAR(LCN);
  5942. ELSIF BUFPTR.SYN = BIT_SET THEN
  5943.   BAD_SYN_HANDLER(LCN, BUFPTR);
  5944. ELSIF BUFPTR.ACK = BIT_SET THEN
  5945.   -- DOES THIS ACK OUR FIN?
  5946.   IF BUFPTR.ACK_NUM >= LCN.SND_NXT - 1 THEN
  5947.     -- TAKE SEGMENT(S) OFF THE RETRANSMISSION QUEUE.
  5948.     DELETE_FROM_RETRANS_QUEUE(LCN, BUFPTR.ACK_NUM);
  5949.     LCN.STATE := CLOSED;
  5950.     -- HERE WE MAY HAVE TO CLEAR THE TCB
  5951.     SOCKET_PARAMS := LCN;
  5952.     UMESSAGE := ( 18,
  5953.                   SOCKET_PARAMS );
  5954.     MESSAGE_FOR_USER( UMESSAGE );
  5955.     TCB_CLEAR(LCN);
  5956.     TCB_FREE(LCN);
  5957.   ELSE
  5958.     -- THIS IS REALLY AN ERROR.
  5959.     TCP_ERROR(5);
  5960.   END IF;
  5961. END IF;
  5962. -- WE WILL IGNORE AS PER THE SPEC. ANYTHING ELSE.
  5963. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5964. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5965. BUFFREE(GLOBAL_PACKED_BUFFER, 0);
  5966. END SEG_ARRIVED_IN_LAST_ACK_STATE;
  5967. PROCEDURE SEG_ARRIVED_IN_TIME_WAIT_STATE( BUFPTR : in out 
  5968.                                 T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  5969.                           BYTE_COUNT : in SIXTEEN_BITS ) IS
  5970. -- INITIAL DESCRIPTION :
  5971. -- 
  5972. --   THIS PROCEDURE IS CALLED BY THE SEGMENT ARRIVE PROCESSOR TO PROCESS A
  5973. --   SEGMENT IN THE TIME-WAIT STATE.
  5974. -- PROCESSING :
  5975. --
  5976. --   THIS PROCEDURE WILL ACCEPT A RESENT FIN, ACK IT AGAIN AND RESTART THE
  5977. --   TIME-WAIT TIMER.
  5978. BEGIN
  5979. IF BUFPTR.RST = BIT_SET THEN
  5980.   LCN.STATE := CLOSED;
  5981.   -- THE TCB MAY HAVE TO BE CLEARED HERE.
  5982.   TCB_CLEAR(LCN);
  5983. ELSIF BUFPTR.SYN = BIT_SET THEN
  5984.   BAD_SYN_HANDLER(LCN, BUFPTR);
  5985. ELSIF BUFPTR.ACK = BIT_SET THEN
  5986.   -- THIS SHOULD BE THE ACK WITH THE RETRANSMITTED FIN
  5987.   IF BUFPTR.FIN = BIT_SET THEN
  5988.     -- ACK THE FIN
  5989.     LCN.RCV_NXT := LCN.RCV_NXT + MODULAR_CONVERT(SIXTEEN_BITS(1)); --COVER THE FIN.
  5990.     SEND_A_PIGGYBACKED_ACK(LCN);
  5991.     -- RESTART THE 2 MSL (MAX SEG. LIFETIME TIMER)
  5992.     START_TIMER(LCN, TIME_WAIT_TIMER);
  5993.   END IF;
  5994. END IF;
  5995. -- WE WILL IGNORE AS PER THE SPEC. ANYTHING ELSE.
  5996. GLOBAL_PACKED_BUFFER.IN_USE := FALSE;
  5997. GLOBAL_PACKED_BUFFER.STATUS := NONE;
  5998. BUFFREE(GLOBAL_PACKED_BUFFER, 0);
  5999. end SEG_ARRIVED_IN_TIME_WAIT_STATE;
  6000. end TCP_SEG_ARRIVE;
  6001. --::::::::::::::
  6002. --subcontr1.txt
  6003. --::::::::::::::
  6004. -----------------------------------------------------------------------
  6005. --
  6006. --         DoD Protocols    NA-00008-200       80-01191-100(-)
  6007. --         E-Systems, Inc.  August 07, 1985
  6008. --
  6009. --         subcontr1.txt       Author : Jim Baldo
  6010. --
  6011. -----------------------------------------------------------------------
  6012. with TEXT_IO;                   use TEXT_IO;
  6013. with SUBNET_CALLS;              use SUBNET_CALLS;
  6014. with WITH_IP_COMMUNICATE;       use WITH_IP_COMMUNICATE;
  6015. with BUFFER_DATA;               use BUFFER_DATA;
  6016.                 package SUBNET_CONTROLLER_TASK is
  6017.                 
  6018. procedure SUBNET_CONTROLLER;
  6019. end SUBNET_CONTROLLER_TASK;
  6020.                 package body SUBNET_CONTROLLER_TASK is
  6021.                 
  6022. procedure SUBNET_CONTROLLER is
  6023. DATAGRAM : PACKED_BUFFER_PTR := null;
  6024. begin
  6025.  SNP.SUBNET_GET; --Check Ethernet Receive
  6026.  SNP.DELIVER( DATAGRAM );
  6027.  if DATAGRAM /= null then
  6028.   --text_io.put_line("datagram /= null");
  6029.   SUBNET_TO_IP( DATAGRAM );
  6030.   BUFFREE( DATAGRAM, 0 );
  6031.  end if;
  6032. exception
  6033.  when CONSTRAINT_ERROR =>
  6034.   PUT_LINE("CONSTRAINT_ERROR IN SUBNET_CONTROLLER");
  6035.  when others =>
  6036.   PUT_LINE("UNKNOWN ERROR IN SUBNET_CONTROLLER");
  6037. end SUBNET_CONTROLLER;
  6038. end SUBNET_CONTROLLER_TASK;
  6039. --::::::::::::::
  6040. --subnet.txt
  6041. --::::::::::::::
  6042. -----------------------------------------------------------------------
  6043. --
  6044. --         DoD Protocols    NA-00008-200       80-01192-100(-)
  6045. --         E-Systems, Inc.  August 07, 1985
  6046. --
  6047. --         subnet.txt       Author : Jim Baldo
  6048. --
  6049. -----------------------------------------------------------------------
  6050.  
  6051. with BUFFER_DATA ;                   use BUFFER_DATA ;
  6052. with IP_GLOBALS ;                    use IP_GLOBALS ;
  6053.                    
  6054.                    package SUBNET_CALLS is
  6055.          
  6056.          --------------------------------------------------
  6057.          --This implementation version is for use with   --
  6058.          --Telesoft Ada for WICAT Machine                --
  6059.          --------------------------------------------------
  6060. ------------------------------------------------------------------------------
  6061. --This package contains procedure calls and data structures necessary for   --
  6062. --the Internet Protocol Group and the Subnet Protocol Group to communicate. --
  6063. ------------------------------------------------------------------------------
  6064.  PACKAGE SNP is
  6065.  
  6066.  procedure SUBNET_GET ;
  6067.  
  6068.  procedure SEND (DATAGRAM            : in out PACKED_BUFFER_PTR ;
  6069.                  LOCAL_DESTINATION   : in    LOCAL_ADDRESS_TYPE ;
  6070.                  PRECEDENCE          : in    PRECEDENCE_TYPE ;
  6071.                  RELIABILITY         : in    RELIABILITY_TYPE ;
  6072.                  DELAY_IP            : in    DELAY_TYPE ;
  6073.                  THROUGHPUT          : in    THROUGHPUT_TYPE ;
  6074.                  LENGTH              : in    DATAGRAM_LENGTH ) ;
  6075.  
  6076.  --This entry sends a datagram to the subnet for transmit.
  6077.         --Fully compatible with MIL-STD 1777.
  6078.         
  6079.  procedure DELIVER (DATAGRAM : out PACKED_BUFFER_PTR) ;
  6080.       
  6081.       --This entry requests for a datagram from the subnet. If
  6082.  --the pointer is null, the subnet queue is empty. Fully compatible
  6083.  --with MIL-STD 1777.
  6084.  
  6085.  procedure SEND_TO_IP (DATAGRAM : in out PACKED_BUFFER_PTR) ;
  6086.  
  6087.  end SNP ;
  6088. end SUBNET_CALLS ;
  6089. with system ;                   use system;
  6090. with unchecked_conversion ;
  6091. with Text_io ;                  use Text_io, integer_io, long_integer_io ;
  6092. with system ;                   use system ;
  6093. with unchecked_conversion ;
  6094. with mover;                     use mover ;
  6095. package body SUBNET_CALLS is
  6096. -------------------------------------------------
  6097. --This implementation version is for use with  --
  6098. -- WICAT                                       --
  6099. -------------------------------------------------
  6100. --
  6101. --          13-JUN-*% : (VCB) Port to WICAT under ROS with TCP/IP
  6102. --************************************************************************
  6103. --------------------------------------------------------------------------
  6104. --------------------------------------------------------------------------
  6105. --  Ethernet Packet Format :
  6106. --
  6107. --          Field                     Number of Bytes
  6108. --
  6109. --          PREAMBLE                       8
  6110. --          DESTINATION ADDRESS            6
  6111. --          SOURCE ADDRESS                 6
  6112. --          PROTOCOL TYPE                  2
  6113. --          DATA                       46 TO 1500
  6114. --          FRAME CHECK SEQUENCE           4
  6115. --               Note :
  6116. --                  The first two bytes of the data field are
  6117. --                   used to store the data LENGTH parameter.
  6118. --
  6119. --   Note :   Inter-frame spacing is 9.6 microseconds, minimum
  6120. --
  6121. --------------------------------------------------------------------------
  6122. --
  6123. -- subnet driver routines
  6124. --
  6125. --------------------------------------------------------------------------
  6126. type net_address is array (0..5) of system.byte ;
  6127. type packet_type is array (0..2047) of system.byte ;
  6128.   type big_packet is array (0..4095) of system.byte ;
  6129.   buffer_busy   : exception ;
  6130.   Net_Error     : exception ;
  6131.   
  6132. function addr is new unchecked_conversion (thirtytwo_bits, system.address) ;
  6133. function long is new unchecked_conversion (system.address, thirtytwo_bits) ;
  6134. function bol is new unchecked_conversion (sixteen_bits, boolean) ;
  6135. function int is new unchecked_conversion (boolean, sixteen_bits) ;
  6136. --
  6137. --  3Com board address...
  6138. --
  6139. base    : constant thirtytwo_bits := 16#E60000# ;  -- base address of 3-Com
  6140. csr     : sixteen_bits ;    for csr     use at addr (base+ 16#0000#) ;
  6141. back    : sixteen_bits ;    for back    use at addr (base+ 16#0002#) ;
  6142. SA_rom  : net_address ; for SA_rom      use at addr (base+ 16#0400#) ;
  6143. SA_ram  : net_address ; for SA_ram      use at addr (base+ 16#0600#) ;
  6144. TX_buf  : packet_type ; for TX_buf      use at addr (base+ 16#0800#) ;
  6145. RX_bufs : big_packet  ;
  6146.       for RX_bufs use at addr (base+ 16#1000#) ;
  6147. A_offset: constant sixteen_bits := 16#0000# ;
  6148. B_offset: constant sixteen_bits := 16#0800# ;
  6149. PA      : constant sixteen_bits := 16#0008# ;
  6150. Jinten  : constant sixteen_bits := 16#0010# ;
  6151. TINTEN  : constant sixteen_bits := 16#0020# ;
  6152. AINTEN  : constant sixteen_bits := 16#0040# ;
  6153. BINTEN  : constant sixteen_bits := 16#0080# ;
  6154. RESET   : constant sixteen_bits := 16#0100# ;
  6155. SPARE   : constant sixteen_bits := 16#0200# ;
  6156. RBBA    : constant sixteen_bits := 16#0400# ;
  6157. AMSW    : constant sixteen_bits := 16#0800# ;
  6158. JAM     : constant sixteen_bits := 16#1000# ;
  6159. TBSW    : constant sixteen_bits := 16#2000# ;
  6160. ABSW    : constant sixteen_bits := 16#4000# ;
  6161. BBSW    : constant sixteen_bits := sixteen_bits (16#8000#) ;
  6162. CODE : constant sixteen_bits := PA+AMSW+ABSW+BBSW ;
  6163. package body SNP is
  6164.  procedure SUBNET_GET is
  6165.  
  6166.  begin
  6167.   null;
  6168.  end SUBNET_GET ;
  6169.  
  6170.  procedure SEND (DATAGRAM            : in out PACKED_BUFFER_PTR ;
  6171.                  LOCAL_DESTINATION   : in    LOCAL_ADDRESS_TYPE ;
  6172.                  PRECEDENCE          : in    PRECEDENCE_TYPE ;
  6173.                  RELIABILITY         : in    RELIABILITY_TYPE ;
  6174.                  DELAY_IP            : in    DELAY_TYPE ;
  6175.                  THROUGHPUT          : in    THROUGHPUT_TYPE ;
  6176.                  LENGTH              : in    DATAGRAM_LENGTH ) is
  6177.            
  6178.   begin
  6179.    null ;
  6180.   end SEND ;
  6181.                  
  6182.  procedure DELIVER (DATAGRAM : out PACKED_BUFFER_PTR) is
  6183.  
  6184.  begin
  6185.   null;
  6186.  end DELIVER ;
  6187.  
  6188.  procedure SEND_TO_IP (DATAGRAM : in out PACKED_BUFFER_PTR) is
  6189.  
  6190.  begin
  6191.   null;
  6192.  end SEND_TO_IP ;
  6193.  
  6194.  end SNP;
  6195.  
  6196.  end SUBNET_CALLS ;
  6197. --::::::::::::::
  6198. --subnetcal.txt
  6199. --::::::::::::::
  6200. -----------------------------------------------------------------------
  6201. --
  6202. --         DoD Protocols    NA-00008-200       80-01193-100(-)
  6203. --         E-Systems, Inc.  August 07, 1985
  6204. --
  6205. --         subnetcal.txt       Author : Jim Baldo
  6206. --
  6207. -----------------------------------------------------------------------
  6208. with buffer_data;                  use buffer_data;
  6209. with IP_GLOBALS;                   use IP_GLOBALS;
  6210.                          
  6211.                          package subnet_calls is
  6212.                 
  6213.                 ------------------------------------------------
  6214.                 --This implementation version is for use with  --
  6215.                 --Telesoft Ada for Wicat Machine               --
  6216.                 -------------------------------------------------         
  6217. -------------------------------------------------------------------------------
  6218. --This package contains procedure calls and data structures necessary for --
  6219. --the Internet Protocol Group and the Subnet Protocol Group to communicate.--
  6220. -------------------------------------------------------------------------------
  6221. PACKAGE SNP is
  6222. procedure subnet_get ;
  6223. procedure send( datagram              :  in out packed_buffer_ptr;
  6224.             local_destination   : in    Local_address_type;
  6225.             precedence          : in    Precedence_type;
  6226.             reliability         : in    reliability_type;
  6227.             delay_ip            : in    delay_type;
  6228.             throughput          : in    throughput_type;
  6229.             length              : in    datagram_length);
  6230. --This entry sends a datagram to the subnet for transmit.
  6231.       --Fully compatible with MIL-STD 1777.
  6232.    procedure Deliver( datagram : out packed_buffer_ptr);
  6233.       --This entry requests for a datagram from the subnet.  If the pointer
  6234. --is null, the subnet queue is empty.  Fully compatible with MIL-STD 1777.
  6235.    procedure send_to_ip ( datagram: in out packed_buffer_ptr); 
  6236. end SNP;
  6237. end subnet_calls;
  6238. with system;  use system;
  6239. with unchecked_conversion;
  6240. with TEXT_IO;        use TEXT_IO, INTEGER_IO, LONG_INTEGER_IO;
  6241. with system; use system;
  6242. with unchecked_conversion;
  6243. with mover;  use mover;
  6244. package body subnet_calls is
  6245. ------------------------------------------------------
  6246. --This implementation version is for use with  --
  6247. --WICAT  
  6248. ------------------------------------------------------
  6249. --  10-JUL-85  :  (VCB) Port to WICAT under ROS with TCP/IP
  6250. ---------------------------------------------------------------
  6251. ---------------------------------------------------------------
  6252. --  Ethernet Packet Format:
  6253. --
  6254. --           Field                        Number Bytes
  6255. --
  6256. --  preamble                           8
  6257. --  destination address                6
  6258. --  source address                     6
  6259. --  protocol type                      2
  6260. --  data                          46 to 1500
  6261. --  frame check sequence               4
  6262. --      note: 
  6263. --           The first two bytes of the dat field are
  6264. --           used to stroe the data LENGTH parameter.            
  6265. --  Note:  inter-frame is 9.6 microseconds, minimum
  6266. --
  6267. --------------------------------------------------------------------------------
  6268. --
  6269. --  subnet driver routines
  6270. --
  6271. --------------------------------------------------------------------------------
  6272. --
  6273. type net_address is array(0..5) of system.byte;
  6274. type packet_type is array(0..2047) of system.byte;
  6275.   type big_packet is array (0..4095) of system.byte;
  6276.   buffer_busy    :  exception;
  6277.   net_error      :  exception;
  6278. function addr is new unchecked_conversion (thirtytwo_bits,system.address);
  6279. function long is new unchecked_conversion (system.address,thirtytwo_bits);
  6280. function bol is new unchecked_conversion (sixteen_bits,boolean);
  6281. function int is new unchecked_conversion (boolean, sixteen_bits);
  6282. --
  6283. --  3Com board addresses....
  6284. --
  6285. base    :  constant thirtytwo_bits := 16#E60000#; --base address of 3-Com
  6286. csr     :  sixteen_bits;   for csr   use at addr(base+ 16#0000#);
  6287. back    :  sixteen_bits;   for back  use at addr(base+ 16#0002#);
  6288. SA_rom  :  net_address; for SA_rom  use at addr(base+ 16#0400#);
  6289. SA_ram  :  net_address; for SA_ram  use at addr(base+ 16#0600#);
  6290. TX_buf  :  packet_type; for TX_buf  use at addr(base+ 16#0800#);
  6291. RX_bufs :  big_packet;
  6292.         for RX_bufs use at addr(base+ 16#1000#);
  6293. A_offset: constant sixteen_bits := 16#0000#;  -- Offset to A buffer
  6294. B_offset: constant sixteen_bits := 16#0800#;  -- offset to b buffer
  6295. PA      : constant sixteen_bits := 16#0008#;  -- receive mine & brcast
  6296. jinten  : constant sixteen_bits := 16#0010#;  -- jam interrupt enable bit         
  6297. tinten  : constant sixteen_bits := 16#0020#;  -- TX interrupt enable bit  
  6298. ainten  : constant sixteen_bits := 16#0040#;  -- A_rec interrupt enable bit
  6299. binten  : constant sixteen_bits := 16#0080#;  -- B_rec interrupt enable bit    
  6300. reset   : constant sixteen_bits := 16#0100#;  -- master reset    
  6301. spare   : constant sixteen_bits := 16#0200#;  -- not used  
  6302. rbba    : constant sixteen_bits := 16#0400#;  -- state of a when b arrives
  6303. amsw    : constant sixteen_bits := 16#0800#;  -- net address control   
  6304. jam     : constant sixteen_bits := 16#1000#;  -- jam bit
  6305. tbsw    : constant sixteen_bits := 16#2000#;  -- transmit buffer control
  6306. absw    : constant sixteen_bits := 16#4000#;  -- receive buffer a control
  6307. bbsw : constant sixteen_bits := sixteen_bits (16#8000#);  -- receive buffer B
  6308. Code    :  constant sixteen_bits  := pa+amsw+absw+bbsw;
  6309. protocol_type_1 : constant system.byte := 16#06#;  --MSB of protocol type
  6310. protocol_type_2 : constant system.byte := 16#60#;  --lsb of protocol type
  6311. buffer_addr : system.address; --  Temp for 'move' routine   
  6312. type ethernet_address is array (0..5) of integer   ;
  6313. type host_ethernet_pair is record
  6314.   host_number  :  local_address_type; 
  6315.   local_addr   :  ethernet_address;
  6316.   end record;
  6317. address_table  :  array (1..max_hosts) of host_ethernet_pair;
  6318. buffer_size : constant integer :=16;
  6319. type dg_array is array (0..buffer_size) of packed_buffer_ptr;
  6320. type buffer_type is record
  6321.   put : integer  range 0..buffer_size := 0;
  6322.   get : integer  range 0..buffer_size := 0;
  6323.   val : dg_array;
  6324.   end record;
  6325. buffer  :  buffer_type;
  6326. package body snp is
  6327. -----------------------------------------------------------------------------
  6328. --                                                                       --
  6329. --   Procedure Subnet_put                                                --
  6330. --                                                                       --
  6331. -----------------------------------------------------------------------------
  6332. procedure subnet_put (buf: in out packed_buffer_ptr;
  6333.                       adr: in     Local_address_type;
  6334.                       length_of_packet: in    datagram_length) is
  6335. minimum_bytes  :  constant datagram_length  := 46;  --minimum bytes to xmit
  6336. ptr            :  sixteen_bits;                     --Offset from 3-com
  6337. attempt_count  :  sixteen_bits;                     --Number of tries
  6338. net_address    :  ethernet_address;         --Ethernet destination address
  6339. datagram       :  system.address;           --IP datagram location
  6340. host_valid     :  boolean  := false;        --Denotes valid host ID
  6341. len            :  datagram_length;          --Local length
  6342. begin
  6343.   len := length_of_packet;
  6344. --Make sure we have a valid host address ID
  6345.      for i in 1..max_hosts loop
  6346.        if address_table(i).host_number = adr then
  6347.          net_address := address_table(i).local_addr;
  6348.          host_valid := true;
  6349.          exit;
  6350.        end if;
  6351.     end loop;
  6352.     if host_valid then
  6353. --Make sure we have transmit buffer
  6354.     if bol(csr) and bol(TBSW) then raise buffer_busy; 
  6355.     end if;
  6356.     new_line;
  6357. --Make sure packet contains at least minimum_bytes of data
  6358.     if len < minimum_bytes then
  6359.     for i in len .. minimum_bytes loop
  6360.     buf.byte(i+1) := 0;                     --nulls padded in
  6361.   end loop;
  6362.   len := minimum_bytes;
  6363. end if;
  6364. --copy packet to 3-Com TX Buffer
  6365.     ptr := 2048-len;                    --offset inTX buffer of 1st byte
  6366.     for i IN 0..(len-1) loop
  6367.       TX_buf(ptr + (LEN - 1) - I) := buf.byte(255 -i);
  6368.     end loop;
  6369. --Now put ethernet header on packet (dest,src,type)
  6370. --First destination address
  6371.   ptr := ptr - 16;               -- 16 bytes before 1st byte in data field
  6372.   for i in 0..5 loop
  6373.     TX_buf(ptr+i) := system.byte(net_address(i));   --insert dest
  6374.    end loop;
  6375. --Now Source address
  6376.    for i in 0..5 loop
  6377.    TX_buf (ptr+6+i) := SA_ram(i);                 --insert source address
  6378.   end loop;
  6379. --Protocol type  (*** ensures invisibility to DECnet--not used by us)
  6380.    TX_buf(ptr+12) := protocol_type_1;               --1st byte of type
  6381.    TX_buf(ptr+13) := protocol_type_2;               --2nd byte of type
  6382. --Add packet length designation following protocol type field
  6383.   TX_buf(ptr+15) := len/256;
  6384.   TX_buf(ptr+14) := len MOD 256;
  6385. --Now set transmit buffer header
  6386.   TX_buf(0) := ptr/256;          --ptr still indexes packet start
  6387.   TX_buf(1) := ptr mod 256;
  6388. --Now issue TRANSMIT COMMAND and wait for it to be sent        
  6389.   csr:=TBSW+Code;              --issue command
  6390.   attempt_count := 1;
  6391.   loop
  6392.     if attempt_count > 15 then 
  6393.       raise Net_Error;
  6394.     end if;
  6395.     exit when (int(bol(csr) and bol (TBSW)) = 0); -- when buffer is returned
  6396.     if int(bol(csr) and bol (JAM))/= 0  then    -- We got collision
  6397.       TEXT_IO.put_line ("Collision");
  6398.       attempt_count := attempt_count + 1;
  6399.       back := -20;                      --stupid delay
  6400.       csr := JAM+CODE;                  -- clear jam and retry
  6401.     end if;
  6402.  end loop;
  6403.  --text_io.new_line;
  6404.  --TEXT_IO.put("Sent Ethernet packet of ");
  6405.  --TEXT_IO.INTEGER_IO.put(len);
  6406.  --TEXT_IO.put_line ("octets");
  6407. else
  6408.  TEXT_io.put_line("invalide ethernet id");    --for debug only
  6409. end if;
  6410. -- NOTE:  Subnet must  set buf.in_use to FALSE before freeing up the buffer
  6411. buf.in_use := false;
  6412. buffree (buf,0);                       -- free the datagram buffer     
  6413. exception
  6414. when buffer_busy =>
  6415.   Text_IO.put_line("Exception in subnet_put:  3-Com board busy.");
  6416. when Net_Error  =>
  6417.   Text_io.put_line("exception in subnet_put:  Maximum collision count.");
  6418. when constraint_error => 
  6419.   text_io.put_line("constraint error in subnet_put");
  6420. when others =>
  6421.   text_io.put_line("Exception in subnet_put:  Undefined.");
  6422. end subnet_put;
  6423. --------------------------------------------------------------------------------
  6424. --
  6425. -- subnet_get
  6426. --
  6427. --------------------------------------------------------------------------------
  6428. procedure subnet_get is
  6429.   buffer_select  :  sixteen_bits  := -1;
  6430.   temp           :  sixteen_bits;
  6431.   temp2          :  sixteen_bits;
  6432.   ptr            :  sixteen_bits;
  6433.   len            :  sixteen_bits;
  6434.   datagram       :  system.address;
  6435.   buf            :  packed_buffer_ptr;
  6436. begin
  6437. --  Check if packet has arrived, and determine which buffer it is in
  6438.     if (int(bol(csr) and bol(ABSW)) = 0) then
  6439.       if (int(bol(csr)  and bol(BBSW)) = 0) then    --if both ready
  6440.         if (int(bol(csr)  and bol(RBBA)) = 0) then  --see which cam first
  6441.           buffer_select := A_offset;
  6442.       else
  6443.           buffer_select := B_offset;
  6444.       end if;
  6445.     else
  6446.       buffer_select := A_offset;
  6447.     end if;
  6448.   else
  6449.     if (int(bol(csr)  and bol(BBSW)) = 0) then
  6450.     buffer_select := B_offset; end if;
  6451.   end if;
  6452. if buffer_select >= 0 then              -- true if packet available
  6453. --Get a free buffer for IP to use
  6454.   buffget (buf,1);
  6455.   if buf /= null then
  6456.     BUF.STATUS := OWNER_IP;
  6457.     BUF.IN_USE := TRUE;
  6458.     datagram := buf.byte'address;
  6459.     ptr := buffer_select;
  6460.     temp := RX_bufs (ptr);             --compute length of packet
  6461.     temp := temp mod 8 ;
  6462.     temp2 := RX_bufs(ptr+1);
  6463.     len := temp*256 + temp2 - 22;  --reduce count by HDR & FCS
  6464.     --text_io.new_line;
  6465.     --Text_io.put("Received a packet of ");
  6466.     --Text_IO.Integer_IO.put (len);
  6467.     --Text_IO.put_line("octets");
  6468.     ptr := ptr + 18;                -- skip over Ethernet header               
  6469.     -- text_io.put("byte 1=");
  6470.     -- integer_io.put(rx_bufs(ptr-2));
  6471.     -- text_io.put("byte 2=") ;
  6472.     -- integer_io.put(rx_bufs(ptr-1));
  6473.     -- new_line;
  6474.     -- text_io.put(" type 1= ");
  6475.     -- integer_io.put(rx_bufs(ptr-4));
  6476.     -- text_io.put(" type 2= ");
  6477.     -- integer_io.put(rx_bufs(ptr-3));
  6478.     -- new_line;
  6479. --Correct the length based on ether packet and move data to user buffer
  6480.     len := rx_bufs(ptr-1)*256+rx_bufs(ptr-2);
  6481.     buf.size := len ;
  6482.     for i IN 1..(len)  loop
  6483.        buf.byte(i) := RX_bufs(i+ptr - 1);
  6484.     end loop;
  6485.     send_to_ip(buf);                          --send to IP
  6486.   else
  6487.     Text_io.put_line("LOST ETHERNET PACKET.  OUT OF BUFFERS");
  6488.   end if;
  6489. end if;
  6490. csr := CODE;                          --give rec. buf back to ether
  6491. exception
  6492.   when constraint_error =>
  6493.     text_io.put_line("Constraint error in subnet_get");
  6494.   when others =>
  6495.     text_io.put_line("other exception in subnet_get");
  6496. end subnet_get;
  6497. procedure deliver( datagram : In out packed_buffer_ptr) is 
  6498.  begin
  6499.  if (buffer.put /= buffer.get) then
  6500.    datagram := buffer.val(buffer.get);
  6501.    buffer.get := (buffer.get + 1) mod buffer_size;
  6502.  else
  6503.   DATAGRAM := null;
  6504.  end if;
  6505.  exception 
  6506.   when constraint_error=>
  6507.     text_io.put_line("Constraint error in deliver");
  6508.   when others =>
  6509.     text_io.put_line("Other exception in deliver");
  6510. end deliver;
  6511. procedure send( datagram          : in out packed_buffer_ptr;
  6512.   local_destination    : in  Local_address_type;
  6513.   precedence           : in  precedence_type;
  6514.   reliability          : in  reliability_type;
  6515.   delay_ip             : in  delay_type;
  6516.   throughput           : in  throughput_type;
  6517.     length             : in   datagram_length)
  6518. is
  6519. begin
  6520. --TEXT_IO.NEW_LINE;
  6521. --TEXT_IO.PUT("LENGTH(SUBNET) := ");
  6522. --TEXT_IO.INTEGER_IO.PUT(LENGTH);
  6523. --TEXT_IO.NEW_LINE;
  6524. subnet_put(datagram, local_destination, length);
  6525. end send;
  6526. procedure send_to_ip(datagram : in out packed_buffer_ptr) is
  6527.   begin
  6528.   if buffer.get /= (buffer.put + 1) mod buffer_size then
  6529.     datagram.ip_ptr := 1;
  6530.     buffer.val(buffer.put)   := datagram ;
  6531.     buffer.put  := (buffer.put + 1) mod buffer_size;
  6532. else
  6533.    Text_io.put_line("LOST AN ETHERNET PACKET -- NO QUEUE SPACE ");
  6534. -- Must set datagram.in_use to FALSE before freeing this buffer
  6535.    
  6536.    datagram.in_use := FALSE;
  6537.    buffree(datagram,0);
  6538. end if;
  6539. exception
  6540.   when constraint_error =>
  6541.     text_io.put_line("constraint error in send_to_ip");
  6542.   when others =>
  6543.     text_io.put_line("other exception in send_to_ip");
  6544. end send_to_ip;
  6545. end SNP;
  6546. --  subnet_interface - subnet protocol for Ethernet
  6547. --
  6548. --
  6549. --------------------------------------------------------------------------
  6550. --
  6551. --Start_Subnet_Driver   (Initialization for 3-Com Board
  6552. --
  6553. --------------------------------------------------------------------------
  6554. procedure start_subnet_driver is
  6555. begin
  6556.   csr := RESET;                   --do a board reset
  6557.   for i in 0..5 loop              --copy rom addres to ram
  6558.     SA_ram(i) := SA_rom(i);       --for recognition
  6559.   end loop;
  6560.   csr := code ;                   -- give address & rec bufs to ether
  6561.  end start_subnet_driver;
  6562. ------------------------------------------------------------------------------
  6563. --
  6564. --  MAIN - Initialize the Ethernet Driver
  6565. --
  6566. -----------------------------------------------------------------------------
  6567. begin
  6568.   address_table  := ( (1,    (16#AA#,16#00#,16#04#,16#00#,
  6569.                               16#01#,16#04#)),            --vax saturn
  6570.                       (2,    (16#AA#,16#00#,16#04#,16#00#,
  6571.                               16#02#,16#04#)),            --vax mars
  6572.                       (3,    (16#02#,16#60#,16#8C#,16#00#,
  6573.                               16#79#,16#42#)),            --sylvester
  6574.                       (128,  (16#00#,16#00#,16#00#,16#00#,
  6575.                               16#00#,16#00#)));           --unused
  6576. text_io.put_line("3Com Board started ");
  6577.  start_subnet_driver ; --intialize 3 Com Board
  6578. end subnet_calls;      
  6579.  
  6580. --::::::::::::::
  6581. --sub_int.txt
  6582. --::::::::::::::
  6583. -----------------------------------------------------------------------
  6584. --
  6585. --         DoD Protocols    NA-00008-200       80-01194-100(-)
  6586. --         E-Systems, Inc.  August 07, 1985
  6587. --
  6588. --         sub_int.txt       Author : Jim Baldo
  6589. --
  6590. -----------------------------------------------------------------------
  6591. with buffer_data; use buffer_data;
  6592. with subnet_calls; use subnet_calls;
  6593. --   PACKAGE subnet_interface - Subnet Protocol for Ethernet
  6594. --
  6595. --   
  6596. --   This package provides the init,send, & receive functions for
  6597. --   Ethernet.  It assumes a 3Com board is plugged in and addressable
  6598. --   at E60000.
  6599. --
  6600. --      04-JUN-85 : (VCB) Port to WICAT under ROS with TCP/IP
  6601. --********************************************************************
  6602. ----------------------------------------------------------------------
  6603. ----------------------------------------------------------------------
  6604. package subnet_interface is                                         --
  6605.                                                                     --
  6606. subtype LOCAL_ADDRESS_TYPE is INTEGER ;
  6607. subtype DATAGRAM_LENGTH is INTEGER ;
  6608. procedure subnet_put (buf: in out packed_buffer_ptr;                -- 
  6609.                       adr: in     local_address_type;               --
  6610.                       len: in     datagram_length);                 --
  6611. procedure subnet_get;                                               --
  6612.                                                                     --
  6613. end subnet_interface;                                               --
  6614.                                                                     --
  6615. ----------------------------------------------------------------------
  6616. ----------------------------------------------------------------------
  6617. --********************************************************************
  6618. --
  6619. --
  6620. --  Ethernet Packet Format:
  6621. --
  6622. --          Field                 Number of Bytes
  6623. --
  6624. --     PREAMBLE                         8
  6625. --     DESTINATION ADDRESS              6
  6626. --     SOURCE ADDRESS                   6
  6627. --     PROTOCOL TYPE                    2
  6628. --     DATA                         46 to 1500
  6629. --     FRAME CHECK SEQUENCE             4
  6630. --
  6631. --  Note:  Inter-frame spacing is 9.6 microseconds, minimum
  6632. --
  6633. with Text_io; use text_io,integer_io, long_integer_io;
  6634. with system; use system;
  6635. with unchecked_conversion;
  6636. with mover;
  6637. package body subnet_interface is
  6638.   type net_address is array(0..5) of system_byte;
  6639.   type packet_type is array(0..2047) of system_byte;
  6640.   buffer_busy   : exception;
  6641.   Net_Error     : exception;
  6642. function addr is new unchecked_conversion (thirtytwo_bits,system.address);
  6643. function long is new unchecked_conversion (system.address,thirtytwo_bits);
  6644. function bol is new unchecked_conversion (sixteen_bits,boolean);
  6645. --
  6646. --  3Com board addresses...
  6647. --
  6648. base    : constant thirtytwo_bits := 16#E60000#;  -- base address of 3com
  6649. csr     : sixteen_bits;     for csr     use at addr(base+ 16#0000#);
  6650. back    : sixteen_bits;     for back    use at addr(base+ 16#0002#);
  6651. SA_rom  : net_address; for SA_rom  use at addr(base+ 16#0400#);
  6652. SA_ram  : net_address; for SA_ram  use at addr(base+ 16#0600#);
  6653. TX_buf  : packet_type; for TX_buf  use at addr(base+ 16#0800#);
  6654. RX_bufs : array(0..4095) of system_byte;for RX_bufs use at addr(base+ 16#1000#);
  6655. A_offset: constant sixteen_bits := 16#0000#;     -- offset to A buffer
  6656. B_offset: constant sixteen_bits := 16#0800#;     -- offset to B buffer
  6657. PA      : constant sixteen_bits := 16#0008#;     -- receive only mine & brcast
  6658. JINTEN  : constant sixteen_bits := 16#0010#;     -- jam interrupt enable bit
  6659. TINTEN  : constant sixteen_bits := 16#0020#;     -- TX interrupt enable bit
  6660. AINTEN  : constant sixteen_bits := 16#0040#;     -- A_Rec interrupt enable bit
  6661. BINTEN  : constant sixteen_bits := 16#0080#;     -- B_Rec interrupt enable bit
  6662. RESET   : constant sixteen_bits := 16#0100#;     -- Master Reset
  6663. SPARE   : constant sixteen_bits := 16#0200#;     -- not used
  6664. RBBA    : constant sixteen_bits := 16#0400#;     -- state of A when B arrives
  6665. AMSW    : constant sixteen_bits := 16#0800#;     -- net address control
  6666. JAM     : constant sixteen_bits := 16#1000#;     -- jam bit
  6667. TBSW    : constant sixteen_bits := 16#2000#;     -- transmit buffer control
  6668. ABSW    : constant sixteen_bits := 16#4000#;     -- receive buffer A control
  6669. BBSW    : constant sixteen_bits := sixteen_bits(16#8000#);     -- receive buffer B control
  6670. CODE    : constant sixteen_bits := PA+AMSW+ABSW+BBSW;
  6671. protocol_type_1 : constant system_byte := 16#60#;   -- MSB of protocol type
  6672. protocol_type_2 : constant system_byte := 16#06#;   -- LSB of protocol type
  6673. buffer_addr    : system.address;    --    Temp for 'move' routine
  6674. type ethernet_address is array (0..7) of system_byte;
  6675. type host_ethernet_pair is record
  6676.    host_number : local_address_type;
  6677.    local_addr  : ethernet_address;
  6678.    end record;
  6679. address_table : array (1..max_hosts) of host_ethernet_pair
  6680.              := ( (1,   (16#AA#,16#00#,16#04#,16#00#,          -- vax saturn
  6681.                          16#01#,16#04#,16#00#,16#00#)),
  6682.                   (2,   (16#AA#,16#00#,16#04#,16#00#,          -- vax mars
  6683.                         16#02#,16#04#,16#00#,16#00#)),
  6684.                   (3,   (16#02#,16#60#,16#8C#,16#00#,          -- sylvester
  6685.                          16#79#,16#42#,16#00#,16#00#)),
  6686.                   (128, (16#00#,16#00#,16#00#,16#00#,          -- unused
  6687.                          16#00#,16#00#,16#00#,16#00#)));
  6688. -- ---------------------------------------------------------------------
  6689. --                                                                    --
  6690. -- START_SUBNET_DRIVER  (Initialization for 3-Com board               --
  6691. --                                                                    --
  6692. ------------------------------------------------------------------------
  6693. procedure start_subnet_driver is
  6694. begin
  6695.  csr := RESET;                       -- do a board reset
  6696.  for i in 0..5 loop                  -- copy rom address to ram
  6697.    SA_ram(i) := SA_rom(i);           -- for recognition
  6698.  end loop;
  6699.  csr := CODE;                        -- give address & rec. bufs to ether
  6700. end init;
  6701. ------------------------------------------------------------------------- 
  6702. --                                                                     --
  6703. --  SUBNET_PUT  (Put datagram from IP to Ethernet)                     --
  6704. --                                                                     --
  6705. -------------------------------------------------------------------------
  6706. procedure subnet_put (buf: in out packed_buffer_ptr;
  6707.                       adr: in     local_address_type;
  6708.                       len: in     datagram_length) is
  6709.   
  6710.   ptr           : sixteen_bits;                     -- Offsets from 3-Com base addr
  6711.   attempt_count : sixteen_bits;                     -- Number of tries
  6712.   net_address   : ethernet_address;            -- Ethernet destination address
  6713.   datagram      : system.address;              -- IP datagram location
  6714.   host_valid    : boolean := false;            -- Denotes valid host ID
  6715. begin
  6716. -- make sure we have a valid host address ID
  6717.   for i in 1..max_hosts loop
  6718.      if address_table(i).host_number = adr then
  6719.         net_address := address_table(i).local_addr;
  6720.         host_valid := true;
  6721.         exit;
  6722.      end if;
  6723.   end loop;
  6724.   if host_valid then
  6725. -- make sure we have transmit buffer
  6726.      if bol(csr) and bol(TBSW) then raise buffer_busy; end if;
  6727. -- copy packet to 3-Com TX Buffer
  6728.      ptr := 2048-len;              -- offset in TX buffer of 1st byte
  6729.      datagram := buf.byte(buf.subnet_ptr)'address;          -- IP datagram
  6730.      buffer_addr := addr(long(TX_buf'address)+thirtytwo_bits(ptr));
  6731.      mover.move (datagram, buffer_addr, len);                -- do move in ASM
  6732. -- now put ethernet header on packet  (dest,src,type)
  6733. -- first destination address
  6734.      ptr := ptr - 14;          -- 14 bytes before 1st byte in data field
  6735.      for i in 0..5 loop
  6736.        TX_buf(ptr+i) := net_address(i);              -- insert dest address
  6737.      end loop;
  6738. -- now source address
  6739.      for i in 0..5 loop
  6740.        TX_buf(ptr+6+i) := SA_ram(i);                 -- insert source address
  6741.      end loop;
  6742. -- protocol type  (*** ensures invisibility to DECnet-- not used by us)
  6743.      TX_buf(ptr+12) := protocol_type_1;              -- 1st byte of type
  6744.      TX_buf(ptr+13) := protocol_type_2;              -- 2nd byte of type
  6745.      
  6746. -- now set transmit buffer header
  6747.      TX_buf(0) := ptr/256;                  -- ptr still indexes packet start
  6748.      TX_buf(1) := ptr mod 256;
  6749. -- now issue TRANSMIT COMMAND and wait for it to be sent
  6750.      csr := TBSW+CODE;                           -- issue command
  6751.      attempt_count := 1;
  6752.      loop
  6753.        if attempt_count > 15 then raise Net_Error; end if;
  6754.        exit when not (bol(csr) and bol(TBSW));  -- when buffer is returned
  6755.        if not (bol(csr) and bol(JAM)) then   -- we got a collision
  6756.          put_line("Collision");
  6757.          attempt_count := attempt_count + 1;
  6758.          back := -20;                       -- stupid delay
  6759.          csr := JAM+CODE;                     -- clear jam & retry
  6760.        end if;
  6761.      end loop;
  6762.      put("Sent Ethernet packet of "); put(len);put_line(" octets");
  6763.   else
  6764.      put_line("INVALID ETHERNET ID");        -- for debug only
  6765.   end if;
  6766.   buffree(buf,0);           -- free the datagram buffer
  6767.   exception
  6768.      when buffer_busy =>
  6769.         put_line("EXCEPTION in Subnet_put:  3-Com board busy.");
  6770.      when Net_Error =>
  6771.         put_line("EXCEPTION in Subnet_put:  Maximum collision count.");
  6772.      when others =>
  6773.         put_line("EXCEPTION in Subnet_put:  Undefined.");
  6774. end subnet_put;
  6775. ---------------------------------------------------------------------
  6776. --                                                                 --
  6777. -- SUBNET_GET  (Get Ethernet Packet and send to IP)                --
  6778. --                                                                 --
  6779. ---------------------------------------------------------------------
  6780. procedure subnet_get;
  6781.   buffer_select   : sixteen_bits := -1;
  6782.   temp            : sixteen_bits;
  6783.   temp2           : sixteen_bits;
  6784.   ptr             : sixteen_bits;
  6785.   len             : sixteen_bits;
  6786.   datagram        : system.address
  6787.   buf             : packed_buffer_pointer;
  6788. begin
  6789. --  Check if packet has arrived, and determine which buffer it is in
  6790.     if not (bol(csr) and bol(ABSW)) then
  6791.       if not(bol(csr) and bol(BBSW)) then        -- if both ready
  6792.         if not(bol(csr) and bol(RBBA)) then      -- see which came first
  6793.           buffer_select := A_offset;
  6794.         else
  6795.           buffer_select := B_offset;
  6796.         end if;
  6797.       else
  6798.         buffer_select := A_offset;
  6799.       end if;
  6800.     else
  6801.       if not (bol(csr) and bol(BBSW)) then buffer_select := B_offset; end if;
  6802.     end if;
  6803.     
  6804.     if buffer_select >= 0 then              -- true if packet available
  6805. -- get a free buffer for IP to use
  6806.       buffget(buf,1);
  6807.       if buf /= null then
  6808.          datagram := buf.byte(buf.subnet_ptr)'address;  
  6809.          ptr := buffer_select;
  6810.          temp  := RX_bufs(ptr) mod 8;          -- compute length of packet
  6811.          temp2 := RX_bufs(ptr+1);
  6812.          len   := temp*256 + temp2 - 18; -- reduce count by HDR & FCS 
  6813.          ptr := ptr + 14;                 -- skip over Ethernet header
  6814. --  move packet to user buffer
  6815.          buffer_addr := addr(long(RX_bufs'address)+thirtytwo_bits(ptr));
  6816.          mover.move(buffer_addr, datagram, len);    -- do move in ASM
  6817.          send_to_ip(buf);                               -- send to IP
  6818.          put("Received a packet of "); put(len);put_line(" octets");
  6819.       else
  6820.          put_line("LOST ETHERNET PACKET.  OUT OF BUFFERS");
  6821.       end if;
  6822.     end if;
  6823.     csr := CODE;                          -- give rec. buf back to ether
  6824. end subnet_get;
  6825. -- INITIALIZE SUBNET DRIVERS
  6826. begin
  6827.   start_subnet_driver;
  6828. end subnet_interface;
  6829. --::::::::::::::
  6830. --tcpcont2.txt
  6831. --::::::::::::::
  6832. -----------------------------------------------------------------------
  6833. --
  6834. --         DoD Protocols    NA-00008-200       80-01195-100(-)
  6835. --         E-Systems, Inc.  August 07, 1985
  6836. --
  6837. --         tcpcont2.txt       Author : Jim Baldo
  6838. --
  6839. -----------------------------------------------------------------------
  6840.         package    TCP_CONTROLLER_TASK is
  6841.     --------------------------------------------------------------
  6842.     --This implementation is for the Telesoft/Ada compiler .    --
  6843.     --------------------------------------------------------------
  6844. ------------------------------------------------------------------------------
  6845. -- This    package    contains the necessary procedures and functions    to control  --
  6846. -- the transmission control protocol(TCP) activities in    general    and         --
  6847. -- specifically    all activities associated with ULP commands to TCP.          --
  6848. ------------------------------------------------------------------------------
  6849.  procedure TCP_CONTROLLER;
  6850. -- The TCP_CONTROLLER task  is responsible for the control and operation of 
  6851. -- the TCP layer.   It  determines the necessary actions after it gets 
  6852. --a message from the communications queue. It then calls the procedure 
  6853. -- that will cause that task to be  performed.  A task message is 
  6854. -- gotten via an entry into the communication task.  This message is 
  6855. -- used to call a procedure to process the request for action made to the TCP.
  6856. --                                   
  6857. --The following procedures are contained within the package body and
  6858. --are used by TCP_CONTROLLER to perform the specific processing for each
  6859. --event.  It should be noted that the event processing defined below
  6860. --is specifed by MIL-STD-1778.
  6861. --                                          
  6862. --   TCP_SEND -    This procedure will process a send request from    the user.     
  6863. --
  6864. --   TCP_ABORT - This procedure    will cause a connection    to be aborted. the    
  6865. --         user requests this action.                      
  6866. --
  6867. --   TCP_RECEIVE - This    procedure will cause any data from a remote site to   
  6868. --           the user to be returned to the user.
  6869. --
  6870. --   TCP_CLOSE - This procedure    will cause a connection    to be closed.
  6871. --
  6872. --   TCP_OPEN -    This procedure will attempt to open an active or passive
  6873. --        connection to a    remote host as required    by the user.     
  6874. --
  6875. --   TCP_STATUS    - This procedure will return the status    of a connection    to    
  6876. --          the user.          
  6877. --
  6878. --   TCP_ERROR - This procedure    will handle any    errors that may    come to    the 
  6879. --         attention of the TCP. They may    be TCP errors or error 
  6880. --         notifications from other layers of protocol.          
  6881. --
  6882. --   RETRANS_TCP - This    procedure will retransmit the first packet in the
  6883. --           retransmit queue.
  6884. --
  6885. --   TCP_SEG_ARRIVE - This procedure determines    the action to be taken upon
  6886. --              reception    of segment. It will then call a    routine    to
  6887. --              perform the action. The action is    based on the state of
  6888. --              the connection.  
  6889. --                                          
  6890. --   MESSAGE_FOR_USER - Give a message to the user layer.
  6891. end TCP_CONTROLLER_TASK ;
  6892. with TEXT_IO;                           use TEXT_IO, INTEGER_IO;
  6893. with TCP_GLOBALS ;            use TCP_GLOBALS ;
  6894. with TCP_SEGMENT_ARRIVES_PROCESSING ;    use TCP_SEGMENT_ARRIVES_PROCESSING ;
  6895. with TCP_ARRIVES_PERIPHERALS ;        use TCP_ARRIVES_PERIPHERALS ;
  6896. with BUFFER_DATA ;            use BUFFER_DATA ;
  6897. with T_TCP_CONTROLLER_UTILITIES ;    use T_TCP_CONTROLLER_UTILITIES ;
  6898. with QUEUES ;                use QUEUES ;
  6899. with REAL_TIME_CLOCK_AND_DATE ;        use REAL_TIME_CLOCK_AND_DATE ;
  6900. with TCB_ALLOCATOR ;            use TCB_ALLOCATOR ;
  6901. with T_TCP_GLOBALS_DATA_STRUCTURES ;    use T_TCP_GLOBALS_DATA_STRUCTURES ;
  6902. with WITH_ULP_COMMUNICATE;              use WITH_ULP_COMMUNICATE;
  6903. with WITH_TCP_COMMUNICATE ;            use WITH_TCP_COMMUNICATE ;
  6904.         
  6905.                 package    body TCP_CONTROLLER_TASK is
  6906.     --------------------------------------------------------------
  6907.     --This implementation is for the DEC/Ada compiler .         --
  6908.     --------------------------------------------------------------
  6909.  procedure TCP_CONTROLLER is
  6910. MESSAGE_FROM_IP : MESSAGE ;
  6911. UMESSAGE : USER_MESSAGE;
  6912. TASK_MESSAGE :    MESSAGE;
  6913. FLAG : BOOLEAN := TRUE; -- for message
  6914. RETRANSMIT : BOOLEAN := TRUE;
  6915. MAX_TEMP : SIXTEEN_BITS ;
  6916. SOCKET_PARAMS : TCB_PTR;
  6917. DELETE_A_LCN : BOOLEAN := FALSE;
  6918. TEMP_HOLDER_LCN : TCB_PTR := null ;
  6919. function DETERMINE_VALID_LCN( LCN : TCB_PTR ) return BOOLEAN is
  6920. VALID_LCN : TCB_PTR := null ;
  6921. RESULT : BOOLEAN := FALSE ;
  6922. begin
  6923.  VALID_LCN := OBTAIN_HEAD_OF_LCN_IN_USE_QUEUE;
  6924.  while VALID_LCN /= null loop
  6925.   if VALID_LCN = LCN then
  6926.    RESULT := TRUE ;
  6927.    RETURN RESULT;
  6928.   end if;
  6929.   VALID_LCN := VALID_LCN.NEXT ;
  6930.  end loop;
  6931.  RETURN RESULT;
  6932. end DETERMINE_VALID_LCN;
  6933.  
  6934. begin -- TCP_CONTROLLER
  6935.   --determine if any timeouts have occurred
  6936.   LCN := OBTAIN_HEAD_OF_LCN_IN_USE_QUEUE;
  6937.   --text_io.put_line("before LCN /= null ");
  6938.   while LCN /= null loop
  6939.    --TEXT_IO.put("system time = ");
  6940.    --text_io.long_integer_io.put(thirtytwo_bits(system_time));
  6941.    --TEXT_IO.new_line;
  6942.    --Note that we will have a problem when the local_time_now cycles
  6943.    --every 6 hours.  We simply make the types modular.
  6944.    if LCN.STATE /= T_TCP_GLOBALS_DATA_STRUCTURES.CLOSED and 
  6945.       (LCN.STATE /= T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN) then
  6946.     --Check appropriate times and call necessary routine for any timeouts.
  6947.     if THIRTYTWO_BITS(SYSTEM_TIME) >= LCN.NEXT_CONNECTION_TIMEOUT and
  6948.        (LCN.NEXT_CONNECTION_TIMEOUT > 0) then
  6949.      --trash the connection and notify the user
  6950.      SOCKET_PARAMS := LCN;    
  6951.      UMESSAGE := ( 24, 
  6952.                    SOCKET_PARAMS);
  6953.      MESSAGE_FOR_USER( UMESSAGE);
  6954.      QUEUE_CLEAR(TCP_RETRANSMIT_QUEUE, LCN);
  6955.      QUEUE_CLEAR(TRANSMIT_QUEUE);
  6956.      QUEUE_CLEAR(TCP_RECEIVED_SEGMENT_QUEUE);
  6957.      QUEUE_CLEAR(RECEIVE_QUEUE);
  6958.      QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE);
  6959.      DELETE_A_LCN := TRUE;
  6960.      FLAG := FALSE;
  6961.     elsif THIRTYTWO_BITS(SYSTEM_TIME) >= LCN.NEXT_TIME_WAIT_TIMEOUT and
  6962.           (LCN.NEXT_TIME_WAIT_TIMEOUT > 0) then
  6963.      --Close it up.  User will now be informed it is closed.
  6964.      SOCKET_PARAMS := LCN;    
  6965.      UMESSAGE := ( 18,
  6966.                    SOCKET_PARAMS);
  6967.      MESSAGE_FOR_USER(UMESSAGE);
  6968.      QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  6969.      DELETE_A_LCN := TRUE;
  6970.      FLAG := FALSE;
  6971.     elsif QUEUE_SIZE(TCP_RETRANSMIT_QUEUE) > 0 then
  6972.      --a more sophisticated retransmission scheme is needed!!
  6973.      while RETRANSMIT loop
  6974.       if THIRTYTWO_BITS(SYSTEM_TIME) >=
  6975.           QUEUE_RETRANS_TIME(LCN) +  15
  6976.           --THIRTYTWO_BITS (LCN.RETRANS_INTERVAL) *
  6977.           --THIRTYTWO_BITS (100) --for VAX
  6978.           then
  6979.        --retransmit a segment
  6980.        RETRANS_TCP(LCN);
  6981.        new_line;--for debug(JB 3/6/85)
  6982.        put_line("just sent a retrans message");
  6983.        new_line;
  6984.        FLAG := FALSE;
  6985.       else
  6986.        RETRANSMIT := FALSE;
  6987.       end if;
  6988.      end loop;
  6989.      --reset the retransmit flag for the next lcn
  6990.      RETRANSMIT := TRUE; --do it the first time
  6991.     end if;
  6992.    end if; --main if
  6993.    if LCN.STATE = T_TCP_GLOBALS_DATA_STRUCTURES.ESTABLISHED and then
  6994.        (not QUEUE_EMPTY(TRANSMIT_QUEUE, LCN)) then
  6995.     SEND_FROM_TRANSMIT_QUEUE(LCN);
  6996.    end if;
  6997.    TEMP_HOLDER_LCN := LCN;
  6998.    LCN := LCN.NEXT;--obtain next connection
  6999.    if DELETE_A_LCN then
  7000.     TCB_CLEAR( TEMP_HOLDER_LCN ) ;
  7001.     TCB_FREE( TEMP_HOLDER_LCN ) ;
  7002.     DELETE_A_LCN := FALSE ;
  7003.    end if;
  7004.   end loop;
  7005.     WAIT( TASK_MESSAGE ) ;
  7006.    -- NOTE THE TASK MESSAGE IS A VARIANT RECORD WHICH WILL BE DELETED FROM
  7007.    -- QUEUE BY QUEING ROUTINE.
  7008.    case TASK_MESSAGE.EVENT is
  7009.     when SEND  =>     -- SET    LOCAL FIELDS FROM QUEUE    RECORD
  7010.      if DETERMINE_VALID_LCN( TASK_MESSAGE.SEND_PARAMETERS.LCN ) then
  7011.       TCP_SEND( TASK_MESSAGE.SEND_PARAMETERS.LCN, 
  7012.                 TASK_MESSAGE.SEND_PARAMETERS.BUFPTR, 
  7013.                   TASK_MESSAGE.SEND_PARAMETERS.BYTE_COUNT, 
  7014.             TASK_MESSAGE.SEND_PARAMETERS.PUSH_FLAG,
  7015.             TASK_MESSAGE.SEND_PARAMETERS.URG_FLAG,    
  7016.             TASK_MESSAGE.SEND_PARAMETERS.TIMEOUT );
  7017.       else
  7018.        PUT_LINE("BOGUS SEND LCN");
  7019.       end if;     
  7020.     when RECEIVE => --SET LOCAL FIELDS FROM QUEUE MESSAGE RECORD
  7021.      if DETERMINE_VALID_LCN( TASK_MESSAGE.RECEIVE_PARAMETERS.LCN ) then
  7022.       TCP_RECEIVE( TASK_MESSAGE.RECEIVE_PARAMETERS.LCN,
  7023.                  TASK_MESSAGE.RECEIVE_PARAMETERS.BUFPTR,
  7024.                TASK_MESSAGE.RECEIVE_PARAMETERS.BYTE_COUNT ) ;
  7025.      else
  7026.       PUT_LINE("BOGUS RECEIVE LCN");
  7027.      end if;
  7028.     when ABOR_T => 
  7029.      if DETERMINE_VALID_LCN( TASK_MESSAGE.ABORT_CLOSE_PARAMETERS.LCN)
  7030.                                                                 then
  7031.       TCP_ABORT( TASK_MESSAGE.ABORT_CLOSE_PARAMETERS.LCN ) ; 
  7032.        -- ABORT THE CONNECTION
  7033.      else
  7034.       PUT_LINE("BOGUS ABORT LCN");
  7035.      end if;
  7036.     when WITH_TCP_COMMUNICATE.CLOSE =>    
  7037.      if DETERMINE_VALID_LCN( TASK_MESSAGE.ABORT_CLOSE_PARAMETERS.LCN ) then
  7038.       TCP_CLOSE( TASK_MESSAGE.ABORT_CLOSE_PARAMETERS.LCN ) ;
  7039.      else
  7040.       PUT_LINE("BOGUS CLOSE LCN");
  7041.      end if;
  7042.     when WITH_TCP_COMMUNICATE.OPEN => 
  7043.      -- WE WILL SET THE LOCAL CONNECTION NAME HERE. IT WILL
  7044.      -- BE THE LOCAL PORT NUMBER TEMPORARILY.    
  7045.           TCP_OPEN( TASK_MESSAGE.OPEN_PARAMETERS.LOCAL_PORT,
  7046.            TASK_MESSAGE.OPEN_PARAMETERS.FOREIGN_PORT,
  7047.            TASK_MESSAGE.OPEN_PARAMETERS.FOREIGN_NET_HOST,
  7048.            TASK_MESSAGE.OPEN_PARAMETERS.ACTIVE_PASSIVE,
  7049.            TASK_MESSAGE.OPEN_PARAMETERS.BUFFER_SIZE,
  7050.            TASK_MESSAGE.OPEN_PARAMETERS.TIMEOUT,
  7051.            TASK_MESSAGE.OPEN_PARAMETERS.LCN,
  7052.            TASK_MESSAGE.OPEN_PARAMETERS.SECURITY,
  7053.            TASK_MESSAGE.OPEN_PARAMETERS.PRECEDENCE,
  7054.            TASK_MESSAGE.OPEN_PARAMETERS.OPTIONS ) ;
  7055.     when STATUS =>
  7056.      if DETERMINE_VALID_LCN( TASK_MESSAGE.STATUS_PARAMETERS.LCN ) then
  7057.       TCP_STATUS( TASK_MESSAGE.STATUS_PARAMETERS.LCN ) ;
  7058.       -- THIS CONDITION MODELS THE TIME-OUT IN THE TIME-WAIT STATE WHICH USES
  7059.       -- A TIMER TO ENSURE THE CONNECTION IS CLOSED.
  7060.      else
  7061.       PUT_LINE("BOGUS STATUS LCN");
  7062.      end if;
  7063.     when TIMEOUT_IN_TIME_WAIT =>
  7064.      -- checked by tcp controller
  7065.      null;
  7066.     when ERROR_MESSAGE =>     
  7067.      TCP_ERROR( TASK_MESSAGE.ERROR_PARAMETERS.ERROR_INDICATOR ) ;
  7068.     when TIMEOUT_IN_RETRANS_QUEUE =>
  7069.      -- checked by tcp controller
  7070.      null;
  7071.     when DATA_FROM_IP => 
  7072.      TCP_SEG_ARRIVE( TASK_MESSAGE.DATA_FROM_IP_PARAMETERS.BUFPTR,
  7073.                  TASK_MESSAGE.DATA_FROM_IP_PARAMETERS.BYTE_COUNT,
  7074.              TASK_MESSAGE.DATA_FROM_IP_PARAMETERS.SOURCE_ADDRESS,
  7075.              TASK_MESSAGE.DATA_FROM_IP_PARAMETERS.DESTINATION_ADDRESS,
  7076.                TASK_MESSAGE.DATA_FROM_IP_PARAMETERS.PROTOCOL,
  7077.              TASK_MESSAGE.DATA_FROM_IP_PARAMETERS.TOS,
  7078.              TASK_MESSAGE.DATA_FROM_IP_PARAMETERS.SECURITY);
  7079.     when TIMER_TIMEOUT => 
  7080.      null;
  7081.     when NO_TCP_ACTION => 
  7082.       --TEXT_IO.put_line("NO_TCP_ACTION");--for debug (JB 1/31/85)
  7083.      null;
  7084.   end case;
  7085. exception
  7086.  when CONSTRAINT_ERROR =>
  7087.   PUT_LINE("A CONSTRAINT ERROR WAS UNHANDLED IN TCP");
  7088.  when others =>
  7089.   PUT_LINE("UNKNOWN ERROR IN UNKNOWN ROUTINE OF TCP");
  7090. end TCP_CONTROLLER;
  7091. end TCP_CONTROLLER_TASK ;
  7092. --::::::::::::::
  7093. --tcpglbda1.txt
  7094. --::::::::::::::
  7095. -----------------------------------------------------------------------
  7096. --
  7097. --         DoD Protocols    NA-00008-200       80-01196-100(-)
  7098. --         E-Systems, Inc.  August 07, 1985
  7099. --
  7100. --         tcpglbda1.txt       Author : Jim Baldo
  7101. --
  7102. -----------------------------------------------------------------------
  7103. with IP_GLOBALS;                use IP_GLOBALS;
  7104. with BUFFER_DATA;        use BUFFER_DATA;
  7105. with WITH_IP_COMMUNICATE;    use WITH_IP_COMMUNICATE;
  7106. with MODULO;            use MODULO;
  7107.         package T_TCP_GLOBALS_DATA_STRUCTURES is
  7108.     -----------------------------------------------------------
  7109.     --This implementation is for use with the Telesoft Ada   --
  7110.     --compiler version 1.5 .                                 --
  7111.     -----------------------------------------------------------
  7112. --*****************************************************************************
  7113. --*Implementation Restrictions                                                *
  7114. --*---------------------------                                                *
  7115. --* Some of these types could have their bit size set when the compiler       *
  7116. --* is able to do it.                                                         *
  7117. --*****************************************************************************
  7118.     TABLE_RANGE : constant SIXTEEN_BITS := 32;
  7119.     subtype ERROR_TYPE is SIXTEEN_BITS;
  7120.     type STATUS_TYPE is 
  7121.         (CONNECTION_OPEN, CONNECTION_CLOSED, OPENING, CLOSING);
  7122.     type ACKPASS is (PASSIVE, ACTIVE);
  7123.     type TIMER_TYPE is (TIME_WAIT_TIMER, RETRANS_TIMER, TIMEOUT_TIMER);
  7124.     type HEADER_TYPE is 
  7125.         (ACK, SYN, SYN_ACK, SEGMENT, SEG_ACK, FIN, RST, RST_ACK);
  7126.     type STATES is (CLOSED,SYN_SENT,SYN_RECEIVED,ESTABLISHED,LISTEN,
  7127.         FIN_WAIT_1,CLOSE_WAIT,FIN_WAIT_2,CLOSING,TIME_WAIT,LAST_ACK);
  7128.     type SECURE is array(1..9) of SIXTEEN_BITS; 
  7129.                     -- EACH ELEMENT OF THIS ARRAY IS ONE
  7130.                        -- OCTET OF SECURITY OPTION INFO. AFTER
  7131.                        -- THE TYPE AN LENGTH FIELD.
  7132.     type TABLE_TYPE is array(1..TABLE_RANGE) of SIXTEEN_BITS;
  7133.     type TIME_ACTION is (NONE, RETRANSMIT_TIMEOUT, CONNECTION_TIMEOUT, 
  7134.              TIME_WAIT_TIMEOUT);
  7135.     subtype    WND_PORT is SIXTEEN_BITS; -- THE ACTUAL RANGE IS + OR - 2**16 - 1
  7136.     subtype    SEVEN_BITS is SIXTEEN_BITS;
  7137.     subtype    TEN_BITS is SIXTEEN_BITS;
  7138.     subtype    THREE_BITS is SIXTEEN_BITS;
  7139.     subtype    TWO_BITS is SIXTEEN_BITS;
  7140.     subtype    FOUR_OCTETS is THIRTYTWO_BITS;
  7141.     subtype    TWO_OCTETS is SIXTEEN_BITS;
  7142.     subtype    ONE_OCTET is SIXTEEN_BITS;
  7143.     subtype    HALF_OCTET is SIXTEEN_BITS;
  7144.     subtype    SIX_BITS is SIXTEEN_BITS;
  7145.     subtype    ONE_BIT    is SIXTEEN_BITS;
  7146.     type BUFFER_POINTER is
  7147.         record
  7148.             BTYPE :    SIXTEEN_BITS;
  7149.             DATA_LEN : SIXTEEN_BITS := 0;
  7150.             SOURCE_PORT : TWO_OCTETS;
  7151.             DESTINATION_PORT : TWO_OCTETS;
  7152.             SEQ_NUM    : MODULAR;
  7153.             ACK_NUM    : MODULAR;
  7154.             DATA_OFFSET : HALF_OCTET;
  7155.             RESERVED : SIX_BITS;
  7156.             URG_FLAG : ONE_BIT;
  7157.             ACK : ONE_BIT;
  7158.             PUSH_FLAG : ONE_BIT;
  7159.             RST : ONE_BIT;     
  7160.             SYN : ONE_BIT;
  7161.             FIN : ONE_BIT;
  7162.             WINDOW : TWO_OCTETS;
  7163.             TCP_CSUM : TWO_OCTETS;
  7164.             URG_PTR    : TWO_OCTETS;
  7165.                   --OPTIONS FOR TCP
  7166.             TCP_OPTIONS : OPTION_TYPE 
  7167.                        := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  7168.                          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  7169.                          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  7170.                          0);
  7171.             DATA : BUFFER_AREA;
  7172.                 -- ARRAY OF SYSTEM.BYTES. FROM USER LEVEL.
  7173.         end record;
  7174.     ERROR_TABLE_CLEAR : constant TABLE_TYPE 
  7175.                 := (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  7176.                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  7177.                   0, 0, 0, 0, 0, 0, 0);
  7178. --*********************QUEUE TYPES******************************
  7179.     type QNAME is (TRANSMIT_QUEUE, TCP_RETRANSMIT_QUEUE, 
  7180.                TCP_RECEIVED_SEGMENT_QUEUE, RECEIVE_QUEUE,
  7181.            PROCESSED_SEGMENTS_FOR_USER_QUEUE);
  7182.     type STD_Q_ITEM is 
  7183.         record
  7184.             BUFFER : PACKED_BUFFER_PTR;
  7185.             UNPACKED_BUFFER : BUFFER_POINTER;
  7186.             LENGTH : SIXTEEN_BITS;
  7187.         end record;
  7188.     type STD_QUEUE_ELEMENT;
  7189.     type STD_QUEUE_ELEMENT_POINTER is access STD_QUEUE_ELEMENT;
  7190.     type STD_QUEUE_ELEMENT is 
  7191.         record
  7192.             ELEMENT : STD_Q_ITEM;
  7193.             TIME : THIRTYTWO_BITS; -- FOR THE RETRANSMISSION TIME.
  7194.             IP_ID : SIXTEEN_BITS; -- THE IP ID FOR RETRANSMISSION
  7195.             NEXT : STD_QUEUE_ELEMENT_POINTER;
  7196.         end record;
  7197.     type STD_HEAD_PTR is
  7198.         record
  7199.             ELEMENT_COUNT : SIXTEEN_BITS;
  7200.             FIRST_ELEMENT : STD_QUEUE_ELEMENT_POINTER;
  7201.             LAST_ELEMENT : STD_QUEUE_ELEMENT_POINTER;
  7202.         end record;
  7203.     type STD_QUEUE_HEAD_POINTERS is array(QNAME) of STD_HEAD_PTR;
  7204. --*********************QUEUE TYPES******************************
  7205.     NUMBER_OF_QUEUES : constant SIXTEEN_BITS := 5;
  7206.     MAX_QUEUE_SIZE : constant SIXTEEN_BITS := 32;
  7207.     INITIAL_QUEUE_HEADER : STD_HEAD_PTR := (0, NULL, NULL);
  7208.     INITIAL_QUEUE_HEADER_POINTERS : STD_QUEUE_HEAD_POINTERS := 
  7209.     (INITIAL_QUEUE_HEADER, INITIAL_QUEUE_HEADER, INITIAL_QUEUE_HEADER, 
  7210.      INITIAL_QUEUE_HEADER, INITIAL_QUEUE_HEADER);
  7211.     type TRANSMISSION_CONTROL_BLOCK;
  7212.         type TCB_PTR is access TRANSMISSION_CONTROL_BLOCK;
  7213.         
  7214.         type TRANSMISSION_CONTROL_BLOCK    is 
  7215.         record
  7216.             STATE : STATES;
  7217.             CONNECTION_STATUS : STATUS_TYPE;
  7218.             LOCAL_PORT : SIXTEEN_BITS := -1;
  7219.             LOCAL_NET : SIXTEEN_BITS := 0;--TEMPORARY**
  7220.             LOCAL_HOST : SIXTEEN_BITS := 1;-- TEMPORARY**
  7221.             SOURCE_ADDRESS : THIRTYTWO_BITS := 1;-- TEMPORARY**
  7222.             DESTINATION_ADDRESS : THIRTYTWO_BITS;
  7223.             FOREIGN_PORT : SIXTEEN_BITS := -1;
  7224.             FOREIGN_HOST : THIRTYTWO_BITS := -1;
  7225.             FOREIGN_NET : THIRTYTWO_BITS := -1;
  7226.             SND_UNA : MODULAR;
  7227.             SND_UP : MODULAR;
  7228.             SND_NXT : MODULAR;
  7229.             SND_WND : SIXTEEN_BITS := 190;
  7230.             RCV_NXT : MODULAR;
  7231.             PRECEDENCE : SIXTEEN_BITS := 0;
  7232.             USER_NOTIFICATION : BOOLEAN := FALSE;
  7233.             SECURITY : SECURE := (0, 0, 0, 0, 0, 0, 0, 0, 0);
  7234. --    SOURCE_PORT    : SIXTEEN_BITS;   --    LIMITED    BITS AND RANGE IS YET TO BE DET
  7235. --    ERMINED
  7236.             BUFFSIZE : SIXTEEN_BITS;
  7237.             RCV_BUFFER_SIZE : WND_PORT;
  7238.             RCV_URGENT_POINTER : SIXTEEN_BITS;
  7239.             SND_WL1 : MODULAR; -- SEQ NUM OF THE  LAST SEGMENT 
  7240.                        --USED TO UPDATE SND.WND
  7241.             SND_WL2 : MODULAR;-- RECORDS THE ACK NUM OF THE 
  7242.             --LAST SEGMENT USED TO
  7243.             -- UPDATE SND.WND. THIS    VARIABLE AND THE ABOVE ONE
  7244.             -- PREVENT AN OLD SEGMENT FROM BEING USED TO UPDATE
  7245.             -- THE WINDOW.
  7246.             RCV_WINDOW : WND_PORT := 190;
  7247.             INIT_RCV_SEQ_NUM : MODULAR;
  7248.             ISS : MODULAR;-- THE INITIAL SEND SEQUENCE NUMBER (ISS)
  7249.             RETRANS_INTERVAL : SIXTEEN_BITS := 30;  
  7250.                 -- LAST ARE PROBABLY TEMPORARY
  7251.             MAX_RETRY_OF_PACKET : SIXTEEN_BITS RANGE 0..8;
  7252.             PROTOCOL : SIXTEEN_BITS := 0;
  7253.                 --(PTCL) UNKNOWN VALUE FOR TCP***
  7254.             ACTIVE_PASSIVE : ACKPASS;
  7255.             CLOSE_PENDING : BOOLEAN := FALSE; 
  7256.                 -- FOR A CLOSE WITH DATA TO SEND.
  7257.             ERROR_TABLE : TABLE_TYPE := ERROR_TABLE_CLEAR;
  7258.             QHEADS : STD_QUEUE_HEAD_POINTERS 
  7259.                 := INITIAL_QUEUE_HEADER_POINTERS;
  7260.             IDENT : SIXTEEN_BITS := -1; 
  7261.                 -- THE IDENTIFICATION NUMBER FOR AN IP DATAGRAM
  7262.             RETRANS_IDENT : SIXTEEN_BITS; 
  7263.             -- SUPPLIED BY THE QUEUE RETRANS ROUTINE FOR IP.
  7264.             NEXT_CONNECTION_TIMEOUT : THIRTYTWO_BITS;
  7265.             NEXT_TIME_WAIT_TIMEOUT : THIRTYTWO_BITS;
  7266.             CONNECTION_TIMEOUT : SIXTEEN_BITS := 180; 
  7267.                 -- DEFAULT IS 180 SECONDS OR 3 MINUTES
  7268.             CLOSE_OK_NOTIFICATION : BOOLEAN := FALSE;
  7269.                         NEXT : TCB_PTR;
  7270.     end record;
  7271. -- THE PSEUDO HEADER
  7272.     SOURCE, DESTINATION : THIRTYTWO_BITS;
  7273.     PROTOCOL, IP_TOS : SIXTEEN_BITS;
  7274.     -- THE SECURITY OPTION FROM IP
  7275.     SECURITY : SECURE;
  7276.     SECURE_CLEAR : SECURE := (0, 0, 0, 0, 0, 0, 0, 0, 0);
  7277.     LEN, IDENT  : SIXTEEN_BITS;
  7278.     LCN_TCB_STATE :    STATES;
  7279.     TYPE_FLAG : HEADER_TYPE;
  7280.     RESERVE : TCB_PTR;
  7281.     BIT_SET : constant SIXTEEN_BITS := 1;
  7282.         LCN : TCB_PTR; -- THE GLOBAL LOCAL CONNECTION NAME
  7283.     OPTIONS : OPTION_TYPE;
  7284. -- THESE DECLARATIONS ARE CONSTANT IP PARAMETERS.
  7285.     ONE_MINUTE : constant SIXTEEN_BITS := 60; --    00111100
  7286.     TOS : constant SIXTEEN_BITS := 0; 
  7287.         --    THE VALUE FROM TCP SPEC    FOR THE    IP AS THE LOWER
  7288.                 --    LEVEL PROTOCOL.
  7289.     TTL : constant SIXTEEN_BITS := ONE_MINUTE;
  7290.     DONT_FRAGMENT :    constant SIXTEEN_BITS := 1; -- WE ARE NOT A GATEWAY.
  7291.     CLEAR : OPTION_TYPE 
  7292.         := (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,
  7293.             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);
  7294.     TCP_SECURITY_OPTIONS : OPTION_TYPE 
  7295.                 := (130,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  7296.                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  7297.                        0,0,0,0,0,0,0,0,0,0,0,0);
  7298. end T_TCP_GLOBALS_DATA_STRUCTURES;
  7299. --::::::::::::::
  7300. --tcpglobals.txt
  7301. --::::::::::::::
  7302. -----------------------------------------------------------------------
  7303. --
  7304. --         DoD Protocols    NA-00008-200       80-01197-100(-)
  7305. --         E-Systems, Inc.  August 07, 1985
  7306. --
  7307. --         tcpglobals.txt       Author : Jim Baldo
  7308. --
  7309. -----------------------------------------------------------------------
  7310. with IP_GLOBALS ;            use IP_GLOBALS ;
  7311. with T_TCP_GLOBALS_DATA_STRUCTURES;    use T_TCP_GLOBALS_DATA_STRUCTURES;
  7312. with BUFFER_DATA;            use BUFFER_DATA;
  7313.             package    TCP_GLOBALS is
  7314.         ----------------------------------------------------
  7315.         --This implementation is for use with the DEC/Ada --
  7316.         --compiler .                                      --
  7317.         ----------------------------------------------------
  7318. -------------------------------------------------------------------------------
  7319. --This    package    contains all necessary global variables    for any    tcp routine. --
  7320. --This includes the TCB and any operations necessary to operate on the global--
  7321. -- data.                                                                     --
  7322. -------------------------------------------------------------------------------
  7323. procedure PACK_BUFFER_INTO_BIT_STREAM( BUFPTR : in 
  7324.                                  T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER; 
  7325.                                        PACKED_BUFFER : in PACKED_BUFFER_PTR);
  7326.     --This subprogram will break up a record of integers, long_integers, 
  7327.     --and modular types into system bytes.  It uses the function 
  7328.     --unchecked_conversion to move integers, etc. into the array of system 
  7329.     --bytes.
  7330. procedure TCP_HEADER_FORMAT( LCN : in TCB_PTR; 
  7331.                              BUFPTR : in out 
  7332.                               T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  7333.                          TYPE_FLAG : in HEADER_TYPE; 
  7334.                              OPTIONS : in OPTION_TYPE);
  7335.     --This subprogram is responsible for formatting a TCP header for any 
  7336.     --type of segment.  The segment type is denoted by the type_flag.  A 
  7337.     --checksum will be performed over the formatted header and conceptual 
  7338.     --pseudo header.  All header fields are reset and/or filled in.
  7339. function CHECKSUM( TCP_HEADER_LENGTH : in SIXTEEN_BITS ; 
  7340.                    PACKED_BUFFER : in PACKED_BUFFER_PTR;
  7341.                DESTINATION, SOURCE : in THIRTYTWO_BITS ; 
  7342.                    PROTOCOL : in SIXTEEN_BITS ) return SIXTEEN_BITS ;
  7343.     --This function performs the 16 bit one's complement checksum over the
  7344.     --entire TCP header and data as well as the 96 bit pseudo header which 
  7345.     --is the source and destination address, the protocol, and the TCP 
  7346.     --length.
  7347. procedure TCP_ERROR( ERROR_INDICATION : in ERROR_TYPE);
  7348.     --This subprogram is called upon an error occurrence. Currently it 
  7349.     --simply increments a counter in the appropriate TCB'S table.
  7350. function FOREIGN_SOCKET_UNSPECIFIED( LCN : in TCB_PTR) return boolean;
  7351.     --This subprogram attempts to determine if the foreign socket is
  7352.     --unspecified by checking for illegal values and the net and host
  7353.     --addresses the same (as they were initialized).
  7354. function ISS return THIRTYTWO_BITS ;
  7355.     --This function gets the local time in milliseconds and multiplies it
  7356.     --by 250 to determine the ISS.  This means it will cycle approximately
  7357.     --every 4.55 hours.
  7358. procedure ADDRESS_DECODER( CONCATENATION : in THIRTYTWO_BITS );
  7359.     --This subprogram will determine the form of the net and host addresses
  7360.     --from the first three bits of the concatenated form. It will then 
  7361.     --separate and decode the bits into the proper TCB varibles by using
  7362.     --unchecked conversions between types. The format of the concatenated
  7363.     --version can be found in the IP spec.
  7364. procedure INSERT_TEXT_IN_BUFFER( LENGTH : in SIXTEEN_BITS ; 
  7365.                                  RECEIVED_PACKED_BUFFER : in PACKED_BUFFER_PTR;
  7366.                                  DATA_LENGTH : in SIXTEEN_BITS ;
  7367.                              PACKED_BUFFER : in PACKED_BUFFER_PTR);
  7368.     --This subprogram will put a slice of data from one array of sytem 
  7369.     --bytes to another of system bytes.  It begins at the points in the 
  7370.     --respective arrays as indicated by their first element.
  7371. procedure TIMEOUT_CHECK( LCN : in TCB_PTR; ACTION : out TIME_ACTION);
  7372.     --This subprogram determines if the connection has timeout, waiting 
  7373.     --for a timeout, or retransmit timeout has occured.  An action result 
  7374.     --parameter indicating which of previously described events has 
  7375.     --occurred is returned.  The LCN parameter is passed to the subprogram.
  7376. procedure START_TIMER(LCN : in TCB_PTR; TIMER : in TIMER_TYPE);
  7377.     --This procedure will reset the connection timeout timer in a TCB
  7378.     --or the time wait timer as specified by an LCN.  There will be a 
  7379.     --problem when the clock cycles after 6 hours, but this can be taken 
  7380.     --care of with the modular type.
  7381. end TCP_GLOBALS;
  7382. with QUEUES;                use QUEUES;
  7383. with SYSTEM;
  7384. with MODULO;                use MODULO;
  7385. with TEXT_IO;                           use TEXT_IO, INTEGER_IO;
  7386. with UNCHECKED_CONVERSION;
  7387. with REAL_TIME_CLOCK_AND_DATE;            use REAL_TIME_CLOCK_AND_DATE;
  7388.             
  7389.                         package BODY TCP_GLOBALS is
  7390. DUMMY : CHARACTER;--DEBUG
  7391. procedure PACK_BUFFER_INTO_BIT_STREAM ( BUFPTR : in
  7392.                                  T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER; 
  7393.                                  PACKED_BUFFER : in PACKED_BUFFER_PTR) is
  7394. HEADER_LENGTH : SIXTEEN_BITS  := BUFPTR.DATA_OFFSET * 4;
  7395. INDEX : SIXTEEN_BITS  := PACKED_BUFFER.TCP_PTR;
  7396. LENGTH : SIXTEEN_BITS  := BUFPTR.DATA_LEN + HEADER_LENGTH; 
  7397. -- CURRENTLY THE HEADER
  7398. -- LENGTH IS ALWAYS 20
  7399. -- SINCE NO OPTIONS ARE
  7400. -- IMPLEMENTED.
  7401.  procedure PUT_AN_INTEGER_IN_THE_BUFFER(VALUE : SIXTEEN_BITS ) is
  7402.   type STUPID is array(1..1) of SIXTEEN_BITS ;
  7403.   type TWO_BYTES is array(1..2) of SYSTEM.BYTE;
  7404.   function CONVERT_INTEGER_TO_BYTES is new
  7405.      UNCHECKED_CONVERSION(STUPID,TWO_BYTES);
  7406.   TEMP_INT : STUPID;
  7407.   BYTES_FROM_INTEGER : TWO_BYTES;
  7408.  begin
  7409.   TEMP_INT(1) := VALUE;
  7410.   BYTES_FROM_INTEGER := CONVERT_INTEGER_TO_BYTES(TEMP_INT);
  7411.   PACKED_BUFFER.BYTE( INDEX + SIXTEEN_BITS ( 2 ) - 1 ) :=
  7412.              BYTES_FROM_INTEGER(1);
  7413.   PACKED_BUFFER.BYTE( INDEX + SIXTEEN_BITS ( 1 ) - 1 ) :=
  7414.                BYTES_FROM_INTEGER(2);
  7415.   INDEX := INDEX + 2;
  7416. exception
  7417.  when others =>
  7418.   TEXT_IO.PUT_LINE("ERROR IN PUT INTEGER INTO BUFFER");
  7419.   INTEGER_IO.PUT(INDEX);
  7420. end PUT_AN_INTEGER_IN_THE_BUFFER;
  7421. procedure PUT_A_LONG_INTEGER_IN_THE_BUFFER
  7422.       (DOUBLE_WORD : THIRTYTWO_BITS ) is
  7423.  type STUPID_LONG is array(1..1) of THIRTYTWO_BITS ;
  7424.  type FOUR_BYTES is array(1..4) of SYSTEM.BYTE ;
  7425.  function CONVERT_LONG_INT_TO_BYTES is new 
  7426.    UNCHECKED_CONVERSION(STUPID_LONG,FOUR_BYTES);
  7427.  TEMP_LONG_INT : STUPID_LONG;
  7428.  BYTES_FROM_LONG_INT : FOUR_BYTES;
  7429. begin
  7430.  TEMP_LONG_INT(1) := DOUBLE_WORD;
  7431.  BYTES_FROM_LONG_INT := CONVERT_LONG_INT_TO_BYTES(TEMP_LONG_INT);
  7432.  for I in 1..4 loop -- PUT THEM IN
  7433.   PACKED_BUFFER.BYTE( INDEX + SIXTEEN_BITS(5 - I) - 1 ) := 
  7434.              BYTES_FROM_LONG_INT(I);
  7435.  end loop;
  7436.  INDEX := INDEX + 4;
  7437. exception
  7438.  when others =>
  7439.   TEXT_IO.PUT_LINE("ERROR IN PUT LONG INTEGER INTO BUFFER");
  7440.   INTEGER_IO.PUT(INDEX);
  7441. end PUT_A_LONG_INTEGER_IN_THE_BUFFER;
  7442. begin
  7443.  -- SET UP THE INITIAL INDEX
  7444.  INDEX := (INDEX - HEADER_LENGTH) + 1;-- THEIR DIFFERENCE PLUS 1 
  7445.                                              -- SO PROPER # PLACES USED
  7446.                  -- DATA IS ALREADY IN BUFFER.
  7447.  PACKED_BUFFER.TCP_PTR := INDEX;
  7448.  PUT_AN_INTEGER_IN_THE_BUFFER(BUFPTR.SOURCE_PORT);
  7449.  PUT_AN_INTEGER_IN_THE_BUFFER(BUFPTR.DESTINATION_PORT);
  7450.  PUT_A_LONG_INTEGER_IN_THE_BUFFER( LONG(BUFPTR.SEQ_NUM));
  7451.  PUT_A_LONG_INTEGER_IN_THE_BUFFER( LONG(BUFPTR.ACK_NUM));
  7452. -- PUT IN SOME SMALL FIELDS AND BIT FIELDS
  7453.  PACKED_BUFFER.BYTE(INDEX) := SYSTEM.BYTE ( BUFPTR.DATA_OFFSET * 16 ) ;
  7454.  PACKED_BUFFER.BYTE(INDEX+1) := SYSTEM.BYTE ( BUFPTR.URG_FLAG * 32 +
  7455.    BUFPTR.ACK * 16 + BUFPTR.PUSH_FLAG * 8 + BUFPTR.RST * 4 +
  7456.                BUFPTR.SYN * 2 + BUFPTR.FIN ) ;
  7457.  INDEX := INDEX + 2;
  7458.  PUT_AN_INTEGER_IN_THE_BUFFER(BUFPTR.WINDOW);
  7459.  -- CLEAR THE CHECKSUM FIELD
  7460.  PACKED_BUFFER.BYTE(INDEX) := 0; 
  7461.  PACKED_BUFFER.BYTE(INDEX+1) := 0;
  7462.  INDEX := INDEX + 2;
  7463.  PUT_AN_INTEGER_IN_THE_BUFFER(BUFPTR.URG_PTR);
  7464.  -- NOW WE PUT THE OPTIONS IN THE BUFFER. HOWEVER THEY ARE 
  7465.  -- CURRENTLY NOT IMPLEMENTED
  7466.  -- HERE WE COULD PUT THE DATA IN THE BUFFER.
  7467.  --FOR I IN 1..LENGTH - HEADER_LENGTH LOOP
  7468.  -- PACKED_BUFFER.BYTE(INDEX + I - 1) := BUFPTR.DATA(I);
  7469.  --END LOOP;
  7470.  -- PERFORM THE HEADER CHECKSUM
  7471.  INDEX := INDEX - 4; -- TO POINT TO THE CHECKSUM FIELD.
  7472.  PUT_AN_INTEGER_IN_THE_BUFFER(CHECKSUM(LENGTH, 
  7473.                                        PACKED_BUFFER, 
  7474.                                        LCN.DESTINATION_ADDRESS,
  7475.                                        LCN.SOURCE_ADDRESS, 
  7476.                                        5)
  7477.                               ); 
  7478.  -- SET THE POINTER FOR THE NEXT LAYER
  7479.  PACKED_BUFFER.IP_PTR := PACKED_BUFFER.TCP_PTR - 1;
  7480.  exception
  7481.  when others =>
  7482.   TEXT_IO.PUT_LINE("ERROR IN PACK BUFFER MAIN");
  7483.   INTEGER_IO.PUT(INDEX);
  7484.   TEXT_IO.PUT_LINE("");
  7485.   INTEGER_IO.PUT(LENGTH);
  7486. end PACK_BUFFER_INTO_BIT_STREAM;
  7487. procedure TCP_HEADER_FORMAT ( LCN : in TCB_PTR; 
  7488.                               BUFPTR : in out 
  7489.                                T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  7490.                       TYPE_FLAG : in HEADER_TYPE; 
  7491.                               OPTIONS : in OPTION_TYPE) is
  7492. pragma SUPPRESS(OVERFLOW_CHECK);-- ENABLES MOD 2**16 IDENT FOR THE IP.
  7493. begin
  7494.  LCN.IDENT := LCN.IDENT + 1; -- INCREMENT IP ID NUMBER.
  7495.  IDENT := LCN.IDENT; -- SET UP THE PARAMETER FOR CALL TO IP
  7496.  -- HERE WE INITIALIZE THE COMMONNLY UNUSED PORTIONS OF THE HEADER.
  7497.  BUFPTR.URG_PTR := 0;
  7498.  BUFPTR.ACK := 0;
  7499.  BUFPTR.URG_FLAG := 0; 
  7500.  -- WE CURRENTLY DO NOT IMPLEMENT THE URGENT OPTION ON SENDS.
  7501.  BUFPTR.PUSH_FLAG := 0; 
  7502.  -- WE CURRENTLY DO NOT IMPLEMENT THE PUSH OPTION ON SENDS.
  7503.  BUFPTR.RST := 0;
  7504.  BUFPTR.SYN := 0;
  7505.  BUFPTR.FIN := 0;
  7506.  case TYPE_FLAG is
  7507.   when ACK => 
  7508.    BUFPTR.ACK := BIT_SET;
  7509.   when RST => 
  7510.    BUFPTR.RST := BIT_SET;
  7511.   when SYN => 
  7512.    BUFPTR.SYN := BIT_SET;
  7513.   when SYN_ACK => 
  7514.    BUFPTR.ACK := BIT_SET;
  7515.    BUFPTR.SYN := BIT_SET;
  7516.   when SEGMENT => 
  7517.    BUFPTR.ACK := BIT_SET;
  7518.   -- HERE WE WOULD CHECK IF WE NEED TO SET OUR URGENT POINTER.
  7519.   when SEG_ACK => 
  7520.    BUFPTR.ACK := BIT_SET;
  7521.    -- HERE WE WOULD CHECK IF WE NEED TO SET OUR URGENT POINTER.
  7522.   when FIN => 
  7523.    BUFPTR.FIN := BIT_SET;
  7524.    BUFPTR.ACK := BIT_SET; -- THE ACK BIT MUST ALWAYS BE SET.
  7525.   when RST_ACK => BUFPTR.RST := BIT_SET;
  7526.    BUFPTR.ACK := BIT_SET;
  7527.  end case;
  7528.  -- FILL IN THE RESET OF THE HEADER.
  7529.  -- NOTE WE DO NOT CURRENTLY IMPLEMENT OPTIONS. 
  7530.  -- THIS MEANS THE DATA OFFSET IS CONSTANT.
  7531.  BUFPTR.DATA_OFFSET := 5;
  7532.  BUFPTR.SOURCE_PORT := LCN.LOCAL_PORT;
  7533.  BUFPTR.DESTINATION_PORT := LCN.FOREIGN_PORT;
  7534.  BUFPTR.SEQ_NUM := LCN.SND_NXT;
  7535.  BUFPTR.ACK_NUM := LCN.RCV_NXT;
  7536.  BUFPTR.WINDOW := LCN.SND_WND;
  7537.  -- WE COULD PERFORM CHECKSUM AND PLACE IT IN THE 
  7538.  -- HEADER HERE BUT IT WILL BE
  7539.  -- DONE BY THE PACK ROUTINE.
  7540. end TCP_HEADER_FORMAT;
  7541. function CHECKSUM ( TCP_HEADER_LENGTH : in SIXTEEN_BITS ; 
  7542.                     PACKED_BUFFER : in PACKED_BUFFER_PTR;
  7543.                 DESTINATION, SOURCE : in THIRTYTWO_BITS ; 
  7544.                     PROTOCOL : in SIXTEEN_BITS ) return SIXTEEN_BITS  is
  7545. --pragma SUPPRESS(OVERFLOW_CHECK);
  7546. type TWO_WORDS is array(1..2) of SIXTEEN_BITS ;
  7547. type TELEHOSE is array(1..1) of THIRTYTWO_BITS ;
  7548. function CONVERSION is neW UNCHECKED_CONVERSION(TELEHOSE, TWO_WORDS);
  7549. START_PTR : SIXTEEN_BITS  := PACKED_BUFFER.TCP_PTR;
  7550. END_PTR : SIXTEEN_BITS  := START_PTR + TCP_HEADER_LENGTH - 1;
  7551. CHECKSUM_TOTAL, TWO_INTEGERS : TWO_WORDS;
  7552. TCSUM : THIRTYTWO_BITS  := 0;
  7553. TEMP1,TEMP2 : THIRTYTWO_BITS  := 0;
  7554. WORD_SHIFT : constant THIRTYTWO_BITS  := 65536;
  7555. HIGH_BYTE : BOOLEAN := FALSE;
  7556. --TRUE; FOR 68000. WORDS ARE BYTE SWAPPED ON VAX.
  7557. CHECKSM, LONG_HOLDER : TELEHOSE;
  7558. begin
  7559.  -- THIS CHECKSUM IS PERFORMED ON THE TCP HEADER AS WELL AS A 96 BIT
  7560.  -- PSEUDO HEADER WHICH IS THE SOURCE AND DESTINATION ADDRESS, 
  7561.  -- THE PROTOCOL, AND THE TCP LENGTH.
  7562.  -- PERFORM THE CHECKSUM OVER THE PSEUDO HEADER.
  7563.  LONG_HOLDER(1) := SOURCE;
  7564.  TWO_INTEGERS := CONVERSION(LONG_HOLDER);
  7565.  TCSUM := THIRTYTWO_BITS (TWO_INTEGERS(1)) +
  7566.  THIRTYTWO_BITS (TWO_INTEGERS(2));
  7567.  LONG_HOLDER(1) := DESTINATION;
  7568.  TWO_INTEGERS := CONVERSION(LONG_HOLDER);
  7569.  TCSUM := TCSUM + THIRTYTWO_BITS (TWO_INTEGERS(1)) + 
  7570.  THIRTYTWO_BITS (TWO_INTEGERS(2));
  7571.  TCSUM := TCSUM + THIRTYTWO_BITS (PROTOCOL) + 
  7572.     THIRTYTWO_BITS ( TCP_HEADER_LENGTH );
  7573. -- NOW DO THE ACTUAL HEADER
  7574.  for I in 0..END_PTR-START_PTR loop
  7575.   if (I /= 16) and I /= 17 then -- DON'T ADD IN THE CHECKSUM
  7576.    if I = 12 then HIGH_BYTE := TRUE;-- NECESSARY FOR VAX BYTE SWAPPING
  7577.    end if;
  7578.    if I = 14 then HIGH_BYTE := FALSE;-- NECESSARY FOR VAX BYTE SWAPPING
  7579.    end if;
  7580.    if I = 20 then HIGH_BYTE := TRUE;-- DATA IS STORED UNSWAPPED.
  7581.    end if;
  7582.    if HIGH_BYTE then
  7583.     TCSUM := TCSUM + THIRTYTWO_BITS (PACKED_BUFFER.BYTE(START_PTR + I)) *
  7584.     THIRTYTWO_BITS ( 2**8 );
  7585.     HIGH_BYTE := FALSE;
  7586.    else
  7587.     HIGH_BYTE := TRUE;
  7588.     TCSUM := TCSUM + THIRTYTWO_BITS (PACKED_BUFFER.BYTE(START_PTR + I));
  7589. end if;
  7590.   end if;
  7591.  end loop;
  7592.  -- GET ONE'S COMPLEMENT
  7593.  TCSUM := (-TCSUM) - 1;
  7594.  CHECKSM(1) := TCSUM;
  7595.  CHECKSUM_TOTAL := CONVERSION(CHECKSM);
  7596.  -- GET BOTH WORDS AND RETURN LOW WORD.
  7597.  return CHECKSUM_TOTAL(2);
  7598. exception
  7599.  when others =>
  7600.   TEXT_IO.PUT_LINE("ERROR IN CHECKSUM");
  7601.   INTEGER_IO.PUT(START_PTR);
  7602.   TEXT_IO.PUT_LINE("END POINTER");
  7603.   INTEGER_IO.PUT(END_PTR);
  7604. end CHECKSUM;
  7605. procedure TCP_ERROR( ERROR_INDICATION : in ERROR_TYPE ) is
  7606. begin
  7607.  -- INCREMENT THE ERROR COUNTER.
  7608.  LCN.ERROR_TABLE(ERROR_INDICATION) := 
  7609.    LCN.ERROR_TABLE(ERROR_INDICATION) + 1;
  7610. end TCP_ERROR;
  7611. function FOREIGN_SOCKET_UNSPECIFIED(LCN : in TCB_PTR) return boolean is
  7612. RESULT : BOOLEAN := FALSE;
  7613. begin
  7614.  -- THIS COULD BE A TROUBLE SPOT IF -1 IS A LEGAL ADDRESS.***
  7615.  if (LCN.FOREIGN_NET = LCN.FOREIGN_HOST) and 
  7616.                  LCN.FOREIGN_PORT = -1 then
  7617.   RESULT := TRUE;
  7618.  end if;
  7619.  return RESULT;
  7620. end FOREIGN_SOCKET_UNSPECIFIED;
  7621. function ISS return THIRTYTWO_BITS  is
  7622. X : THIRTYTWO_BITS  := 0;
  7623. begin
  7624.  -- THE TIME IS IN MILLISECONDS. MULTIPLYING BY 250 
  7625.  -- MAKES THE TIME APPEAR TO BELONG TO A CLOCK 
  7626.  -- INCREMENTED EVERY FOUR MICROSECONDS.
  7627.  return X;-- TEMPORARY FOR TEST(LOCAL_TIME_NOW * 250);
  7628. end ISS;
  7629. procedure ADDRESS_DECODER ( CONCATENATION : in THIRTYTWO_BITS ) is
  7630. type DUMB is array(1..1) of THIRTYTWO_BITS ;
  7631. type TEMP is array(1..4) of SYSTEM.BYTE;
  7632. function CONVERT is new UNCHECKED_CONVERSION(DUMB, TEMP);
  7633. function CONVERT_LONG is new UNCHECKED_CONVERSION(TEMP, DUMB);
  7634. X : DUMB := (1 => CONCATENATION);
  7635. Y,W : TEMP;
  7636. Z : DUMB;
  7637. begin
  7638.  -- THE ADDRESSES ARE CONCATENATED INTO A 32 BIT LONG WORD. THE CODE FOR
  7639.  -- THE TYPES CAN BE FOUND IN THE INTERNET SPECIFICATION.
  7640.  W(1) := 0;
  7641.  W(2) := 0;
  7642.  W(3) := 0;
  7643.  W(4) := 0;
  7644.  Y := CONVERT(X);
  7645.  -- 7 BITS INTERNET ADDRESS AND 24 BITS HOST ADDRESS.
  7646.  if X(1) > 0 then
  7647.  LCN.FOREIGN_NET := THIRTYTWO_BITS (Y(4));
  7648.  Y(4) := 0;
  7649.  Z := CONVERT_LONG(Y);
  7650.  LCN.FOREIGN_HOST := Z(1);
  7651.  -- 14 BITS INTERNET ADDRESS AND 16 HOST ADDRESS.
  7652. elsif SIXTEEN_BITS ( Y(4) ) / 2**6 = 2 then
  7653.  Y(4) := Y(4) - 192 ;
  7654.  W(2) := Y(4);
  7655.  W(1) := Y(3);
  7656.  Z := CONVERT_LONG(W);
  7657.  LCN.FOREIGN_NET := Z(1);
  7658.  W(2) := Y(2);
  7659.  W(1) := Y(1);
  7660.  Z := CONVERT_LONG(W);
  7661.  LCN.FOREIGN_HOST := Z(1);
  7662. elsif SIXTEEN_BITS(Y(4))/2**5 = 6 then
  7663.  -- 21 BITS INTERNET ADDRESS AND 8 HOST ADDRESS.
  7664.  Y(4) := Y(4) - 192 ;
  7665.  W(3) := Y(4);
  7666.  W(2) := Y(3);
  7667.  W(1) := Y(2);
  7668.  Z := CONVERT_LONG(W);
  7669.  LCN.FOREIGN_NET := Z(1);
  7670. LCN.FOREIGN_HOST := THIRTYTWO_BITS (Y(1));
  7671. elsif SIXTEEN_BITS(Y(4))/2**5 = 7 then
  7672.  -- CURRENTLY NO EXTENDED ADDRESSING
  7673.  TCP_ERROR(2);
  7674.  null;
  7675. else
  7676.  TCP_ERROR(3);
  7677. end if;
  7678. exception
  7679. when others =>
  7680.  TEXT_IO.PUT_LINE("ADDRESS DECODER FAILED");
  7681.  for I in 1..4 loop
  7682.   INTEGER_IO.PUT( SIXTEEN_BITS(Y(I)) );
  7683.  end loop;
  7684. -- INTEGER_IO.PUT(LCN);
  7685. end ADDRESS_DECODER;
  7686. procedure INSERT_TEXT_IN_BUFFER( LENGTH : in SIXTEEN_BITS ; 
  7687.                                  RECEIVED_PACKED_BUFFER : in PACKED_BUFFER_PTR; 
  7688.                                  DATA_LENGTH : in SIXTEEN_BITS ;
  7689.                      PACKED_BUFFER : in PACKED_BUFFER_PTR) is
  7690.     -- THE FIRST PARAMETERS ARE THE LENGTH OF THE DATA 
  7691.     -- FIELD IN THE RECEIVE BUFFER  AND THE BUFFER. 
  7692.     -- THE SECOND SET OF PARAMETERS ARE THE LENGTH OF THE DATA 
  7693.     -- BUFFER AND THE DATA BUFFER.
  7694. INDEX, INDEX1 : SIXTEEN_BITS ;
  7695. begin
  7696.  INDEX := RECEIVED_PACKED_BUFFER.TCP_PTR;
  7697.  INDEX1 := PACKED_BUFFER.TCP_PTR;
  7698.  if DATA_LENGTH = LENGTH then
  7699.   RECEIVED_PACKED_BUFFER.BYTE(INDEX..INDEX+LENGTH) := 
  7700.    PACKED_BUFFER.BYTE(INDEX1..INDEX1+LENGTH);
  7701.    RECEIVED_PACKED_BUFFER.TELNET_PTR := RECEIVED_PACKED_BUFFER.TCP_PTR +
  7702.                                         LENGTH - 1;
  7703.  elsif DATA_LENGTH < LENGTH then
  7704.   RECEIVED_PACKED_BUFFER.BYTE(INDEX..INDEX + DATA_LENGTH) :=
  7705.    PACKED_BUFFER.BYTE(INDEX1..INDEX1 + DATA_LENGTH);
  7706.   -- Set the TELNET Pointer
  7707.   RECEIVED_PACKED_BUFFER.TELNET_PTR := RECEIVED_PACKED_BUFFER.TCP_PTR +
  7708.                                       DATA_LENGTH - 1;
  7709.  else -- WE CURRENTLY CAN'T HANDLE THIS CASE.
  7710.   TCP_ERROR(8);
  7711.  end if;
  7712. exception
  7713.  when others =>
  7714.   TEXT_IO.PUT_LINE("ERROR IN INSERT TEXT INTO BUFFER.");
  7715.   INTEGER_IO.PUT(INDEX);
  7716.   INTEGER_IO.PUT(INDEX1);
  7717.   INTEGER_IO.PUT(LENGTH);
  7718. end INSERT_TEXT_IN_BUFFER;
  7719.     procedure TIMEOUT_CHECK(LCN : in TCB_PTR; ACTION : out TIME_ACTION) is
  7720.     TIME : THIRTYTWO_BITS  := THIRTYTWO_BITS(SYSTEM_TIME);
  7721.     RETRANS_TIME : THIRTYTWO_BITS  := QUEUES.QUEUE_RETRANS_TIME(LCN);
  7722.     begin
  7723.      if TIME >= LCN.NEXT_CONNECTION_TIMEOUT then
  7724.       ACTION := CONNECTION_TIMEOUT;
  7725.      elsif TIME >= LCN.NEXT_TIME_WAIT_TIMEOUT then
  7726.       ACTION :=  TIME_WAIT_TIMEOUT;
  7727.       -- WE MUST CHECK THE RETRANS TIMES
  7728.      elsif TIME >= RETRANS_TIME then
  7729.       ACTION := RETRANSMIT_TIMEOUT;
  7730.      end if;
  7731.     end TIMEOUT_CHECK;
  7732.  procedure START_TIMER(LCN : in TCB_PTR; TIMER : in TIMER_TYPE) is
  7733. -- pragma SUPPRESS(OVERFLOW_CHECK);
  7734.  --Note there will be a problem when local time now cycles.
  7735.  --this is every six hours.
  7736.  begin
  7737.   --the MSL is one minute
  7738.   if TIMER = TIMEOUT_TIMER then
  7739.    LCN.NEXT_CONNECTION_TIMEOUT := THIRTYTWO_BITS(SYSTEM_TIME) 
  7740.                                       + THIRTYTWO_BITS (10) * 
  7741.                                      THIRTYTWO_BITS (LCN.CONNECTION_TIMEOUT);
  7742.                                      --APPROX 2 * MSL
  7743.   elsif TIMER = TIME_WAIT_TIMER then
  7744.    LCN.NEXT_TIME_WAIT_TIMEOUT := (THIRTYTWO_BITS(SYSTEM_TIME) +
  7745.                                       THIRTYTWO_BITS (14));
  7746.                                       --14 sec. Two more then retrans time.
  7747.   else --calling the retrans timer which start automatically when queued.
  7748.    TCP_ERROR(17);
  7749.   end if;
  7750.  exception
  7751.   when CONSTRAINT_ERROR =>
  7752.    TEXT_IO.PUT_LINE("CONSTRAINT_ERROR in START_TIMER");
  7753.    TEXT_IO.NEW_LINE;
  7754.   when others =>
  7755.    TEXT_IO.PUT_LINE("unknown error in START_TIMER");
  7756.    TEXT_IO.NEW_LINE;
  7757.  end START_TIMER;
  7758.   
  7759. END TCP_GLOBALS;
  7760. --::::::::::::::
  7761. --tcpqueue.txt
  7762. --::::::::::::::
  7763. -----------------------------------------------------------------------
  7764. --
  7765. --         DoD Protocols    NA-00008-200       80-01198-100(-)
  7766. --         E-Systems, Inc.  August 07, 1985
  7767. --
  7768. --         tcpqueue.txt       Author : Jim Baldo
  7769. --
  7770. -----------------------------------------------------------------------
  7771. with BUFFER_DATA;            use BUFFER_DATA;
  7772. with MODULO;                use MODULO;
  7773. with T_TCP_GLOBALS_DATA_STRUCTURES;    USE T_TCP_GLOBALS_DATA_STRUCTURES;
  7774. --         ************** GLOBAL ROUTINES ***************
  7775. ------------------------- GLOBAL Q PACKAGE --------------------------------
  7776.                 package QUEUES is
  7777.         ----------------------------------------------------
  7778.         --This implementation is for use with the DEC/Ada --
  7779.         --compiler .                                      --
  7780.         ----------------------------------------------------
  7781. -------------------------------------------------------------------------------
  7782. -- This package will contain all data and routines necessary to manipulate   --
  7783. -- the queues.                                                               --
  7784. -------------------------------------------------------------------------------
  7785. procedure INITIALIZE_QUEUES;
  7786.     --This subprogram allocates and links together in a list (pointed to by
  7787.     --queue_free_list) of queue elements to be used by all of the queue
  7788.     --routines. It allocates them via new. They are never deallocated.
  7789.     --They are simply put back in the free queue element list.
  7790.     --The max queue size times the number of queues is the number of queue
  7791.     --elements that are allocated.
  7792. function QUEUE_EMPTY(QUEUE : in QNAME; LCN : in TCB_PTR) return BOOLEAN;
  7793.     --This function returns a boolean indication of whether a queue for a
  7794.     --specific TCB as defined by the LCN is empty.
  7795. procedure QUEUE_GET( QUEUE : in QNAME; 
  7796.                      LCN : in TCB_PTR; 
  7797.                      ITEM : in out STD_Q_ITEM);
  7798.     --This subprogram obtains a queue element from a specified queue which
  7799.     --passed as parameter QUEUE.  If the a queue element is availible  
  7800.     --it is loaded into ITEM.  ITEM returns null in ITEM.BUFFER and zero
  7801.     --in ITEM.LENGTH if queue elements are empty.
  7802. procedure QUEUE_DELETE( QUEUE : in QNAME; 
  7803.                         LCN : in TCB_PTR; 
  7804.                         ITEM : in STD_Q_ITEM);
  7805.     --This subprogram will delete a messaged from a specified queue and 
  7806.     --associated LCN.
  7807. procedure DELETE_FROM_RETRANS_QUEUE( LCN : in TCB_PTR; 
  7808.                                      SEQ_NUM : in MODULAR);
  7809.     --This subprogram removes a message specified by the LCN and SEQ_QUN 
  7810.     --parameters.
  7811. function QUEUE_SIZE( QUEUE :  in QNAME) return SIXTEEN_BITS ;
  7812.     --The element count of the queue header is returned as the size of
  7813.     --the queue.  
  7814. procedure QUEUE_CLEAR( QUEUE : in QNAME; LCN : in TCB_PTR);
  7815.     --This subprogram clears a specified queue of all messages belonging 
  7816.     --to the LCN parameter passed as an argument.
  7817. procedure QUEUE_CLEAR(QUEUE : in QNAME);
  7818.     --This procedure is called to clear a queue of all its entries.  
  7819.       --It will return all the queue structures or queue elements to the 
  7820.     --free list.  The element count is set to zero.  It will also return
  7821.     --any buffers in the queue to the buffer free list.
  7822. procedure QUEUE_ADD( QUEUE : in QNAME; LCN : in TCB_PTR; ITEM : in STD_Q_ITEM);
  7823.     --This subprogram adds a message to a queue specified in the parameter 
  7824.     --list associated with a LCN.
  7825. procedure QUEUE_ADD( QUEUE : in QNAME; 
  7826.                      LCN : in TCB_PTR; 
  7827.                      ITEM : in STD_Q_ITEM; 
  7828.                      RESULT : out BOOLEAN);
  7829.     --This subprogram adds a message to a queue specified in the parameter 
  7830.     --list associated with a LCN.  Parameter RESULT  indicates if the 
  7831.     --queue add was successful.
  7832. procedure QUEUE_ADD_TO_FRONT( QUEUE : in QNAME; 
  7833.                               LCN : in TCB_PTR; 
  7834.                               ITEM : in STD_Q_ITEM);
  7835.     --This subprogram pushes a message on a queue specified in the parameter
  7836.     --list with its associated LCN.
  7837. function QUEUE_RETRANS_TIME(LCN : in TCB_PTR) return THIRTYTWO_BITS ;
  7838.     --This subprogram returns the retransmission time of the first queue 
  7839.     --element of the TCP retransmission queue.
  7840. NULL_BUFFER : PACKED_BUFFER_PTR := NULL;
  7841. NULL_FLAG : BOOLEAN := TRUE;
  7842. NULL_UNPACKED_BUFFER : BUFFER_POINTER;
  7843. QUEUE_FREE_LIST : STD_QUEUE_ELEMENT_POINTER; -- HEAD OF QUEUE FREE LIST
  7844. end QUEUES ;
  7845. -----------------------------GLOBAL Q PACKAGE ----------------------------
  7846. with REAL_TIME_CLOCK_AND_DATE;        use REAL_TIME_CLOCK_AND_DATE;
  7847. with UNCHECKED_CONVERSION;
  7848. with SYSTEM;
  7849. with TEXT_IO;                           use TEXT_IO, INTEGER_IO;
  7850. with WITH_TCP_COMMUNICATE;        use WITH_TCP_COMMUNICATE; 
  7851. with IP_GLOBALS ;            use IP_GLOBALS ;
  7852.         
  7853.                 package BODY QUEUES is
  7854. procedure TCP_ERROR( ERROR_INDICATION : in ERROR_TYPE) is
  7855. begin
  7856.  -- INCREMENT THE ERROR COUNTER.
  7857.  LCN.ERROR_TABLE(ERROR_INDICATION) := 
  7858.        LCN.ERROR_TABLE(ERROR_INDICATION) + 1;
  7859. end TCP_ERROR;
  7860. procedure INITIALIZE_QUEUES is
  7861. NEXT_STRUCTURE : STD_QUEUE_ELEMENT_POINTER;
  7862. begin
  7863.  QUEUE_FREE_LIST := new STD_QUEUE_ELEMENT;
  7864.  NEXT_STRUCTURE := new STD_QUEUE_ELEMENT;
  7865.  QUEUE_FREE_LIST.NEXT := NEXT_STRUCTURE;
  7866.  for I in 2..MAX_QUEUE_SIZE*NUMBER_OF_QUEUES loop
  7867.   -- SET UP A FREE LIST OF QUEUE STRUCTURES.
  7868.   NEXT_STRUCTURE.NEXT := new STD_QUEUE_ELEMENT;
  7869.   NEXT_STRUCTURE := NEXT_STRUCTURE.NEXT;
  7870.  end loop;
  7871. end INITIALIZE_QUEUES;
  7872. function QUEUE_EMPTY(QUEUE : in QNAME; LCN : in TCB_PTR) return BOOLEAN is
  7873. RESULT : BOOLEAN := FALSE;
  7874. begin
  7875.  if LCN.QHEADS(QUEUE).ELEMENT_COUNT = 0 then
  7876.   RESULT := TRUE;
  7877.  end if;
  7878.  return RESULT;
  7879. end QUEUE_EMPTY;
  7880. procedure FREE_Q_STRUCTURE(Q_STRUCTURE : in out STD_QUEUE_ELEMENT_POINTER) is
  7881.     
  7882. begin
  7883.  Q_STRUCTURE.NEXT := QUEUE_FREE_LIST;
  7884.  QUEUE_FREE_LIST := Q_STRUCTURE; --Adds to front of list
  7885.  Q_STRUCTURE := null; --make the pointer null now
  7886. exception
  7887.  when constraint_error =>
  7888.   TEXT_IO.PUT_LINE("Constraint error in FREE_Q_STRUCTURE ");
  7889.   TEXT_IO.PUT(ASCII.BEL);
  7890.  when others =>
  7891.   TEXT_IO.PUT_LINE("unknown error raised in FREE_Q_STRUCTURE ");
  7892.   TEXT_IO.PUT(ASCII.BEL);
  7893. end FREE_Q_STRUCTURE;
  7894.     
  7895. procedure QUEUE_GET( QUEUE : in QNAME; 
  7896.                      LCN : in TCB_PTR; 
  7897.                      ITEM : in out STD_Q_ITEM) is
  7898. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(QUEUE);
  7899. Q_ELEMENT_TO_BE_FREED : STD_QUEUE_ELEMENT_POINTER;
  7900. begin
  7901.  if QHEAD.ELEMENT_COUNT > 0 then
  7902.   QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  7903.   Q_ELEMENT_TO_BE_FREED := QHEAD.FIRST_ELEMENT;
  7904.   -- SET UP IP ID FOR RETRANSMISSION.
  7905.   LCN.RETRANS_IDENT := QHEAD.FIRST_ELEMENT.IP_ID;
  7906.   ITEM := QHEAD.FIRST_ELEMENT.ELEMENT;
  7907.   QHEAD.FIRST_ELEMENT := QHEAD.FIRST_ELEMENT.NEXT;
  7908.   if QHEAD.ELEMENT_COUNT = 0 then -- AN EMPTY LIST
  7909.    QHEAD.LAST_ELEMENT := null;
  7910.   end if;
  7911.   FREE_Q_STRUCTURE(Q_ELEMENT_TO_BE_FREED); 
  7912.   -- FREE UP THE FORMER FIRST ELEMENT
  7913.  else
  7914.   ITEM.BUFFER := null; -- AN EMPTY QUEUE
  7915.   ITEM.LENGTH := 0;   
  7916.   -- AN INDICATION FOR A STANDARD BUFFER NO ENTRY EXISTS
  7917.  end if;
  7918. exception
  7919.  when CONSTRAINT_ERROR =>
  7920.   PUT_LINE("CONSTRAINT ERROR IN QGET");
  7921.  when others =>
  7922.   PUT_LINE("UNKNOWN  ERROR IN QUEUE_GET");
  7923. end QUEUE_GET;
  7924. procedure QUEUE_DELETE( QUEUE : in QNAME; 
  7925.                         LCN : in TCB_PTR; 
  7926.                         ITEM : in STD_Q_ITEM) is
  7927. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(QUEUE);
  7928. BEFORE_PTR : STD_QUEUE_ELEMENT_POINTER := QHEAD.FIRST_ELEMENT;
  7929. CURRENT_ELEMENT_POINTER : STD_QUEUE_ELEMENT_POINTER 
  7930.                     := QHEAD.FIRST_ELEMENT;
  7931. FOUND : BOOLEAN := FALSE;
  7932. BUFFTYPE : SIXTEEN_BITS ;
  7933. begin
  7934.  while CURRENT_ELEMENT_POINTER /= null and (not FOUND) loop
  7935.   if CURRENT_ELEMENT_POINTER.ELEMENT = ITEM then
  7936.    -- FREE IT AND THE BUFFER UP
  7937.    if CURRENT_ELEMENT_POINTER.ELEMENT.BUFFER /= null then 
  7938.     -- RETURN BUFFER TO POOL
  7939.     CURRENT_ELEMENT_POINTER.ELEMENT.BUFFER.STATUS := NONE;
  7940.     BUFFREE(CURRENT_ELEMENT_POINTER.ELEMENT.BUFFER, BUFFTYPE);
  7941.    end if;
  7942.    BEFORE_PTR.NEXT := CURRENT_ELEMENT_POINTER.NEXT;
  7943.    -- TAKE CARE OF DELETING FROM THE END 
  7944.    --OR BEGINNING OF A LIST.
  7945.    if QHEAD.FIRST_ELEMENT = CURRENT_ELEMENT_POINTER then
  7946.     QHEAD.FIRST_ELEMENT := CURRENT_ELEMENT_POINTER.NEXT;
  7947.    end if;
  7948.    if QHEAD.LAST_ELEMENT = CURRENT_ELEMENT_POINTER then
  7949.     -- WE ARE DELETING LAST ELEMENT.
  7950.     if QHEAD.FIRST_ELEMENT /= null then
  7951.      QHEAD.LAST_ELEMENT := BEFORE_PTR;
  7952.     else -- AN EMPTY LIST NOW
  7953.      QHEAD.LAST_ELEMENT := null;
  7954.     end if;
  7955.    end if;
  7956.    -- FREE THE ELEMENT AND DECREMENT THE ELEMENT COUNT
  7957.    FREE_Q_STRUCTURE(CURRENT_ELEMENT_POINTER);
  7958.    QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  7959.    FOUND := TRUE;
  7960.   else
  7961.    BEFORE_PTR := CURRENT_ELEMENT_POINTER;
  7962.    CURRENT_ELEMENT_POINTER := CURRENT_ELEMENT_POINTER.NEXT;
  7963.   end if;
  7964.  end loop;
  7965.  if not FOUND then
  7966.   --ERROR
  7967.   TCP_ERROR(11);
  7968.  end if;
  7969. exception
  7970.  when CONSTRAINT_ERROR =>
  7971.   PUT_LINE("CONSTRAINT ERROR IN QUEUE DELETE");
  7972.  when others =>
  7973.   PUT_LINE(" ERROR IN QUEUE DELETE");
  7974. end QUEUE_DELETE;
  7975. procedure DELETE_FROM_RETRANS_QUEUE( LCN : in TCB_PTR; 
  7976.                                      SEQ_NUM : in MODULAR) is
  7977. type FOUR_BYTES is array(1..4) of SYSTEM.BYTE ;
  7978. type ONELONG is array(1..1) of THIRTYTWO_BITS ;
  7979. function CONVERT is new UNCHECKED_CONVERSION(FOUR_BYTES, ONELONG);
  7980. SEARCH_NUM : MODULAR := SEQ_NUM - 1; 
  7981. -- WE GOT IN SND_UNA AND WILL TAKE OFF
  7982. -- EVERTHING THAT IS SND_UNA - 1 OR LESS.
  7983. SEQUENCE_NUM : MODULAR;
  7984. PACKED_BUFFER : PACKED_BUFFER_PTR;
  7985. TEMP : FOUR_BYTES;
  7986. RESULT : ONELONG;
  7987. DATA_LENGTH, DATA_OFFSET, INDEX : SIXTEEN_BITS ;
  7988. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(TCP_RETRANSMIT_QUEUE);
  7989. TEMP_PTR : STD_QUEUE_ELEMENT_POINTER;
  7990. BEFORE_PTR : STD_QUEUE_ELEMENT_POINTER := QHEAD.FIRST_ELEMENT;
  7991. CURRENT_ELEMENT_POINTER : STD_QUEUE_ELEMENT_POINTER := 
  7992.                     QHEAD.FIRST_ELEMENT;
  7993. begin
  7994.  while CURRENT_ELEMENT_POINTER /= null loop 
  7995.   -- TAKE ANYTHING WE CAN OFF OF THE QUEUE.
  7996.   PACKED_BUFFER := CURRENT_ELEMENT_POINTER.ELEMENT.BUFFER;
  7997.   -- GET THE DATA OFFSET.
  7998.   INDEX := PACKED_BUFFER.TCP_PTR + 12;
  7999.   DATA_OFFSET := SIXTEEN_BITS ( PACKED_BUFFER.BYTE ( INDEX ) ) / 2**4 ;
  8000.   -- GET THE SEQUENCE NUMBER
  8001.   INDEX := PACKED_BUFFER.TCP_PTR - 1;
  8002.   for I in 1..4 loop
  8003.    TEMP(I) :=  PACKED_BUFFER.BYTE ( INDEX + SIXTEEN_BITS ( 5 - I ) + 4) ; 
  8004.    -- GET THE SEQ NUMBER
  8005.   end loop;
  8006.   -- INITIALIZE RESULT
  8007.   RESULT(1) := 0;
  8008.   RESULT := CONVERT(TEMP); 
  8009.   -- CONVERT IT TO A LONG INTEGER
  8010.   SEQUENCE_NUM := MODULAR_CONVERT(RESULT(1)); 
  8011.   -- MAKE IT MODULAR
  8012.   -- GET THE DATA LENGTH
  8013.   DATA_LENGTH := CURRENT_ELEMENT_POINTER.ELEMENT.LENGTH -
  8014.                  DATA_OFFSET * 4;
  8015.   if DATA_LENGTH > 0 then 
  8016.   -- SINCE WE NEVER SEND DATA WITH A SYN 
  8017.   --OR A FIN( WHICH ARE CONSIDERED DATA
  8018.   -- OCTETS, THE DATA LENGTH IN ADDITION TO THE 
  8019.   --SEQ NUM IS ONE LESS THAN THE
  8020.   -- ACTUAL NUMBER OF DATA OCTETS.
  8021.    DATA_LENGTH := DATA_LENGTH - 1;
  8022.   end if;
  8023.         --PUT_LINE("IN RETRANS DELETE");--- DEBUG
  8024.                 --LONG_INTEGER_IO.PUT(LONG(SEARCH_NUM));
  8025. --        INTEGER_IO.PUT(LCN);
  8026. --        PUT_LINE("THE PACKED BUFFER POINTER AND DATA OFFSET ARE");
  8027. --        INTEGER_IO.PUT(PACKED_BUFFER.TCP_PTR);
  8028. --        INTEGER_IO.PUT(DATA_OFFSET);
  8029.                 --PUT_LINE("THE SEQUENCE NUMBER AND DATA LENGTH ARE ");
  8030.                 --LONG_INTEGER_IO.PUT(RESULT(1));
  8031.           --INTEGER_IO.PUT(DATA_LENGTH);
  8032.   if SEQUENCE_NUM + DATA_LENGTH <= SEARCH_NUM then 
  8033.    -- DELETE THIS QUEUE ELEMENT.
  8034.    --TEXT_IO.PUT_LINE("DELETEING FROM RETRANS QUEUE");
  8035.    BEFORE_PTR.NEXT := CURRENT_ELEMENT_POINTER.NEXT;
  8036.    -- TAKE CARE OF DELETING FROM THE END OR BEGINNING OF A LIST.
  8037.    if QHEAD.FIRST_ELEMENT = CURRENT_ELEMENT_POINTER then
  8038.     QHEAD.FIRST_ELEMENT := CURRENT_ELEMENT_POINTER.NEXT;
  8039.    end if;
  8040.    if QHEAD.LAST_ELEMENT = CURRENT_ELEMENT_POINTER then
  8041.     -- WE ARE DELETING LAST ELEMENT.
  8042.     if QHEAD.FIRST_ELEMENT /= null then
  8043.      QHEAD.LAST_ELEMENT := BEFORE_PTR;
  8044.     else -- AN EMPTY LIST NOW
  8045.      QHEAD.LAST_ELEMENT := null;
  8046.     end if;
  8047.    end if;
  8048.    TEMP_PTR := BEFORE_PTR.NEXT; 
  8049.    -- THE NEXT ELEMENT TO BE CHECKED
  8050.    -- FREE UP THE ELEMENT AND DECREMENT THE QUEUE COUNT.
  8051.    FREE_Q_STRUCTURE(CURRENT_ELEMENT_POINTER);
  8052.    QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  8053.    -- FREE UP THE BUFFER
  8054.    PACKED_BUFFER.STATUS := NONE;
  8055.    BUFFREE(PACKED_BUFFER, 1);
  8056.    -- UPDATE CURRENT_ELEMENT_POINTER TO POINT AT THE 
  8057.    --NEXT ELEMENT TO BE CHECKED.
  8058.    CURRENT_ELEMENT_POINTER := TEMP_PTR;
  8059.   else -- ADVANCE THE POINTERS.
  8060.    --TEXT_IO.PUT_LINE("DID NOT DELETE FROM RETRANS QUEUE");
  8061.    BEFORE_PTR := CURRENT_ELEMENT_POINTER;
  8062.    CURRENT_ELEMENT_POINTER := CURRENT_ELEMENT_POINTER.NEXT;
  8063.   end if;
  8064.  end loop;
  8065. exception
  8066.  when CONSTRAINT_ERROR =>
  8067.   PUT_LINE("CONSTRAINT ERROR IN DELETE FROM RETRANS QUEUE");
  8068. --  PUT("THE LCN IS ");
  8069. --  INTEGER_IO.PUT(LCN);
  8070.   TEXT_IO.PUT_LINE("");
  8071.   TEXT_IO.PUT("INDEX VALUE IS ");
  8072.   INTEGER_IO.PUT(INDEX);
  8073.   INTEGER_IO.PUT(PACKED_BUFFER.TCP_PTR);
  8074.   if CURRENT_ELEMENT_POINTER = null then
  8075.    TEXT_IO.PUT_LINE("A NULL CURRENT ELEMENT POINTER.");
  8076.   end if;
  8077.   if BEFORE_PTR.NEXT = null then
  8078.    TEXT_IO.PUT_LINE("A NULL BEFORE POINTER NEXT FIELD");
  8079.   end if;
  8080.   if PACKED_BUFFER = null then
  8081.    TEXT_IO.PUT_LINE("A NULL PACKED BUFFER ON THE RETRANS QUEUE");
  8082.   end if;
  8083.  when others =>
  8084.   TEXT_IO.PUT_LINE("UNKNOWN ERROR IN DELETE FROM RETRANS QUEUE");
  8085.  end DELETE_FROM_RETRANS_QUEUE;
  8086. function QUEUE_SIZE( QUEUE : in QNAME) return SIXTEEN_BITS  is
  8087.     
  8088. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(QUEUE);
  8089.     
  8090. begin
  8091.  return QHEAD.ELEMENT_COUNT;
  8092. exception
  8093.  when CONSTRAINT_ERROR =>
  8094.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR in QUEUE_SIZE");
  8095.  when others =>
  8096.   TEXT_IO.PUT_LINE("unknown error in QUEUE_SIZE");
  8097. end QUEUE_SIZE;
  8098. procedure QUEUE_CLEAR( QUEUE : in QNAME) is
  8099. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(QUEUE);
  8100. X : STD_QUEUE_ELEMENT_POINTER;
  8101. BUFFTYPE : SIXTEEN_BITS ;
  8102. begin
  8103.  while QHEAD.ELEMENT_COUNT > 0 loop
  8104.   X := QHEAD.FIRST_ELEMENT;
  8105.   if X.ELEMENT.BUFFER /= null then
  8106.    if X.ELEMENT.BUFFER.STATUS =OWNER_TCP then -- if it is ours,
  8107.                                               -- it is no longer.
  8108.     X.ELEMENT.BUFFER.STATUS := BUFFER_DATA.NONE;
  8109.    end if;
  8110.    BUFFREE(X.ELEMENT.BUFFER, BUFFTYPE);
  8111.   end if;
  8112.   QHEAD.FIRST_ELEMENT := X.NEXT;
  8113.   FREE_Q_STRUCTURE(X);
  8114.   QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  8115.  end loop;
  8116.  -- reset the head and tail pointers
  8117.  QHEAD.FIRST_ELEMENT := null;
  8118.  QHEAD.LAST_ELEMENT := null;
  8119. exception
  8120.  when CONSTRAINT_ERROR =>
  8121.   TEXT_IO.PUT_LINE(" CONSTRAINT ERROR IN QUEUE CLEAR");
  8122.  when others =>
  8123.   TEXT_IO.PUT_LINE(" UNKNOWN ERROR TYPE IN QUEUE CLEAR");
  8124. end QUEUE_CLEAR;
  8125. procedure QUEUE_CLEAR( QUEUE : in QNAME; LCN : in TCB_PTR) is
  8126. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(QUEUE);
  8127. X : STD_QUEUE_ELEMENT_POINTER;
  8128. BUFFTYPE : SIXTEEN_BITS ;
  8129. begin
  8130.  while QHEAD.ELEMENT_COUNT > 0 loop
  8131.   X := QHEAD.FIRST_ELEMENT;
  8132.   if X.ELEMENT.BUFFER /= null then
  8133.    X.ELEMENT.BUFFER.STATUS := NONE;
  8134.    BUFFREE(X.ELEMENT.BUFFER, BUFFTYPE);
  8135.   end if;
  8136.   QHEAD.FIRST_ELEMENT := X.NEXT;
  8137.   FREE_Q_STRUCTURE(X);
  8138.   QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT - 1;
  8139.  end loop;
  8140.  -- RESET THE HEAD AND TAIL POINTERS.
  8141.  QHEAD.FIRST_ELEMENT := null;
  8142.  QHEAD.LAST_ELEMENT := null;
  8143. exception
  8144.  when CONSTRAINT_ERROR =>
  8145.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN QUEUE CLEAR");
  8146.  when others =>
  8147.   TEXT_IO.PUT_LINE("UNKNOWN ERROR TYPE IN QUEUE CLEAR");
  8148. end QUEUE_CLEAR;
  8149. function GET_Q_STRUCTURE return STD_QUEUE_ELEMENT_POINTER is
  8150. X : STD_QUEUE_ELEMENT_POINTER;
  8151. begin
  8152.  X := QUEUE_FREE_LIST;
  8153.  QUEUE_FREE_LIST := QUEUE_FREE_LIST.NEXT;
  8154.  return X;
  8155. exception
  8156.  when constraint_error =>
  8157.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN GET_Q_STRUCTURE");
  8158.  when others =>
  8159.   TEXT_IO.PUT_LINE("UNKNOWN ERROR RAISED IN GET_Q_STRUCTURE");
  8160. end GET_Q_STRUCTURE;
  8161. procedure QUEUE_ADD( QUEUE : in QNAME; 
  8162.                      LCN : in TCB_PTR; 
  8163.                      ITEM : in STD_Q_ITEM) is
  8164. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(QUEUE);
  8165. NEW_ITEM : STD_QUEUE_ELEMENT_POINTER := GET_Q_STRUCTURE;
  8166. begin
  8167.  NEW_ITEM.ELEMENT := ITEM;
  8168.  NEW_ITEM.NEXT := null;
  8169.  if QUEUE = TCP_RETRANSMIT_QUEUE then
  8170.  -- PUT ON A TIME FOR THE RETRANS QUEUE
  8171.   --TEXT_IO.PUT("THE POINTER ON QUEUE ADD AND LCN  IS "); 
  8172.                         -- TESTING
  8173. --  INTEGER_IO.PUT(ITEM.BUFFER.TCP_PTR);
  8174. --            INTEGER_IO.PUT(LCN);
  8175. --            PUT_LINE("");
  8176.             NEW_ITEM.TIME := THIRTYTWO_BITS ( SYSTEM_TIME ) ;
  8177.             NEW_ITEM.IP_ID := LCN.IDENT; -- SAVE THE ID FOR IP.
  8178.  end if;
  8179.  if QHEAD.ELEMENT_COUNT < MAX_QUEUE_SIZE then
  8180.   if QHEAD.ELEMENT_COUNT /= 0 then
  8181.    -- ITS NOT AN EMPTY QUEUE. SO LINK FORMER
  8182.    -- LAST ITEM TO NEW ONE.
  8183.    QHEAD.LAST_ELEMENT.NEXT := NEW_ITEM;
  8184.   else -- FIRST ADD TO THE QUEUE
  8185.    QHEAD.FIRST_ELEMENT := NEW_ITEM;
  8186.   end if;
  8187.   QHEAD.LAST_ELEMENT := NEW_ITEM;
  8188.   QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT + 1;
  8189.  else -- NO ROOM TOO BAD
  8190.   TCP_ERROR(18);
  8191.   FREE_Q_STRUCTURE(NEW_ITEM);
  8192.  end if;
  8193. exception
  8194.  when CONSTRAINT_ERROR =>
  8195.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN QUEUE ADD");
  8196.  when others =>
  8197.   TEXT_IO.PUT_LINE("ERROR IN QADD");
  8198. --  INTEGER_IO.PUT(LCN);
  8199.   INTEGER_IO.PUT(QHEAD.ELEMENT_COUNT);
  8200. end QUEUE_ADD;
  8201. procedure QUEUE_ADD( QUEUE : in QNAME; 
  8202.                      LCN : in TCB_PTR; 
  8203.                      ITEM : in STD_Q_ITEM; 
  8204.                      RESULT : out BOOLEAN) is
  8205. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(QUEUE);
  8206. NEW_ITEM : STD_QUEUE_ELEMENT_POINTER := GET_Q_STRUCTURE;
  8207. begin
  8208.  NEW_ITEM.ELEMENT := ITEM;
  8209.  NEW_ITEM.NEXT := null;
  8210.  if QUEUE = TCP_RETRANSMIT_QUEUE then
  8211.   -- PUT ON A TIME FOR THE RETRANS QUEUE
  8212. --  PUT("THE POINTER ON QUEUE ADD AND LCN  IS "); -- TESTING
  8213. --  INTEGER_IO.PUT(ITEM.BUFFER.TCP_PTR);
  8214. --            INTEGER_IO.PUT(LCN);
  8215. --            PUT_LINE("");
  8216.   NEW_ITEM.TIME := THIRTYTWO_BITS ( SYSTEM_TIME ) ;
  8217.   NEW_ITEM.IP_ID := LCN.IDENT; -- SAVE THE ID FOR IP.
  8218.  end if;
  8219.  if QHEAD.ELEMENT_COUNT < MAX_QUEUE_SIZE then
  8220.   if QHEAD.ELEMENT_COUNT /= 0 then
  8221.    -- ITS NOT AN EMPTY QUEUE. SO LINK FORMER
  8222.    -- LAST ITEM TO NEW ONE.
  8223.    QHEAD.LAST_ELEMENT.NEXT := NEW_ITEM;
  8224.   else --FIRST ELEMENT IN QUEUE
  8225.    QHEAD.FIRST_ELEMENT := NEW_ITEM;
  8226.   end if;
  8227.   QHEAD.LAST_ELEMENT := NEW_ITEM;
  8228.   QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT + 1;
  8229.   RESULT := FALSE;
  8230.  else -- NO ROOM TOO BAD. 
  8231.   -- PUT QUEUE STRUCTURE BACK ON THE FREE LIST.
  8232.   TCP_ERROR(18);
  8233.   FREE_Q_STRUCTURE(NEW_ITEM);
  8234.   RESULT := TRUE;
  8235.  end if;
  8236. exception
  8237.  when CONSTRAINT_ERROR =>
  8238.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN ");
  8239.   TEXT_IO.PUT_LINE("QUEUE ADD, WITH RESULT INDICATION.");
  8240.  when others =>
  8241.   TEXT_IO.PUT_LINE("UNKNOWN ERROR TYPE IN ");
  8242.   TEXT_IO.PUT_LINE("QUEUE ADD, WITH RESULT INDICATION.");
  8243. end QUEUE_ADD;
  8244. procedure QUEUE_ADD_TO_FRONT( QUEUE : in QNAME; 
  8245.                               LCN : in TCB_PTR; 
  8246.                               ITEM : in STD_Q_ITEM) is
  8247. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(QUEUE);
  8248. NEW_ITEM : STD_QUEUE_ELEMENT_POINTER := GET_Q_STRUCTURE; 
  8249. -- GET A QUEUE STRUCTURE FROM FREE LIST.
  8250. begin
  8251.  NEW_ITEM.ELEMENT := ITEM;
  8252.  NEW_ITEM.NEXT := null;
  8253.  if QHEAD.ELEMENT_COUNT < MAX_QUEUE_SIZE then
  8254.   NEW_ITEM.NEXT := QHEAD.FIRST_ELEMENT;
  8255.   QHEAD.FIRST_ELEMENT := NEW_ITEM;
  8256.   if QHEAD.ELEMENT_COUNT = 0 then
  8257.    -- ADDING TO AN EMPTY LIST
  8258.    QHEAD.LAST_ELEMENT := NEW_ITEM;
  8259.   end if;
  8260.   QHEAD.ELEMENT_COUNT := QHEAD.ELEMENT_COUNT + 1;
  8261.  else -- A MAJOR PROBLEM SHOULDN'T HAPPEN
  8262.   TCP_ERROR(18);
  8263.   FREE_Q_STRUCTURE(NEW_ITEM); 
  8264.   -- FREE QUEUE STRUCTURE ANYWAY.
  8265.   TEXT_IO.PUT_LINE("NO ROOM FOR QUEUE ADD TO FRONT IN TCP");
  8266.  end if;
  8267. exception
  8268.  when CONSTRAINT_ERROR =>
  8269.   TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN QUEUE ADD TO FRONT");
  8270.  when others =>
  8271.   TEXT_IO.PUT_LINE("UNKNOWN ERROR TYPE IN QUEUE ADD TO FRONT");
  8272. end QUEUE_ADD_TO_FRONT;
  8273. function QUEUE_RETRANS_TIME( LCN : in TCB_PTR) return THIRTYTWO_BITS is
  8274. QHEAD : STD_HEAD_PTR renames LCN.QHEADS(TCP_RETRANSMIT_QUEUE);
  8275. begin
  8276.  RETURN QHEAD.FIRST_ELEMENT.TIME;
  8277. end QUEUE_RETRANS_TIME;
  8278. begin
  8279.  INITIALIZE_QUEUES ;
  8280. end QUEUES;
  8281. --::::::::::::::
  8282. --tcputil.txt
  8283. --::::::::::::::
  8284. -----------------------------------------------------------------------
  8285. --
  8286. --         DoD Protocols    NA-00008-200       80-01199-100(-)
  8287. --         E-Systems, Inc.  August 07, 1985
  8288. --
  8289. --         tcputil.txt       Author : Jim Baldo
  8290. --
  8291. -----------------------------------------------------------------------
  8292. with WITH_TCP_COMMUNICATE ;        use WITH_TCP_COMMUNICATE ;
  8293. with MODULO;                use MODULO;
  8294. with BUFFER_DATA;            use BUFFER_DATA;
  8295. -- COMMUNICATE AND QUEUE CONTAINS THE NECESSARY    FACILITIES FOR MESSAGES    TO BE
  8296. -- QUEUED BETWEEN TASKS.
  8297. with T_TCP_GLOBALS_DATA_STRUCTURES;    USE T_TCP_GLOBALS_DATA_STRUCTURES;
  8298.         package T_TCP_CONTROLLER_UTILITIES is
  8299.     --------------------------------------------------------------------
  8300.     --This implementation is for use with the DEC/Ada compiler        --
  8301.     --version .                                                       --
  8302.     --------------------------------------------------------------------
  8303.  function USER_ACCESS_CHECK( LCN : in TCB_PTR) return BOOLEAN;
  8304.  procedure SEND_A_SYN( LCN : in TCB_PTR);
  8305.  procedure TCP_SEND( LCN : in TCB_PTR;
  8306.                      PACKED_BUFF : in out PACKED_BUFFER_PTR;
  8307.              BUFFLEN, PUSH_FLAG, URG_FLAG, TIMEOUT : in SIXTEEN_BITS );
  8308.  procedure TCP_RECEIVE( LCN : in TCB_PTR; 
  8309.                         PACKED_BUFF : in out PACKED_BUFFER_PTR;
  8310.                 BYTE_COUNT : in SIXTEEN_BITS );
  8311.  procedure TCP_ABORT( LCN : in TCB_PTR);
  8312.  procedure TCP_CLOSE( LCN : in TCB_PTR);
  8313.  procedure TCP_OPEN(LOCAL_PORT, FOREIGN_PORT :in SIXTEEN_BITS ; 
  8314.                     FOREIGN_NET_HOST : in THIRTYTWO_BITS ;
  8315.             ACTIVE_PASSIVE : in WITH_TCP_COMMUNICATE.ACKPASS;    
  8316.             BUFFER_SIZE, TIMEOUT : in SIXTEEN_BITS ;  
  8317.                     LOCAL_CONN_NAME : in out TCB_PTR ;
  8318.             SECURITY, PRECEDENCE : in SIXTEEN_BITS ;
  8319.             OPTIONS : in TCP_OPTION_TYPE);
  8320.  procedure TCP_STATUS(LCN : in TCB_PTR);
  8321.  procedure RETRANS_TCP(LCN : in TCB_PTR);
  8322. end T_TCP_CONTROLLER_UTILITIES;
  8323. with SYSTEM;
  8324. with TEXT_IO;                use TEXT_IO;
  8325. with UNCHECKED_CONVERSION;
  8326. -- COMMUNICATE AND QUEUE CONTAINS THE NECESSARY    FACILITIES FOR MESSAGES    TO BE
  8327. -- QUEUED BETWEEN TASKS.
  8328. with WITH_TCP_COMMUNICATE;        use WITH_TCP_COMMUNICATE;
  8329. with TCP_GLOBALS;            use TCP_GLOBALS;
  8330. with QUEUES;                            use QUEUES;
  8331. with TCP_SEGMENT_ARRIVES_PROCESSING;    use TCP_SEGMENT_ARRIVES_PROCESSING;
  8332. with IP_GLOBALS;            use IP_GLOBALS;
  8333. with TCB_ALLOCATOR;        use TCB_ALLOCATOR;
  8334. with WITH_ULP_COMMUNICATE;              use WITH_ULP_COMMUNICATE;
  8335. with WITH_IP_COMMUNICATE;               use WITH_IP_COMMUNICATE;
  8336. with T_tcp_utilities_1 ;                  
  8337.         
  8338.                 package body T_TCP_CONTROLLER_UTILITIES is
  8339. function USER_ACCESS_CHECK( LCN : in TCB_PTR) return BOOLEAN is
  8340. RESULT : BOOLEAN := TRUE;
  8341. I : TCB_PTR := OBTAIN_HEAD_OF_LCN_IN_USE_QUEUE;
  8342.                            -- THE BEGINNING INDEX INTO THE LCN LIST!
  8343. begin
  8344.  while I /= null and RESULT loop
  8345.   if I = LCN then 
  8346.    RESULT := FALSE;
  8347.   end if;
  8348.   I := I.NEXT;
  8349.  end loop;
  8350.  return RESULT;
  8351. exception 
  8352.  when OTHERS =>
  8353.   PUT("PROBLEM IN USER ACCESS CHECK");
  8354. end USER_ACCESS_CHECK;
  8355.  procedure SEND_A_SYN( LCN : in TCB_PTR) is
  8356.     --This subprogram is called by the TCP_OPEN and the TCP_SEND in the 
  8357.     --listen state to send out a SYN.  The LCN is passed to the subprogram 
  8358.     --to calculate the appropiate address.  This subprogram will format 
  8359.     --and send a SYN segment to the IP for transmission to the remote host.
  8360.  HEADER_LENGTH : SIXTEEN_BITS  := 20;
  8361.  BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  8362.  DEST : THIRTYTWO_BITS ;
  8363.  SOURCE : THIRTYTWO_BITS ;
  8364.  PACKED_BUFF : PACKED_BUFFER_PTR;
  8365.  BUFFLEN : SIXTEEN_BITS ; -- TEMPORARY
  8366.  Q_ITEM : STD_Q_ITEM;
  8367.  UMESSAGE : USER_MESSAGE;
  8368.  SOCKET_PARAMS : TCB_PTR;
  8369.  MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  8370.  
  8371.  begin
  8372.   BUFFGET(PACKED_BUFF, BUFFLEN);
  8373.   if PACKED_BUFF = null then
  8374.    -- TELL USER
  8375.    -- ERROR: INSUFFICIENT RESOURCES
  8376.    SOCKET_PARAMS := LCN;
  8377.    UMESSAGE := ( 1, 
  8378.                  SOCKET_PARAMS);
  8379.    MESSAGE_FOR_USER(UMESSAGE);
  8380.   else
  8381.    PACKED_BUFF.IN_USE := TRUE;
  8382.    PACKED_BUFF.STATUS := OWNER_TCP;
  8383.    LCN.ISS := MODULAR_CONVERT(ISS);--GET AN INTIAL SEND SEQUENCE NUMBER 
  8384.                                         --(ISS)
  8385.    LCN.SND_NXT := LCN.ISS;-- SET UP THE INITIAL SEND NEXT.
  8386.    TYPE_FLAG := SYN;
  8387.    OPTIONS := CLEAR;--CLEAR THE OPTIONS ARRAY
  8388.                     --ADD ANY OPTIONS TO HEADER LENGTH HERE
  8389.    TCP_HEADER_FORMAT( LCN, BUFPTR, TYPE_FLAG, OPTIONS);
  8390.    DEST := LCN.DESTINATION_ADDRESS;
  8391.    -- HERE WE MUST PUT IN THE NECESSARY SECURITY OPTIONS FOR IP.
  8392.    OPTIONS := TCP_SECURITY_OPTIONS;
  8393.    PACK_BUFFER_INTO_BIT_STREAM(BUFPTR, PACKED_BUFF);-- PACK THE BUFFER
  8394.    SOURCE := IP_GLOBALS.WHOIAM;
  8395.    SEND_IP( SOURCE,
  8396.             DEST,
  8397.             TOS,
  8398.             TTL,
  8399.             PACKED_BUFF,
  8400.             HEADER_LENGTH,
  8401.             IDENT,
  8402.             DONT_FRAGMENT,
  8403.             OPTIONS,
  8404.             RESULT);
  8405.    -- UPDATE SEND UNACKNOWLEDGED AND SND_NXT.
  8406.    LCN.SND_UNA :=    LCN.ISS;
  8407.    LCN.SND_NXT :=    LCN.ISS + MODULAR_CONVERT(SIXTEEN_BITS(1)); -- SAME AS SEND NEXT + 1
  8408.    --  PUT BUFFER ON RETRANSMIT QUEUE WITH THE LENGTH IN OCTETS.
  8409.    Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER, HEADER_LENGTH);
  8410.    --  IT IS QUEUED UP WITH A TIME.
  8411.    QUEUE_ADD(TCP_RETRANSMIT_QUEUE, LCN, Q_ITEM);
  8412.   end if;
  8413.  end SEND_A_SYN;
  8414.  procedure TCP_SEND(LCN : in TCB_PTR;
  8415.                     PACKED_BUFF : in out PACKED_BUFFER_PTR;
  8416.             BUFFLEN, PUSH_FLAG,URG_FLAG,TIMEOUT : in SIXTEEN_BITS ) is
  8417. --This subprogram is called by the TCP controller to process a users send
  8418. --request.  This subprogram will format the header and pass the buffer on to 
  8419. --the IP for transmission.
  8420. --The following parameters are passed to the subprogram:
  8421. --    LCN
  8422. --    Buffer length
  8423. --    PUSH_FLAG : An indication of whether all data should be pushed through.
  8424. --    URG_FLAG : An indication of the urgency of the data.
  8425. --         (1 URGENT, 0 NORMAL).
  8426. --    TIMEOUT : The timeout interval for a connection. timeout occurs if 
  8427. --        there is no response for that amount of time.
  8428. --    PACKED_BUFF : A packed buffer with user data.
  8429. --                                          
  8430.  NULL_FLAG, NO_ROOM_ON_QUEUE : BOOLEAN;
  8431.  BUFFSIZE : SIXTEEN_BITS ;
  8432.  BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  8433.  Q_ITEM : STD_Q_ITEM;
  8434.  SEGMENT_LENGTH : SIXTEEN_BITS  := 255 - PACKED_BUFF.TCP_PTR; 
  8435.    -- CORRECT UNTIL SIZE CHANGES
  8436.  UMESSAGE : USER_MESSAGE;
  8437.  SOCKET_PARAMS : TCB_PTR;
  8438.  MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  8439.  begin
  8440.   T_TCP_GLOBALS_DATA_STRUCTURES.LCN := LCN; -- FOR TEST***
  8441.   if TIMEOUT /= 0 then -- PUT IN THE NEW CONNECTION TIMEOUT.
  8442.    LCN.CONNECTION_TIMEOUT := TIMEOUT;
  8443.   end if;
  8444.   case LCN.STATE is
  8445.    when CLOSED =>
  8446.     if USER_ACCESS_CHECK(LCN) then
  8447.      -- TELL USER
  8448.      --  ERROR: CONNECTION ILLEGAL FOR THIS PROCESS 
  8449.      SOCKET_PARAMS := LCN;
  8450.      UMESSAGE := ( 2, 
  8451.                    SOCKET_PARAMS);
  8452.      MESSAGE_FOR_USER(UMESSAGE);
  8453.     else
  8454.      -- TELL USER
  8455.      -- ERROR: CONNECTION DOES NOT EXIST
  8456.      SOCKET_PARAMS := LCN;
  8457.      UMESSAGE := ( 3, 
  8458.                    SOCKET_PARAMS);
  8459.      MESSAGE_FOR_USER(UMESSAGE);
  8460.     end if;
  8461.    when T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN =>
  8462.    if FOREIGN_SOCKET_UNSPECIFIED(LCN) then
  8463.      -- TELL USER
  8464.      -- ERROR: FOREIGN SOCKET UNSPECIFIED
  8465.      SOCKET_PARAMS := LCN;
  8466.      UMESSAGE := ( 4,
  8467.                    SOCKET_PARAMS);
  8468.      MESSAGE_FOR_USER(UMESSAGE);
  8469.     else
  8470.      -- TCB STATE BECOMES ACTIVE 
  8471.      LCN.ACTIVE_PASSIVE := ACTIVE;
  8472.      --  PUT ANY TEXT ON THE TEXT TRANSMIT QUEUE FOR LATER TRANSMISSION 
  8473.      if BUFFLEN > 0 then -- THERE IS DATA.
  8474.      Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER, BUFFLEN);
  8475.      QUEUE_ADD(TRANSMIT_QUEUE, LCN, Q_ITEM, NO_ROOM_ON_QUEUE);
  8476.      if NO_ROOM_ON_QUEUE then
  8477.       -- TELL USER OR ERROR ROUTINE
  8478.       -- ERROR: INSUFFICIENT RESOURCES 
  8479.       PUT_LINE("STATE IS LISTEN");--DEBUG
  8480.       PUT_LINE("NO Q RM IN SEND");-- DEBUG
  8481.       SOCKET_PARAMS := LCN;
  8482.       UMESSAGE := ( 5, 
  8483.                     SOCKET_PARAMS);
  8484.       MESSAGE_FOR_USER(UMESSAGE);
  8485.      end if;
  8486.     end if;
  8487.     -- SEND OUT A SYN
  8488.     SEND_A_SYN(LCN);
  8489.     --  PUT TCB INTO SYN_SENT STATE.
  8490.     LCN.STATE := SYN_SENT;
  8491.    end if;
  8492.   when SYN_SENT | SYN_RECEIVED =>
  8493.    -- PUT THE TEXT ON THE TRANSMIT QUEUE FOR LATER TRANSMISSION
  8494.    if BUFFLEN > 0 then -- THERE IS DATA.
  8495.     Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER, BUFFLEN);
  8496.     QUEUE_ADD(TRANSMIT_QUEUE, LCN, Q_ITEM, NO_ROOM_ON_QUEUE);
  8497.     if NO_ROOM_ON_QUEUE then
  8498.      -- TELL USER
  8499.      -- ERROR: INSUFFICIENT RESOURCES
  8500.      PUT_LINE("NO Q RM IN SEND");-- DEBUG
  8501.      PUT_LINE("STATE IS SYN SENT OR SYN RECEIVED");--DEBUG
  8502.      SOCKET_PARAMS := LCN;
  8503.      UMESSAGE := ( 5, 
  8504.                    SOCKET_PARAMS);
  8505.      MESSAGE_FOR_USER(UMESSAGE);
  8506.     end if;
  8507.    end if;
  8508.   when ESTABLISHED | CLOSE_WAIT =>
  8509.    -- HERE WE WOULD SEGMENTIZE A BUFFER FOR TRANSMISSON, WHICH WE
  8510.    -- ARE CURRENTLY NOT DOING.
  8511.    if LCN.SND_WND + LCN.SND_UNA >= (LCN.SND_NXT + 
  8512.     SEGMENT_LENGTH) then
  8513.     -- USE THE SAME BUFFER ALL THE WAY
  8514.     TYPE_FLAG := SEGMENT;
  8515.     -- PUT THE DATA IN THE BUFFER
  8516.     for I in 1..SEGMENT_LENGTH loop
  8517.      BUFPTR.DATA(I) := PACKED_BUFF.BYTE(PACKED_BUFF.TCP_PTR+I);
  8518.     end loop;
  8519.     BUFPTR.DATA_LEN := SEGMENT_LENGTH;
  8520.     -- CLEAR OPTIONS ARRAY
  8521.     OPTIONS := CLEAR;
  8522.     TCP_HEADER_FORMAT(LCN, BUFPTR, TYPE_FLAG, OPTIONS);
  8523.     -- HERE WE MUST PUT IN THE NECESSARY SECURITY OPTIONS FOR IP.
  8524.     OPTIONS := TCP_SECURITY_OPTIONS;
  8525.     -- PACK THE BUFFER
  8526.     -- WE ASSUME THAT THE POINTER IS CORRECTLY SET.
  8527.     PACK_BUFFER_INTO_BIT_STREAM(BUFPTR, PACKED_BUFF);
  8528.     -- THE STANDARD HEADER LENGTH + DATA LENGTH
  8529.     LEN := BUFPTR.DATA_OFFSET * 4 + SEGMENT_LENGTH; 
  8530.     PACKED_BUFF.STATUS := OWNER_TCP;
  8531.     SEND_IP( LCN.SOURCE_ADDRESS,
  8532.              LCN.DESTINATION_ADDRESS,
  8533.              TOS,
  8534.              TTL,
  8535.              PACKED_BUFF,
  8536.              LEN,
  8537.              IDENT,
  8538.              DONT_FRAGMENT,
  8539.              OPTIONS,
  8540.              RESULT);
  8541.     -- PUT BUFFER IN RETRANSMISSION QUEUE AND SET THE TIMER
  8542.     -- LEN IS THE TOTAL NUM OF BYTES IN THE SEGMENT.
  8543.     Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER, LEN); 
  8544.     -- TESTING
  8545.     QUEUE_ADD(TCP_RETRANSMIT_QUEUE, LCN, Q_ITEM);
  8546.     -- WECOULD MESS WITH OUR RECEIVE WINDOW HERE IF WE WISHED.
  8547.     LCN.SND_NXT := LCN.SND_NXT + SEGMENT_LENGTH;
  8548.     if URG_FLAG = BIT_SET then
  8549.      LCN.SND_UP := LCN.SND_NXT - 1;
  8550.     end if;
  8551.    else
  8552.     -- PUT THE TEXT ON THE TRANSMIT QUEUE FOR PROCESSING WHEN AN ACK COMES
  8553.     -- IN AND WE CAN SEND IT.
  8554.     Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER, SEGMENT_LENGTH);
  8555.     QUEUE_ADD(TRANSMIT_QUEUE, LCN, Q_ITEM, NO_ROOM_ON_QUEUE);
  8556.     if NO_ROOM_ON_QUEUE then
  8557.      --TELL USER ERROR: INSUFFICIENT RESOURCES
  8558.      PUT_LINE("NO Q RM IN SEND");-- DEBUG
  8559.      PUT_LINE("STATE IS ESTAB");--DEBUG
  8560.      --INT_IO_16.PUT(SEGMENT_LENGTH);
  8561.      SOCKET_PARAMS:= LCN;
  8562.      UMESSAGE := ( 5, 
  8563.                    SOCKET_PARAMS);
  8564.      MESSAGE_FOR_USER(UMESSAGE);
  8565.     end if;
  8566.    end if;
  8567.   when others =>
  8568.    -- TELL USER ERROR: CONNECTION CLOSING
  8569.    SOCKET_PARAMS := LCN;
  8570.    UMESSAGE :=( 6, 
  8571.                 SOCKET_PARAMS);
  8572.    MESSAGE_FOR_USER(UMESSAGE);
  8573.  end case;
  8574. end TCP_SEND;
  8575.  procedure TCP_RECEIVE( LCN : in TCB_PTR; 
  8576.                         PACKED_BUFF : in out PACKED_BUFFER_PTR;
  8577.                 BYTE_COUNT : in SIXTEEN_BITS ) is
  8578.     --This subprogram is called by the user via the TCP controller. 
  8579.     --it will queue the request or if there is data to satisfy it, return 
  8580.     --a buffer full of data if one is available.  Otherwise it will simply 
  8581.     --queue the request until data becomes available.  The subprogram is 
  8582.     --passed a LCN, BYTE_COUNT which represents the size of the buffer if 
  8583.     --one is passed in, and PACKED_BUFF that contains the data to be 
  8584.     --returned to the user.
  8585.  RECEIVE_QUEUE_FULL : BOOLEAN;
  8586.  PACKED_BUFFER : PACKED_BUFFER_PTR;
  8587.  BUFFTYPE, PROCESSED_BYTE_COUNT : SIXTEEN_BITS ;
  8588.  Q_ITEM : STD_Q_ITEM;
  8589.  UMESSAGE : USER_MESSAGE;
  8590.  SOCKET_PARAMS : TCB_PTR;
  8591.  
  8592.  begin
  8593.   T_TCP_GLOBALS_DATA_STRUCTURES.LCN := LCN; -- FOR TEST***
  8594.   -- ALL RECEIVE REQUESTS THAT WE CAN HANDLE WILL BE SATISIFIED OR QUEUED
  8595.   -- ON THE TCP RECEIVE QUEUE FOR LATER PROCESSING WHEN DATA COMES IN.
  8596.   case LCN.STATE is
  8597.    when T_TCP_GLOBALS_DATA_STRUCTURES.CLOSED =>
  8598.     if USER_ACCESS_CHECK(LCN) then
  8599.      -- TELL USER ERROR: CONNECTION ILLEGAL FOR THIS PROCESS 
  8600.      SOCKET_PARAMS:= LCN;
  8601.      UMESSAGE := ( 2, 
  8602.                    SOCKET_PARAMS);
  8603.      MESSAGE_FOR_USER(UMESSAGE);
  8604.     else
  8605.      -- TELL USER ERROR: CONNECTION DOES NOT EXIST
  8606.      SOCKET_PARAMS := LCN;
  8607.      UMESSAGE := ( 3, 
  8608.                    SOCKET_PARAMS);
  8609.      MESSAGE_FOR_USER(UMESSAGE);
  8610.     end if;
  8611.    when T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN | SYN_SENT | SYN_RECEIVED =>
  8612.     -- PUT REQUEST ON QUEUE FOR LATER PROCESSING
  8613.     Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER, BYTE_COUNT);
  8614.     QUEUE_ADD(RECEIVE_QUEUE, LCN, Q_ITEM, RECEIVE_QUEUE_FULL);
  8615.     if RECEIVE_QUEUE_FULL then
  8616.      -- TELL USER ERROR: INSUFFICIENT RESOURCES
  8617.      PUT_LINE("NO Q RM IN RECEIVE");-- DEBUG
  8618.      SOCKET_PARAMS := LCN;
  8619.      UMESSAGE := ( 5, 
  8620.                    SOCKET_PARAMS);
  8621.      MESSAGE_FOR_USER(UMESSAGE);
  8622.     end if;
  8623.    when ESTABLISHED | FIN_WAIT_1 | FIN_WAIT_2 =>
  8624.     -- NOTE THAT WE CONSIDER ANY DATA TO BE SUFFICIENT DATA FOR A BUFFER.
  8625.     -- WE DO NOTHING WITH THE PUSH FLAG SINCE WE CURRENTLY PUSH EVERYTHING.
  8626.     -- ALSO WE MAKE NO PROVISION FOR URGENT DATA AND DO NOT CHECK FOR IT.
  8627.     -- GET A BUNCH OF DATA IF WE CAN.
  8628.     QUEUE_GET(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN, Q_ITEM);
  8629.     PROCESSED_BYTE_COUNT := Q_ITEM.LENGTH;
  8630.     PACKED_BUFFER := Q_ITEM.BUFFER;
  8631.     if PACKED_BUFFER = null then
  8632.     -- PUT REQUEST ON QUEUE FOR LATER PROCESSING
  8633.     Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER, BYTE_COUNT);
  8634.     QUEUE_ADD(RECEIVE_QUEUE, LCN, Q_ITEM, RECEIVE_QUEUE_FULL);
  8635.     if RECEIVE_QUEUE_FULL then
  8636.     -- TELL USER ERROR: INSUFFICIENT RESOURCES
  8637.     PUT_LINE("NO Q RM IN SEND");-- DEBUG
  8638.     SOCKET_PARAMS := LCN;
  8639.     UMESSAGE := ( 5, 
  8640.                   SOCKET_PARAMS);
  8641.     MESSAGE_FOR_USER(UMESSAGE);
  8642.    end if;
  8643.   else
  8644.    -- FILL BUFFER WITH QUEUED INCOMING SEGMENTS
  8645.    INSERT_TEXT_IN_BUFFER(BYTE_COUNT, PACKED_BUFF,
  8646.     PROCESSED_BYTE_COUNT, PACKED_BUFFER);
  8647.    -- WE IGNORE A PUSH; WE IGNORE URGENT POINTER
  8648.    -- GIVE THE BUFFER TO THE USER
  8649.    SOCKET_PARAMS := LCN;
  8650.    UMESSAGE := ( 10, 
  8651.                  SOCKET_PARAMS, 
  8652.                  PACKED_BUFF);
  8653.    MESSAGE_FOR_USER(UMESSAGE);
  8654.    -- FREE UP THE PACKED BUFFER
  8655.    PACKED_BUFFER.STATUS := NONE;
  8656.    PACKED_BUFFER.IN_USE := FALSE;
  8657.    BUFFREE(PACKED_BUFFER, BUFFTYPE);
  8658.   end if;
  8659.  when CLOSE_WAIT =>
  8660.   QUEUE_GET(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN, Q_ITEM);
  8661.   PROCESSED_BYTE_COUNT := Q_ITEM.LENGTH;
  8662.   PACKED_BUFFER := Q_ITEM.BUFFER;
  8663.   if PACKED_BUFFER = null then
  8664.    -- ERROR: CONNECTION    CLOSING
  8665.    SOCKET_PARAMS := LCN;
  8666.    UMESSAGE := ( 6, 
  8667.                  SOCKET_PARAMS);
  8668.    MESSAGE_FOR_USER(UMESSAGE);
  8669.   else
  8670.    -- FILL BUFFER WITH ANY REMAINING TEXT
  8671.    INSERT_TEXT_IN_BUFFER(BYTE_COUNT, PACKED_BUFF,
  8672.     PROCESSED_BYTE_COUNT, PACKED_BUFFER);
  8673.    -- RETURN BUFFER TO USER 
  8674.    SOCKET_PARAMS := LCN;
  8675.    UMESSAGE := ( 10,
  8676.                  SOCKET_PARAMS, 
  8677.                  PACKED_BUFF);
  8678.    MESSAGE_FOR_USER(UMESSAGE);
  8679.    -- FREE UP THE PACKED BUFFER
  8680.    PACKED_BUFFER.IN_USE := FALSE;
  8681.    PACKED_BUFFER.STATUS := NONE;
  8682.    BUFFREE(PACKED_BUFFER, BUFFTYPE);
  8683.   end if;
  8684.  when CLOSING | TIME_WAIT | LAST_ACK    =>
  8685.   -- TELL USER ERROR: CONNECTION CLOSING
  8686.   SOCKET_PARAMS := LCN;
  8687.   UMESSAGE := ( 6, 
  8688.                 SOCKET_PARAMS);
  8689.   MESSAGE_FOR_USER(UMESSAGE);
  8690.  end case;
  8691. exception
  8692.  when constraint_error =>
  8693.   PUT_LINE("CONSTRAINT ERROR IN TCP RECEIVE");
  8694.  when others =>
  8695.   PUT_LINE("ERROR IN TCP RECEIVE");
  8696. end TCP_RECEIVE;
  8697.  procedure TCP_ABORT( LCN : in TCB_PTR) is
  8698.     --This subprogram is called by the user via the TCP controller to 
  8699.         --abort a connection.  It does this by sending a reset to the remote 
  8700.     --host and clearing the TCB associated with the particular local 
  8701.     --connection name. All queues will have the items from this connection 
  8702.     --removed from them.
  8703.  USER_SHOULD_NOT_HAVE_ACCESS : BOOLEAN;
  8704.  BUFFLEN : SIXTEEN_BITS ;
  8705.  BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  8706.  PACKED_BUFF : PACKED_BUFFER_PTR;
  8707.  UMESSAGE : USER_MESSAGE;
  8708.  SOCKET_PARAMS : TCB_PTR;
  8709.  MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  8710.  begin
  8711.   T_TCP_GLOBALS_DATA_STRUCTURES.LCN := LCN; -- FOR TEST***
  8712.   case LCN.STATE is
  8713.    when T_TCP_GLOBALS_DATA_STRUCTURES.CLOSED =>
  8714.     if USER_ACCESS_CHECK(LCN) then
  8715.      -- TELL USER ERROR: CONNECTION ILLEGAL FOR THIS PROCESS 
  8716.      SOCKET_PARAMS := LCN;
  8717.      UMESSAGE := ( 2,
  8718.                    SOCKET_PARAMS);
  8719.      MESSAGE_FOR_USER(UMESSAGE);
  8720.     else
  8721.      -- TELL USER ERROR: CONNECTION DOES NOT EXIST
  8722.      SOCKET_PARAMS := LCN;
  8723.      UMESSAGE := ( 3, 
  8724.                    SOCKET_PARAMS);
  8725.      MESSAGE_FOR_USER(UMESSAGE);
  8726.     end if;
  8727.    when T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN => 
  8728.     QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  8729.     -- CLEAR THE TCB AND ENTER THE CLOSED STATE
  8730.     LCN.STATE := CLOSED;
  8731.     TCB_CLEAR(LCN);
  8732.    when SYN_SENT => 
  8733.     QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  8734.     -- NONE ON THIS LEVEL. CLEAR_SEND_QUEUE(LCN);
  8735.     -- CLEAR THE TCB AND ENTER THE CLOSED STATE
  8736.     QUEUE_CLEAR(TCP_RETRANSMIT_QUEUE, LCN);
  8737.     QUEUE_CLEAR(TRANSMIT_QUEUE, LCN);
  8738.     TCB_CLEAR(LCN);
  8739.    when SYN_RECEIVED |    ESTABLISHED | FIN_WAIT_1 | FIN_WAIT_2
  8740.      | CLOSE_WAIT =>  -- SEND A RESET SEGMENT
  8741.     BUFFGET(PACKED_BUFF, BUFFLEN);
  8742.     if PACKED_BUFF = null then -- ERROR OUT OF    BUFFERS
  8743.      TCP_ERROR(1);
  8744.     else
  8745.      PACKED_BUFF.STATUS := NONE;
  8746.      PACKED_BUFF.IN_USE := TRUE;
  8747.      TCP_HEADER_FORMAT(    LCN, BUFPTR, RST, OPTIONS);
  8748.       -- HERE WE MUST PUT IN THE NECESSARY SECURITY OPTIONS FOR IP.
  8749.       OPTIONS := TCP_SECURITY_OPTIONS;
  8750.       -- PACK THE BUFFER
  8751.       PACK_BUFFER_INTO_BIT_STREAM(BUFPTR, PACKED_BUFF);
  8752.       LEN := BUFPTR.DATA_OFFSET * 4;-- SINCE NO DATA SENT
  8753.     SEND_IP( LCN.SOURCE_ADDRESS,
  8754.              LCN.DESTINATION_ADDRESS,
  8755.              TOS,
  8756.              TTL,
  8757.              PACKED_BUFF,
  8758.              LEN,
  8759.              IDENT,
  8760.              DONT_FRAGMENT,
  8761.              OPTIONS,
  8762.              RESULT);
  8763.     end    if;
  8764.     QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  8765.     -- NONE ON THIS LEVEL. CLEAR_SEND_QUEUE(LCN);
  8766.     --    TRASH TRANSMIT AND RETRANSMIT QUEUES
  8767.     QUEUE_CLEAR(TRANSMIT_QUEUE, LCN); 
  8768.     QUEUE_CLEAR(TCP_RETRANSMIT_QUEUE, LCN);
  8769.     QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE, LCN);
  8770.     -- CLEAR THE TCB AND ENTER    THE CLOSED STATE
  8771.     LCN.STATE := CLOSED;
  8772.     TCB_CLEAR(LCN);
  8773.    when CLOSING | LAST_ACK | TIME_WAIT =>
  8774.     -- TELL USER OK
  8775.     SOCKET_PARAMS := LCN;
  8776.     UMESSAGE := ( 8, 
  8777.                   SOCKET_PARAMS);
  8778.     MESSAGE_FOR_USER(UMESSAGE);
  8779.     -- CLEAR THE TCB AND ENTER THE CLOSED STATE
  8780.     QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  8781.     TCB_CLEAR(LCN); -- PUT IN A KNOWN STATE
  8782.    end case;
  8783.   end TCP_ABORT;
  8784.  procedure TCP_CLOSE( LCN : in TCB_PTR) IS
  8785.   BEGIN       -- REQUIRED TO REDUCE FILE SIZE
  8786.     T_tcp_utilities_1.tcp_close (LCN ) ;
  8787.   END TCP_CLOSE ;
  8788.  procedure TCP_OPEN(LOCAL_PORT, FOREIGN_PORT :in SIXTEEN_BITS ; 
  8789.                     FOREIGN_NET_HOST : in THIRTYTWO_BITS ;
  8790.             ACTIVE_PASSIVE : in WITH_TCP_COMMUNICATE.ACKPASS;    
  8791.             BUFFER_SIZE, TIMEOUT : in SIXTEEN_BITS ;  
  8792.                     LOCAL_CONN_NAME : in out TCB_PTR ;
  8793.             SECURITY, PRECEDENCE : in SIXTEEN_BITS ;
  8794.             OPTIONS : in TCP_OPTION_TYPE) IS
  8795.   
  8796.   BEGIN         -- REQUIRED TO REDUCE FILE SIZE
  8797.     T_tcp_utilities_1.tcp_open (local_port, foreign_port, foreign_net_host,
  8798.      active_passive, buffer_size,timeout, local_conn_name, security, precedence,
  8799.      options) ;
  8800.   END tcp_open ;
  8801.  procedure TCP_STATUS(LCN : in TCB_PTR) IS
  8802.   BEGIN        -- REQUIRED TO REDUCE FILE SIZE
  8803.     T_tcp_utilities_1.tcp_status (LCN) ;
  8804.   END tcp_status ;
  8805.  procedure RETRANS_TCP(LCN : in TCB_PTR) IS
  8806.    
  8807.   BEGIN        -- REQUIRED TO REDUCE FILE SIZE
  8808.     T_tcp_utilities_1.retrans_tcp (LCN) ;
  8809.   END retrans_tcp ;
  8810. end T_TCP_CONTROLLER_UTILITIES;
  8811. --::::::::::::::
  8812. --tcputil1.txt
  8813. --::::::::::::::
  8814. -----------------------------------------------------------------------
  8815. --
  8816. --         DoD Protocols    NA-00008-200       80-01200-100(-)
  8817. --         E-Systems, Inc.  August 07, 1985
  8818. --
  8819. --         tcputil1.txt       Author : Jim Baldo
  8820. --
  8821. -----------------------------------------------------------------------
  8822. with WITH_TCP_COMMUNICATE ;        use WITH_TCP_COMMUNICATE ;
  8823. with MODULO;                use MODULO;
  8824. with BUFFER_DATA;            use BUFFER_DATA;
  8825. -- COMMUNICATE AND QUEUE CONTAINS THE NECESSARY    FACILITIES FOR MESSAGES    TO BE
  8826. -- QUEUED BETWEEN TASKS.
  8827. with T_TCP_GLOBALS_DATA_STRUCTURES;    USE T_TCP_GLOBALS_DATA_STRUCTURES;
  8828.         
  8829.                 package T_TCP_UTILITIES_1 is
  8830.     
  8831.         --------------------------------------------------------------------
  8832.     --This implementation is for use with the TeleSoft/Ada compiler   --
  8833.     --version .                                                       --
  8834.     --------------------------------------------------------------------
  8835.  
  8836.  procedure TCP_CLOSE( LCN : in TCB_PTR);
  8837.  procedure TCP_OPEN(LOCAL_PORT, FOREIGN_PORT :in SIXTEEN_BITS ; 
  8838.                     FOREIGN_NET_HOST : in THIRTYTWO_BITS ;
  8839.             ACTIVE_PASSIVE : in WITH_TCP_COMMUNICATE.ACKPASS;    
  8840.             BUFFER_SIZE, TIMEOUT : in SIXTEEN_BITS ;  
  8841.                     LOCAL_CONN_NAME : in out TCB_PTR ;
  8842.             SECURITY, PRECEDENCE : in SIXTEEN_BITS ;
  8843.             OPTIONS : in TCP_OPTION_TYPE);
  8844.  procedure TCP_STATUS(LCN : in TCB_PTR);
  8845.  procedure RETRANS_TCP(LCN : in TCB_PTR);
  8846. end T_TCP_UTILITIES_1 ;
  8847. with SYSTEM;
  8848. with UNCHECKED_CONVERSION;
  8849. with QUEUES;                     use QUEUES;
  8850. with IP_GLOBALS;                 use IP_GLOBALS;
  8851. with TCP_SEGMENT_ARRIVES_PROCESSING;
  8852. use TCP_SEGMENT_ARRIVES_PROCESSING;
  8853. with TEXT_IO;                    use TEXT_IO;
  8854. with TCP_GLOBALS;                use TCP_GLOBALS;
  8855. with TCB_ALLOCATOR;              use TCB_ALLOCATOR;
  8856. with WITH_ULP_COMMUNICATE;       use WITH_ULP_COMMUNICATE;
  8857. with WITH_IP_COMMUNICATE;        use WITH_IP_COMMUNICATE;
  8858.         
  8859.                 package body T_TCP_UTILITIES_1 is
  8860.  
  8861.  function USER_ACCESS_CHECK( LCN : in TCB_PTR ) return BOOLEAN is
  8862.  
  8863.  RESULT : BOOLEAN := TRUE;
  8864.  I : TCB_PTR := OBTAIN_HEAD_OF_LCN_IN_USE_QUEUE;
  8865.                  -- The beginning index into the LCN list!
  8866.  
  8867.  begin
  8868.   while I /= null loop
  8869.    if I = LCN then
  8870.     RESULT := FALSE;
  8871.    end if;
  8872.    I := I.NEXT;
  8873.   end loop;
  8874.   return RESULT;
  8875.  exception
  8876.   when OTHERS =>
  8877.    PUT("PROBLEM IN USER ACCESS CHECK");
  8878.  end USER_ACCESS_CHECK;
  8879.   
  8880.   procedure SEND_A_SYN( LCN : in TCB_PTR ) is
  8881.   
  8882.   HEADER_LENGTH : SIXTEEN_BITS := 20;
  8883.   BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  8884.   DEST : THIRTYTWO_BITS;
  8885.   SOURCE : THIRTYTWO_BITS;
  8886.   PACKED_BUFF : PACKED_BUFFER_PTR;
  8887.   BUFFLEN : SIXTEEN_BITS;
  8888.   Q_ITEM : STD_Q_ITEM;
  8889.   UMESSAGE : USER_MESSAGE;
  8890.   SOCKET_PARAMS : TCB_PTR;
  8891.   MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE;
  8892.   
  8893.   begin
  8894.    BUFFGET( PACKED_BUFF, 0 );
  8895.    if PACKED_BUFF = null then
  8896.     SOCKET_PARAMS := LCN;
  8897.     UMESSAGE := ( -1,
  8898.                   SOCKET_PARAMS);
  8899.     MESSAGE_FOR_USER( UMESSAGE );
  8900.    else
  8901.     PACKED_BUFF.STATUS := OWNER_TCP;
  8902.     PACKED_BUFF.IN_USE := TRUE;
  8903.     LCN.ISS := MODULAR_CONVERT( ISS );
  8904.     LCN.SND_NXT := LCN.ISS;
  8905.     TYPE_FLAG := SYN;
  8906.     OPTIONS := CLEAR;
  8907.     TCP_HEADER_FORMAT( LCN, BUFPTR, TYPE_FLAG, OPTIONS);
  8908.     DEST := LCN.DESTINATION_ADDRESS;
  8909.     OPTIONS := TCP_SECURITY_OPTIONS;
  8910.     PACK_BUFFER_INTO_BIT_STREAM( BUFPTR, PACKED_BUFF );
  8911.     SOURCE := IP_GLOBALS.WHOIAM;
  8912.     SEND_IP( SOURCE,
  8913.              DEST,
  8914.              TOS,
  8915.              TTL,
  8916.              PACKED_BUFF,
  8917.              HEADER_LENGTH,
  8918.              IDENT,
  8919.              DONT_FRAGMENT,
  8920.              OPTIONS,
  8921.              RESULT);
  8922.     LCN.SND_UNA := LCN.ISS;
  8923.     LCN.SND_NXT := LCN.ISS + MODULAR_CONVERT(SIXTEEN_BITS(1));
  8924.     Q_ITEM := ( PACKED_BUFF,
  8925.                 NULL_UNPACKED_BUFFER,
  8926.                 HEADER_LENGTH);
  8927.     QUEUE_ADD( TCP_RETRANSMIT_QUEUE,
  8928.                LCN,
  8929.                Q_ITEM);
  8930.    end if;
  8931.   end SEND_A_SYN;
  8932.   
  8933.   procedure TCP_CLOSE(LCN : in TCB_PTR) is
  8934.         
  8935.     --This subprogram is called by the user via the TCP controller. 
  8936.     --It will send a FIN to a remote host. This will cause the connection 
  8937.     --to close down upon a FIN and/or an ACK from the remote host.
  8938.         UMESSAGE : WITH_ULP_COMMUNICATE.USER_MESSAGE;
  8939.         SOCKET_PARAMS : TCB_PTR;
  8940.  procedure SEND_A_FIN(LCN : in TCB_PTR) is
  8941.     --This subprogram formats and sends a FIN to the IP for transmission 
  8942.     --to the remote host.
  8943.         BUFPTR : T_TCP_GLOBALS_DATA_STRUCTURES.BUFFER_POINTER;
  8944.         BUFFLEN    : SIXTEEN_BITS ;
  8945.         PACKED_BUFF : PACKED_BUFFER_PTR;
  8946.         SEGMENT_DATA_LENGTH : CONSTANT SIXTEEN_BITS  := 1; 
  8947.         TCP_HEAD_AND_DATA_LENGTH : CONSTANT SIXTEEN_BITS  := 20;
  8948.         -- THE LENGTH OF A FIN SEGMENT WITHOUT OPTIONS
  8949.         NO_ROOM : BOOLEAN;
  8950.         Q_ITEM : STD_Q_ITEM;
  8951.         UMESSAGE : USER_MESSAGE;
  8952.         MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  8953.         begin
  8954.          BUFFGET(PACKED_BUFF, BUFFLEN);
  8955.          if PACKED_BUFF = null then
  8956.           -- TELL USE ERROR: INSUFFICIENT RESOURCES
  8957.           SOCKET_PARAMS := LCN;
  8958.           UMESSAGE := ( 20, 
  8959.                         SOCKET_PARAMS);
  8960.           MESSAGE_FOR_USER(UMESSAGE);
  8961.           SOCKET_PARAMS := LCN;
  8962.           UMESSAGE := ( 5, 
  8963.                         SOCKET_PARAMS);
  8964.           MESSAGE_FOR_USER(UMESSAGE);
  8965.          elsif LCN.SND_WND + LCN.SND_UNA >= (LCN.SND_NXT + 
  8966.             SEGMENT_DATA_LENGTH) then -- WE CAN SEND IT.
  8967.           PACKED_BUFF.IN_USE := TRUE;
  8968.           PACKED_BUFF.STATUS := OWNER_TCP;
  8969.           TYPE_FLAG := FIN;
  8970.           -- CLEAR THE OPTIONS ARRAY
  8971.           OPTIONS := CLEAR;
  8972.           TCP_HEADER_FORMAT(LCN, BUFPTR, TYPE_FLAG, OPTIONS);--FIN
  8973.           -- HERE WE MUST PUT IN THE NECESSARY SECURITY OPTIONS FOR IP.
  8974.           OPTIONS := TCP_SECURITY_OPTIONS;
  8975.           -- PACK THE BUFFER
  8976.           PACK_BUFFER_INTO_BIT_STREAM(BUFPTR, PACKED_BUFF);
  8977.                     SEND_IP( LCN.SOURCE_ADDRESS,
  8978.                    LCN.DESTINATION_ADDRESS,
  8979.                    TOS,
  8980.                    TTL,
  8981.                    PACKED_BUFF,
  8982.                    TCP_HEAD_AND_DATA_LENGTH,
  8983.                    IDENT,
  8984.                    DONT_FRAGMENT,
  8985.                    OPTIONS,
  8986.                    RESULT);
  8987. -- UPDATE THE SEND NEXT
  8988.           LCN.SND_NXT := LCN.SND_NXT + MODULAR_CONVERT ( SIXTEEN_BITS (1));
  8989.           --  PUT IT ON THE RETRANSMIT QUEUE IT IS QUEUED UP WITH A TIME.
  8990.           Q_ITEM := 
  8991.            (PACKED_BUFF, NULL_UNPACKED_BUFFER,TCP_HEAD_AND_DATA_LENGTH);
  8992.           QUEUE_ADD(TCP_RETRANSMIT_QUEUE, LCN, Q_ITEM);
  8993.          else
  8994.           -- PUT IT ON THE TRANSMIT QUEUE FOR LATER PROCESSING.
  8995.           Q_ITEM := (PACKED_BUFF, NULL_UNPACKED_BUFFER,
  8996.             TCP_HEAD_AND_DATA_LENGTH);
  8997.           QUEUE_ADD(TRANSMIT_QUEUE, LCN, Q_ITEM);
  8998.          end if;
  8999.         end SEND_A_FIN;
  9000.         begin -- TCP_CLOSE
  9001.          T_TCP_GLOBALS_DATA_STRUCTURES.LCN := LCN; -- FOR TEST
  9002.          case LCN.STATE is
  9003.           when T_TCP_GLOBALS_DATA_STRUCTURES.CLOSED =>
  9004.            if USER_ACCESS_CHECK(LCN) then
  9005.             -- TELL USER ERROR: CONNECTION ILLEGAL FOR THIS PROCESS 
  9006.             SOCKET_PARAMS := LCN;
  9007.             UMESSAGE := ( 2, 
  9008.                           SOCKET_PARAMS);
  9009.             MESSAGE_FOR_USER(UMESSAGE);
  9010.            else
  9011.         -- TELL USER ERROR: CONNECTION DOES NOT EXIST
  9012.             SOCKET_PARAMS := LCN;
  9013.          UMESSAGE := ( 3, 
  9014.                           SOCKET_PARAMS);
  9015.         MESSAGE_FOR_USER(UMESSAGE);
  9016.        end if;
  9017.       when T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN => 
  9018.                         QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  9019.        -- CLEAR TCB AND ENTER THE CLOSED STATE
  9020.        TCB_CLEAR(LCN);
  9021.        LCN.STATE := CLOSED;
  9022.       when SYN_SENT    => -- NONE ON THIS LEVEL. CLEAR_SEND_QUEUE(LCN);
  9023.        QUEUE_CLEAR(RECEIVE_QUEUE, LCN);
  9024.        -- CLEAR THE    TCB AND    ENTER THE CLOSED STATE. 
  9025.        TCB_CLEAR(LCN);
  9026.        LCN.STATE := CLOSED;
  9027.       when SYN_RECEIVED | ESTABLISHED => 
  9028.        if QUEUE_EMPTY(TRANSMIT_QUEUE, LCN) then 
  9029.         SEND_A_FIN(LCN);
  9030.        else    
  9031.         -- SET THE CLOSE PENDING FLAG IN THE TCB.
  9032.         LCN.CLOSE_PENDING := TRUE;
  9033.        end if;
  9034.        -- ENTER THE FIN-WAIT-1 STATE
  9035.            LCN.STATE := FIN_WAIT_1;
  9036.       when FIN_WAIT_1 | FIN_WAIT_2 => 
  9037.        --TELL USER ERROR: CONNECTION CLOSING
  9038.            SOCKET_PARAMS := LCN;
  9039.        UMESSAGE := ( 6, 
  9040.                          SOCKET_PARAMS);
  9041.            MESSAGE_FOR_USER(UMESSAGE);
  9042.       when CLOSE_WAIT => 
  9043.        if QUEUE_EMPTY(TRANSMIT_QUEUE, LCN) then 
  9044.         SEND_A_FIN(LCN);
  9045.         -- ENTER THE LAST ACK STATE
  9046.         LCN.STATE := LAST_ACK;
  9047.         QUEUE_CLEAR(PROCESSED_SEGMENTS_FOR_USER_QUEUE,LCN);
  9048.        else    
  9049.         -- SET TH CLOSE PENDING FLAG IN THE TCB.
  9050.         LCN.CLOSE_PENDING := TRUE;
  9051.         -- WHEN THE FIN IS SENT DUE TO THE CLOSE PENDING
  9052.         -- FLAG THE STATE MUST BE CHANGED.
  9053.        end if;
  9054.       when CLOSING | LAST_ACK | TIME_WAIT    =>
  9055.        --TELL USER ERROR: CONNECTION CLOSING
  9056.            SOCKET_PARAMS := LCN;
  9057.        UMESSAGE := ( 6, 
  9058.                          SOCKET_PARAMS);
  9059.            MESSAGE_FOR_USER(UMESSAGE);
  9060.      end case;
  9061.     end TCP_CLOSE;
  9062.  procedure TCP_OPEN( LOCAL_PORT, FOREIGN_PORT : in SIXTEEN_BITS ; 
  9063.                      FOREIGN_NET_HOST : in THIRTYTWO_BITS ;
  9064.              ACTIVE_PASSIVE : in WITH_TCP_COMMUNICATE.ACKPASS;    
  9065.              BUFFER_SIZE, TIMEOUT : in SIXTEEN_BITS ;  
  9066.                      LOCAL_CONN_NAME : in out TCB_PTR ;
  9067.              SECURITY, PRECEDENCE : in SIXTEEN_BITS ;
  9068.              OPTIONS : in TCP_OPTION_TYPE) is
  9069. --This subprogram will perform the actions necessary to do a passive or
  9070. --an active OPEN. If a passive OPEN is requested the listen state will
  9071. --entered. If an active OPEN is requested a SYN will be sent and the 
  9072. --connection actively pursued.  The subprogram is called by the user layer 
  9073. --via the TCP controller.  The following parameters are passed to the 
  9074. --subprogram :
  9075. --    LOCAL_PORT : The local port identification number.
  9076. --    FOREIGN_NET_HOST : The foreign net address of the remote host we wish 
  9077. --        to talk with and the address of the foreign host on the net. 
  9078. --        they are concatenated in a format found in the IP spec.
  9079. --     FOREIGN_PORT : The port in the foreign host that we wish to send to.
  9080. --    ACTIVE_PASSIVE : indicates whether an active or passive OPEN is
  9081. --         desired.
  9082. --    TIMEOUT : The timeout for transmitting data. if some data does not get
  9083. --           through in the required time the connection is aborted.
  9084. --    SECURITY : The request for a level of security.  Which must be a 
  9085. --        legal level. 
  9086. --    PRECEDENCE : The precedence of the connection. Used in a multi-level, 
  9087. --                secure environment.
  9088. --    OPTIONS :  This data structure will contain a request for any options 
  9089. --           desired.  Currently none will be.
  9090. --
  9091. -- RESTRICTIONS :
  9092. --
  9093. --   CURRENTLY WE ALLOW ONLY ONE CONNECTION PER PORT.
  9094. --
  9095.     NO_ROOM_FOR_CONNECTION : BOOLEAN := FALSE;
  9096.         UMESSAGE : USER_MESSAGE;
  9097.         SOCKET_PARAMS : TCB_PTR;
  9098.     begin
  9099.          --if ACTIVE_PASSIVE = WITH_TCP_COMMUNICATE.PASSIVE then
  9100.        T_TCP_GLOBALS_DATA_STRUCTURES.LCN := TCB_ALLOCATOR.TCB_GET; -- SEND THE LCN BACK TO THE USER.
  9101.           TCB_CLEAR( LCN ) ; -- Clear TCB.
  9102.           SOCKET_PARAMS := LCN ;
  9103.           LOCAL_CONN_NAME := LCN ;
  9104.          UMESSAGE := (14, SOCKET_PARAMS);
  9105.       MESSAGE_FOR_USER(UMESSAGE);
  9106.       LCN.LOCAL_PORT := LOCAL_PORT;
  9107.          --end if ;
  9108.      if LCN.STATE = T_TCP_GLOBALS_DATA_STRUCTURES.CLOSED then
  9109.          if USER_ACCESS_CHECK(LCN) then
  9110.        -- TELL USER ERROR: CONNECTION ILLEGAL FOR THIS PROCESS.
  9111.            SOCKET_PARAMS := LCN;
  9112.        UMESSAGE := ( 2, 
  9113.                          SOCKET_PARAMS);
  9114.        MESSAGE_FOR_USER(UMESSAGE);
  9115.       elsif    NO_ROOM_FOR_CONNECTION then -- THERE IS CURRENTLY ALWAYS ROOM
  9116.        -- TELL USER ERROR: INSUFFICIENT RESOURCES
  9117.        PUT_LINE("IN OPEN INSUF RESOURCES");-- DEBUG
  9118.            SOCKET_PARAMS := LCN;
  9119.        UMESSAGE := ( 5, 
  9120.                          SOCKET_PARAMS);
  9121.        MESSAGE_FOR_USER(UMESSAGE);
  9122.       elsif    ACTIVE_PASSIVE = WITH_TCP_COMMUNICATE.ACTIVE then
  9123.        if PRECEDENCE < 0 or (PRECEDENCE > 7) then
  9124.         -- TELL USER ERROR:    PRECEDENCE NOT ALLOWED
  9125.             SOCKET_PARAMS := LCN;
  9126.         UMESSAGE := ( 9, 
  9127.                           SOCKET_PARAMS);
  9128.         MESSAGE_FOR_USER(UMESSAGE);
  9129.        elsif SECURITY < 0 or (SECURITY > 7) then
  9130.         -- TELL USER ERROR: SECURITY/COMPARTMENT NOT ALLOWED
  9131.             SOCKET_PARAMS := LCN;
  9132.         UMESSAGE := ( 11, 
  9133.                           SOCKET_PARAMS);
  9134.         MESSAGE_FOR_USER(UMESSAGE);
  9135.        elsif FOREIGN_NET_HOST = 0 then
  9136.         -- TELL USER ERROR: FOREIGN SOCKET    UNSPECIFIED
  9137.             SOCKET_PARAMS := LCN;
  9138.         UMESSAGE := ( 4, 
  9139.                           SOCKET_PARAMS);
  9140.         MESSAGE_FOR_USER(UMESSAGE);
  9141.        else
  9142.             -- START THE TIMEOUT FOR CONNECTION TIMER
  9143.         if TIMEOUT /= 0 then -- PUT IN THE NEW CONNECTION TIMEOUT.
  9144.          LCN.CONNECTION_TIMEOUT := TIMEOUT;
  9145.         end if;
  9146.             START_TIMER(LCN, TIMEOUT_TIMER);
  9147.             -- SET UP THE TCB
  9148.             LCN.DESTINATION_ADDRESS := FOREIGN_NET_HOST;
  9149.             LCN.FOREIGN_PORT := FOREIGN_PORT;
  9150.             -- SET UP THE TCB NET AND HOST ADDRESSES BY 
  9151.         -- DECODING THE CONCATENATION OF FOREIGN_NET AND
  9152.             --  FOREIGN HOST. 
  9153.             ADDRESS_DECODER(FOREIGN_NET_HOST);
  9154.             SEND_A_SYN(LCN);
  9155.             LCN.STATE := SYN_SENT; -- ENTER THE SYN-SENT    STATE
  9156.            end if;
  9157.           else -- THIS IS A PASSIVE OPEN
  9158.            if FOREIGN_NET_HOST /= 0 then
  9159.             -- SET UP THE TCB.
  9160.             LCN.FOREIGN_PORT := FOREIGN_PORT;
  9161.             LCN.DESTINATION_ADDRESS := FOREIGN_NET_HOST ;
  9162.             -- DECODE THE TCB DESTINATION ADDRESS. A CONCATENATION 
  9163.         -- OF FOREIGN_NET AND FOREIGN HOST AND PUT IT 
  9164.         -- IN THE APPROPRIATE VARIABLES IN THE TCB.
  9165.             ADDRESS_DECODER(FOREIGN_NET_HOST);
  9166.            end if;
  9167.        if TIMEOUT /= 0 then -- PUT IN THE NEW CONNECTION TIMEOUT.
  9168.         LCN.CONNECTION_TIMEOUT := TIMEOUT;
  9169.        end if;
  9170.        LCN.ACTIVE_PASSIVE := T_TCP_GLOBALS_DATA_STRUCTURES.PASSIVE; -- A PASSIVE OPEN
  9171.        LCN.STATE := T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN; 
  9172.            -- ENTER THE LISTEN STATE   
  9173.       end if;
  9174.      elsif LCN.STATE = T_TCP_GLOBALS_DATA_STRUCTURES.LISTEN then
  9175.           if ACTIVE_PASSIVE = WITH_TCP_COMMUNICATE.ACTIVE then
  9176.        if FOREIGN_NET_HOST = 0 then
  9177.         -- TELL USER ERROR: FOREIGN SOCKET UNSPECIFIED
  9178.             SOCKET_PARAMS := LCN;
  9179.         UMESSAGE := ( 4, 
  9180.                           SOCKET_PARAMS);
  9181.         MESSAGE_FOR_USER(UMESSAGE);
  9182.        else
  9183.         -- SET UP THE TCB
  9184.         LCN.ACTIVE_PASSIVE := T_TCP_GLOBALS_DATA_STRUCTURES.ACTIVE; 
  9185.         -- CONNECTION NOW ACTIVE.
  9186.         LCN.FOREIGN_PORT := FOREIGN_PORT;
  9187.         LCN.DESTINATION_ADDRESS := FOREIGN_NET_HOST ;
  9188.         -- START THE CONNECTION TIMEOUT TIMER.
  9189.         START_TIMER(LCN, TIMEOUT_TIMER);--not used presently (JB 1/25/85)
  9190.         -- DECODE THE TCB DESTINATION ADDRESS. A CONCATENATION 
  9191.         -- OF FOREIGN_NET AND FOREIGN HOST AND PUT IT IN 
  9192.         -- THE APPROPRIATE VARIABLES IN THE TCB
  9193.         ADDRESS_DECODER(FOREIGN_NET_HOST);
  9194.         SEND_A_SYN(LCN);
  9195.         LCN.STATE := SYN_SENT; -- ENTER THE SYN_SENT STATE
  9196.        end if;
  9197.       end if;
  9198.       if TIMEOUT /= 0 then -- PUT IN THE NEW CONNECTION TIMEOUT.
  9199.        LCN.CONNECTION_TIMEOUT := TIMEOUT;
  9200.       end if;
  9201.      else -- THERE ALREADY IS A CONNECTION
  9202.       -- TELL USER ERROR: CONNECTION ALREADY EXISTS
  9203.          SOCKET_PARAMS := LCN;
  9204.      UMESSAGE := ( 12, 
  9205.                        SOCKET_PARAMS);
  9206.      MESSAGE_FOR_USER(UMESSAGE);
  9207.     end if;
  9208.        end TCP_OPEN;
  9209.  procedure TCP_STATUS( LCN : in TCB_PTR) is
  9210.  
  9211.     --This subprogram returns the status of a connection, specified by the 
  9212.     --LCN to the user layer.  It also returns a pointer to the TCB for the 
  9213.         --connection, which will indicate the state of the connection(OPEN 
  9214.        --or CLOSED).  The subprogram is called by the user interface via the 
  9215.     --TCP controller.  LCN is passed as a parameter to the subprogram.
  9216. STATE : T_TCP_GLOBALS_DATA_STRUCTURES.STATUS_TYPE;
  9217. STATUS_REC : STATUS_RECORD;
  9218. UMESSAGE :USER_MESSAGE;
  9219. SOCKET_PARAMS : TCB_PTR;
  9220. begin
  9221.  T_TCP_GLOBALS_DATA_STRUCTURES.LCN := LCN; -- FOR TEST
  9222.  if USER_ACCESS_CHECK(LCN) then
  9223.   -- TELL USER ERROR: CONNECTION ILLEGAL FOR THIS PROCESS
  9224.   SOCKET_PARAMS := LCN;
  9225.   UMESSAGE := ( 2, 
  9226.                 SOCKET_PARAMS);
  9227.   MESSAGE_FOR_USER(UMESSAGE);
  9228.  elsif LCN.STATE = T_TCP_GLOBALS_DATA_STRUCTURES.CLOSED THEN
  9229.   -- TELL USER ERROR CONNECTION DOES NOT EXIST
  9230.   SOCKET_PARAMS := LCN;
  9231.   UMESSAGE := ( 3, 
  9232.                 SOCKET_PARAMS);
  9233.   MESSAGE_FOR_USER(UMESSAGE);
  9234.  else
  9235.   STATUS_REC.SOURCE_PORT := LCN.LOCAL_PORT;
  9236.   STATUS_REC.SOURCE_ADDRESS := LCN.SOURCE_ADDRESS;
  9237.   STATUS_REC.DESTINATION_PORT := LCN.FOREIGN_PORT;
  9238.   STATUS_REC.DESTINATION_ADDRESS := LCN.DESTINATION_ADDRESS;
  9239.   -- THE POSITIONS OF THE ENUMERATED DATA IN EACH RECORD IS THE SAME.
  9240.   -- THEREFORE THE VALUE OF THE CORRESPONDING TYPE GIVES YOU THE CORRECT
  9241.   -- ENUMERATION VALUE.
  9242.   STATUS_REC.CONNECTION_STATE := 
  9243.     STATE_TYPE'VAL(STATES'POS(LCN.STATE));
  9244.   STATUS_REC.STATUS:= WITH_ULP_COMMUNICATE.STATUS_TYPE'VAL(
  9245.     T_TCP_GLOBALS_DATA_STRUCTURES.STATUS_TYPE'POS(LCN.CONNECTION_STATUS));
  9246.   STATUS_REC.LOCAL_RCV_WINDOW := LCN.RCV_WINDOW;
  9247.   STATUS_REC.REMOTE_RCV_WINDOW := LCN.SND_WND;
  9248.   STATUS_REC.OCTETS_ON_RETRANSMIT_QUEUE :=
  9249.   LCN.QHEADS(TCP_RETRANSMIT_QUEUE).ELEMENT_COUNT; 
  9250.   -- THIS IS SIMPLE
  9251.   -- UNTIL WE HAVE VARIABLE SIZE PACKETS ON THE QUEUE.
  9252.   STATUS_REC.URGENT_STATE := LCN.USER_NOTIFICATION; 
  9253.   -- IF NOTIFIED OF URG.  DATA
  9254.   STATUS_REC.PRECEDENCE := LCN.PRECEDENCE;
  9255.   for I in 1..9 loop -- COPY SECURITY PARAMS
  9256.    STATUS_REC.SECURITY(I) :=  LCN.SECURITY(I);
  9257.   end loop;
  9258.   STATUS_REC.ULP_TIMEOUT := LCN.CONNECTION_TIMEOUT;
  9259.   -- NOW MESSAGE MUST GET BACK TO THE USER INTERFACE.
  9260.   SOCKET_PARAMS := LCN;
  9261.   UMESSAGE := ( 15, 
  9262.                 SOCKET_PARAMS, 
  9263.                 STATUS_REC);
  9264.   MESSAGE_FOR_USER(UMESSAGE);
  9265.  end if;
  9266. exception
  9267.  when others =>
  9268.   PUT_LINE(" ERROR IN TCP STATUS");
  9269. end TCP_STATUS;
  9270. procedure RETRANS_TCP( LCN : in TCB_PTR) is
  9271.     --This subprogram will get a segment off the retransmission queue and 
  9272.     --send it to the IP for transmission to the remote host. It will 
  9273.     --update the window in the segment.  This subprogram is called when 
  9274.     --a retransmission timeout has occured. It will retransmit a segment 
  9275.     --to the remote host.  A LCN is passed into the subprogram which pop 
  9276.     --a segment off the retransmit to the IP for the remote host.
  9277.     -- ALLOWS US TO ADD TO THE IP ID MOD 2**16.
  9278.     Q_ITEM : STD_Q_ITEM;
  9279.     PACKED_BUFF : PACKED_BUFFER_PTR;
  9280.     BYTE_COUNT : SIXTEEN_BITS ; -- LENGTH OF BUFFER FROM RETRANSMIT QUEUE
  9281.         MESSAGE_FOR_IP : IP_GLOBALS.IP_MESSAGE ;
  9282.     begin
  9283.      --  GET A SEGMENT OFF THE RETRANS QUEUE.
  9284.      QUEUE_GET(TCP_RETRANSMIT_QUEUE, LCN, Q_ITEM);
  9285.      if Q_ITEM.BUFFER /= null then
  9286.           if not Q_ITEM.BUFFER.IN_USE then --its not still waiting 
  9287.                                            --for transmission
  9288.          PACKED_BUFF := Q_ITEM.BUFFER;
  9289.        BYTE_COUNT := Q_ITEM.LENGTH;
  9290.        --Reset the IP pointer in the buffer
  9291.            PACKED_BUFF.IP_PTR := PACKED_BUFF.TCP_PTR - 1;
  9292.         --IT WILL NOT BE OUR RESPONSIBILITY TO DETERMINE THE MAX TIME FOR A 
  9293.        --TRANS.  THAT WILL BELONG TO THE USER LAYER. THE DATAGRAM LAYER MAY 
  9294.        --ALSO HAVE A TIME TO LIVE.  WE CAN ALWAYS SEND FROM THE RETRANSMIT 
  9295.            --QUEUE WE WILL USE THE PREVIOUSLY PACKED BUFFER FROM THE RETRANS Q 
  9296.            --AS IS.
  9297.        -- SET UP ID FOR IP
  9298.        IDENT := LCN.RETRANS_IDENT;
  9299.        --   LCN.IDENT := LCN.IDENT + 1;
  9300.            SEND_IP( LCN.SOURCE_ADDRESS,
  9301.                     LCN.DESTINATION_ADDRESS,
  9302.                     TOS,
  9303.                     TTL,
  9304.                     PACKED_BUFF,
  9305.                     BYTE_COUNT,
  9306.                     IDENT,
  9307.                     DONT_FRAGMENT,
  9308.                     OPTIONS,
  9309.                     RESULT);
  9310.           end if;
  9311.           QUEUE_ADD(TCP_RETRANSMIT_QUEUE, LCN, Q_ITEM);
  9312.          else
  9313.           TCP_ERROR(4);
  9314.          end if;
  9315.     end RETRANS_TCP;
  9316.  
  9317. end T_TCP_UTILITIES_1 ;
  9318. --::::::::::::::
  9319. --timer.txt
  9320. --::::::::::::::
  9321. -----------------------------------------------------------------------
  9322. --
  9323. --         DoD Protocols    NA-00008-200       80-01201-100(-)
  9324. --         E-Systems, Inc.  August 07, 1985
  9325. --
  9326. --         timer.txt       Author : Jim Baldo
  9327. --
  9328. -----------------------------------------------------------------------
  9329. with BUFFER_DATA;                       use BUFFER_DATA;
  9330. package REAL_TIME_CLOCK_AND_DATE is
  9331. subtype IN_MILLISECONDS is THIRTYTWO_BITS ;
  9332. procedure START_LOCAL_CLOCK;
  9333. procedure STOP_LOCAL_CLOCK;
  9334. function SYSTEM_TIME return IN_MILLISECONDS ;
  9335. end REAL_TIME_CLOCK_AND_DATE;
  9336. with T_REAL_TIME_CLOCK;
  9337. package body REAL_TIME_CLOCK_AND_DATE is
  9338. TOD : IN_MILLISECONDS ;
  9339. procedure START_LOCAL_CLOCK is
  9340. begin
  9341.  T_REAL_TIME_CLOCK.START; --Start interval timer
  9342. end START_LOCAL_CLOCK;
  9343. procedure STOP_LOCAL_CLOCK is
  9344. begin
  9345.  T_REAL_TIME_CLOCK.STOP; --Stop interval timer
  9346. end STOP_LOCAL_CLOCK;
  9347. function SYSTEM_TIME return IN_MILLISECONDS is
  9348. begin
  9349.  T_REAL_TIME_CLOCK.READ(TOD); -- read the clock
  9350.  return (TOD/1000) ;
  9351. end SYSTEM_TIME;
  9352. end REAL_TIME_CLOCK_AND_DATE;
  9353. --::::::::::::::
  9354. --unpack.txt
  9355. --::::::::::::::
  9356. -----------------------------------------------------------------------
  9357. --
  9358. --         DoD Protocols    NA-00008-200       80-01202-100(-)
  9359. --         E-Systems, Inc.  August 07, 1985
  9360. --
  9361. --         unpack.txt       Author : Jim Baldo
  9362. --
  9363. -----------------------------------------------------------------------
  9364. with IP_GLOBALS;    use IP_GLOBALS;
  9365. with BUFFER_DATA;    use BUFFER_DATA;
  9366.         package IP_UNPACK_AND_PACK_UTILITIES is
  9367.     --------------------------------------------------------------
  9368.     --This implementation is for use with the DEC/Ada compiler. --
  9369.     --------------------------------------------------------------
  9370.   function UNPACK
  9371.     (PACKED_BUFFER : PACKED_BUFFER_PTR) return BUFFER_POINTER;
  9372.     --This function will unpack a packet of SYSTEM_BYTE to facilatate
  9373.     --access to data.
  9374.   procedure PACK_BUFFER_INTO_BIT_STREAM
  9375.       (BUFPTR : BUFFER_POINTER; PACKED_BUFFER : 
  9376.               in out PACKED_BUFFER_PTR);
  9377.     --This procedure transform an IP header and date into SYSTEM_BYTE
  9378.   function CHECKSUM( START_PTR : in SIXTEEN_BITS ; 
  9379.                      END_PTR : in SIXTEEN_BITS ; 
  9380.                      PACKED_BUFFER : in PACKED_BUFFER_PTR) return SIXTEEN_BITS ;
  9381.     --This function performs a checksum calculation on the 
  9382.     --arrived datagram and compares its value with that contained 
  9383.     --in the IP header.
  9384. end IP_UNPACK_AND_PACK_UTILITIES;
  9385. --with WITH_TCP_COMMUNICATE;      use WITH_TCP_COMMUNICATE;
  9386. with TEXT_IO;                   use TEXT_IO, INTEGER_IO;
  9387. with SYSTEM ;            use SYSTEM;
  9388. with UNCHECKED_CONVERSION;
  9389.         
  9390.                 package body IP_UNPACK_AND_PACK_UTILITIES is
  9391.   
  9392.   function UNPACK
  9393.     (PACKED_BUFFER : PACKED_BUFFER_PTR) return BUFFER_POINTER is
  9394.     --This function will unpack a buffer full of bytes and put them in the
  9395.     --proper fields of a record for ease of processing by other routines.
  9396.     --
  9397.     -- RESTRICTIONS :
  9398.     --
  9399.     --   ** This routine is likely to be implementation dependent. **
  9400. --TEL  pragma suppress(OVERFLOW_CHECK);
  9401.   type INDEX is (HIGH_WORD_HI_BYTE, HIGH_WORD_LO_BYTE, 
  9402.          LOW_WORD_HI_BYTE, LOW_WORD_LO_BYTE); -- THIS IS THE WAY 
  9403.                   -- UNCHECKED CONV PUTS
  9404.                   -- THE BYTES IN. IT IS
  9405.                   -- OPPOSITE FOR THE VAX.
  9406.   type LONG_CONV is array(1..1) of THIRTYTWO_BITS ; 
  9407.           -- CURRENTLY NECESSARY FOR 
  9408.                  -- IMPLEMENTATION RESTRICTION
  9409.   type BYTE_TYPE is array(INDEX) of SYSTEM.BYTE;
  9410.   function CONVERT is new UNCHECKED_CONVERSION(BYTE_TYPE, LONG_CONV);
  9411.   BYTES_TO_CONVERT : BYTE_TYPE;
  9412.   CONVERTED_WORDS : LONG_CONV;
  9413.   BUFPTR : BUFFER_POINTER;
  9414.   COUNT, I, X, Y : SIXTEEN_BITS ;
  9415.   SHIFT_WORD : CONSTANT THIRTYTWO_BITS  := 65536;
  9416.   begin
  9417.   -- IT IS ASSUMED THAT THE POINTER IN THE BUFFER POINTS TO 
  9418.   --THE PROPER HEADER.
  9419.     I := PACKED_BUFFER.IP_PTR;
  9420.     X := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I)/2**4) ;
  9421.     BUFPTR.VERSION := X;
  9422.     BUFPTR.IHL := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I)) - X * 2**4 ;
  9423.     BUFPTR.TOS := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+1)) ;
  9424.     BUFPTR.TOT_LEN := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+2) * 2**8 + 
  9425.       PACKED_BUFFER.BYTE(I+3)) ;
  9426.     BUFPTR.ID := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+4) * 2**8 + 
  9427.       PACKED_BUFFER.BYTE(I+5)) ;
  9428.     X := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+6)/2**5) ;
  9429.     BUFPTR.FLAGS := X;
  9430.     BUFPTR.FRAG_OFFSET := (SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+6)) - X * 2**5) * 
  9431.       2**8 + SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+7)) ;
  9432.     BUFPTR.TTL := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+8)) ;
  9433.     BUFPTR.PROT := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+9)) ;
  9434.     BUFPTR.IPCSUM := SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+10)) * 2**8 + 
  9435.       SIXTEEN_BITS (PACKED_BUFFER.BYTE(I+11)) ;
  9436.     -- PUT IN SOURCE
  9437.     BYTES_TO_CONVERT(LOW_WORD_LO_BYTE) := 
  9438.                         PACKED_BUFFER.BYTE(I+12) ;
  9439.     BYTES_TO_CONVERT(LOW_WORD_HI_BYTE) := 
  9440.                         PACKED_BUFFER.BYTE(I+13) ;
  9441.     BYTES_TO_CONVERT(HIGH_WORD_LO_BYTE) := 
  9442.                         PACKED_BUFFER.BYTE(I+14) ;
  9443.     BYTES_TO_CONVERT(HIGH_WORD_HI_BYTE) :=
  9444.                         PACKED_BUFFER.BYTE(I+15) ;
  9445.     CONVERTED_WORDS := CONVERT(BYTES_TO_CONVERT);
  9446.     BUFPTR.SOURCE := CONVERTED_WORDS(1);
  9447.     -- PUT IN DESTINATION
  9448.     BYTES_TO_CONVERT(LOW_WORD_LO_BYTE) := 
  9449.                         PACKED_BUFFER.BYTE(I+16) ;
  9450.     BYTES_TO_CONVERT(LOW_WORD_HI_BYTE) := 
  9451.                         PACKED_BUFFER.BYTE(I+17) ;
  9452.     BYTES_TO_CONVERT(HIGH_WORD_LO_BYTE) := 
  9453.                         PACKED_BUFFER.BYTE(I+18) ;
  9454.     BYTES_TO_CONVERT(HIGH_WORD_HI_BYTE) :=   
  9455.                         PACKED_BUFFER.BYTE(I+19) ;
  9456.     CONVERTED_WORDS := CONVERT(BYTES_TO_CONVERT);
  9457.     BUFPTR.DEST := CONVERTED_WORDS(1);
  9458.     -- NOW FOR THE OPTIONS IF ANY
  9459.     I := I + 20;
  9460.     if BUFPTR.IHL > 5 then -- OPTIONS EXIST
  9461.       COUNT := 1;
  9462.       for J in 1..BUFPTR.IHL - 5 LOOP
  9463.         for K in 0..3 loop
  9464.           BUFPTR.IP_OPTIONS( COUNT + SIXTEEN_BITS(K) ) := 
  9465.             SIXTEEN_BITS (PACKED_BUFFER.BYTE( I + SIXTEEN_BITS(K)) ) ;
  9466.         end loop;
  9467.         COUNT := COUNT + 4;
  9468.         I := I + 4;
  9469.       end loop;
  9470.     end IF;
  9471.     PACKED_BUFFER.TCP_PTR := I; 
  9472.       -- UPDATE THE POINTER TO POINT TO THE FIRST 
  9473.         -- BYTE OF THE TCP HEADER.
  9474.     return BUFPTR;
  9475.   exception
  9476.      when CONSTRAINT_ERROR =>
  9477.         TEXT_IO.PUT_LINE("IP UNPACK?, CONSTRAINT ERROR");
  9478.       INTEGER_IO.PUT(I);
  9479.     when others =>
  9480.       TEXT_IO.PUT_LINE("IP UNPACK?, ERROR");
  9481.       --  SYSTEM.REPORT_ERROR;
  9482.   end UNPACK;
  9483.   procedure PACK_BUFFER_INTO_BIT_STREAM
  9484.       (BUFPTR : BUFFER_POINTER; PACKED_BUFFER : 
  9485.               in out PACKED_BUFFER_PTR) is
  9486.     --This subprogram will take an unpacked IP header record with each 
  9487.     --field having its own spot, and pack the fields into a bit 
  9488.     --stream( in the form of bytes).  It assumes that the pointer given 
  9489.     --it (for the packed array) is correctly set. The IP header picture 
  9490.     --in the specification shows how the packed stream should look.  
  9491.     --It also calls the header checksum routine and packs the checksum 
  9492.     --in the stream.
  9493. --TEL   pragma SUPPRESS(OVERFLOW_CHECK);
  9494.   type INDEX is (HIGH_WORD_HI_BYTE, HIGH_WORD_LO_BYTE, 
  9495.          LOW_WORD_HI_BYTE, LOW_WORD_LO_BYTE); -- THIS IS THE WAY 
  9496.                 -- UNCHECKED CONV PUTS
  9497.                 -- THE BYTES IN.
  9498.                 -- IT IS OPPOSITE FOR
  9499.                 -- THE VAX.
  9500.   type LONG_CONV is array(1..1) of THIRTYTWO_BITS ; 
  9501.             -- CURRENTLY NECESSARY FOR 
  9502.                   -- IMPLEMENTATION RESTRICTION
  9503.   type BYTE_TYPE is array(INDEX) of SYSTEM.BYTE; --DEC/Ada
  9504.   type TWO_BYTE is array(1..2) of SYSTEM.BYTE; --DEC/Ada
  9505.   type TELEGOOFUP is array(1..1) of SIXTEEN_BITS ;
  9506.   function CONVERT_TO_TWO_BYTES is new 
  9507.       UNCHECKED_CONVERSION(TELEGOOFUP, TWO_BYTE);
  9508.   function CONVERT is new UNCHECKED_CONVERSION(LONG_CONV, BYTE_TYPE);
  9509.   SHIFT_WORD : constant THIRTYTWO_BITS  := 65536;
  9510.   J : SIXTEEN_BITS  := 1;
  9511.   IP_LENGTH : constant SIXTEEN_BITS  := BUFPTR.IHL * 4;
  9512.   HIGH_BYTE : BOOLEAN := TRUE;
  9513.   COUNT : SIXTEEN_BITS  := 0;
  9514.   I, CSUM, X : SIXTEEN_BITS ;
  9515.   BYTES: BYTE_TYPE;
  9516.   WORDS_TO_CONVERT : LONG_CONV;
  9517.   TEMP : TWO_BYTE;
  9518.   WORD_TO_CONVERT : TELEGOOFUP;
  9519.   begin
  9520.     --SET POINTER
  9521.     PACKED_BUFFER.IP_PTR := PACKED_BUFFER.IP_PTR - 
  9522.             IP_LENGTH + 1;-- POINTER IS
  9523.          -- INITIALLY AT THE FIRST OPEN BYTE IN THE BUFFER(ARRAY).
  9524.     I := PACKED_BUFFER.IP_PTR;
  9525.     PACKED_BUFFER.BYTE(I) := SYSTEM_BYTE (BUFPTR.VERSION * 2**4 + BUFPTR.IHL);
  9526.     PACKED_BUFFER.BYTE(I+1) := SYSTEM_BYTE (BUFPTR.TOS) ;
  9527.     WORD_TO_CONVERT(1) := BUFPTR.TOT_LEN;
  9528.     TEMP := CONVERT_TO_TWO_BYTES(WORD_TO_CONVERT);
  9529.     PACKED_BUFFER.BYTE(I+2) := TEMP(1);
  9530.         -- FOR VAX. TEMP(2);-- HIGH BYTE
  9531.     PACKED_BUFFER.BYTE(I+3) := TEMP(2); -- FOR VAX. TEMP(1);
  9532.     WORD_TO_CONVERT(1) := BUFPTR.ID;
  9533.     TEMP := CONVERT_TO_TWO_BYTES(WORD_TO_CONVERT);
  9534.     PACKED_BUFFER.BYTE(I+4) := TEMP(1);
  9535.         -- HIGH BYTE. OPPOSITE FOR THE mc68000
  9536.     PACKED_BUFFER.BYTE(I+5) := TEMP(2);
  9537.     WORD_TO_CONVERT(1) := BUFPTR.FRAG_OFFSET;
  9538.     TEMP := CONVERT_TO_TWO_BYTES(WORD_TO_CONVERT);
  9539.     PACKED_BUFFER.BYTE(I+6) := TEMP(1) + SYSTEM_BYTE ( BUFPTR.FLAGS * 2**5) ;
  9540.                 -- HIGH BYTE
  9541.     PACKED_BUFFER.BYTE(I+7) := TEMP(2); -- OPPOSITE OF THE VAX.
  9542.     PACKED_BUFFER.BYTE(I+8) := SYSTEM_BYTE ( BUFPTR.TTL ) ;
  9543.     PACKED_BUFFER.BYTE(I+9) := SYSTEM_BYTE ( BUFPTR.PROT ) ;
  9544.     -- CHECKSUM GOES HERE
  9545.     PACKED_BUFFER.BYTE(I+10) := 0;
  9546.     PACKED_BUFFER.BYTE(I+11) := 0;
  9547.     WORDS_TO_CONVERT(1) := BUFPTR.SOURCE;
  9548.     BYTES := CONVERT(WORDS_TO_CONVERT);
  9549.     PACKED_BUFFER.BYTE(I+12) := BYTES(LOW_WORD_LO_BYTE);
  9550.     PACKED_BUFFER.BYTE(I+13) := BYTES(LOW_WORD_HI_BYTE);
  9551.     PACKED_BUFFER.BYTE(I+14) := BYTES(HIGH_WORD_LO_BYTE);
  9552.     PACKED_BUFFER.BYTE(I+15) := BYTES(HIGH_WORD_HI_BYTE);
  9553.     WORDS_TO_CONVERT(1) := BUFPTR.DEST;
  9554.     BYTES := CONVERT(WORDS_TO_CONVERT);
  9555.     PACKED_BUFFER.BYTE(I+16) := BYTES(LOW_WORD_LO_BYTE);
  9556.     PACKED_BUFFER.BYTE(I+17) := BYTES(LOW_WORD_HI_BYTE);
  9557.     PACKED_BUFFER.BYTE(I+18) := BYTES(HIGH_WORD_LO_BYTE);
  9558.     PACKED_BUFFER.BYTE(I+19) := BYTES(HIGH_WORD_HI_BYTE);
  9559.     -- NOW THE OPTIONS
  9560.     I := I + 20;
  9561.     COUNT := (BUFPTR.IHL - 5) * 4;
  9562.     for J in 1..COUNT loop
  9563.       PACKED_BUFFER.BYTE(I + SIXTEEN_BITS ( J ) - 1) :=
  9564.                                    SYSTEM_BYTE (BUFPTR.IP_OPTIONS(J) ) ;
  9565.     end loop;
  9566.     -- MOVE THE POINTER TO POINT TO THE NEXT OPEN SPACE FOR TCP
  9567. --    PACKED_BUFFER.CPM_PTR := PACKED_BUFFER.IP_PTR - 1;
  9568. -- PUT IN THE CHECKSUM
  9569.     WORD_TO_CONVERT(1) := CHECKSUM(PACKED_BUFFER.IP_PTR,
  9570.                                    BUFPTR.IHL * 4,
  9571.                                    PACKED_BUFFER);
  9572.     TEMP := CONVERT_TO_TWO_BYTES(WORD_TO_CONVERT);
  9573.     I := PACKED_BUFFER.IP_PTR;
  9574.     PACKED_BUFFER.BYTE(I + 10) := TEMP(2); -- FOR THE 68000 TEMP(2);
  9575.     PACKED_BUFFER.BYTE(I + 11) := TEMP(1); -- FOR THE 68000 TEMP(1);
  9576.   exception
  9577.      when CONSTRAINT_ERROR =>
  9578.       TEXT_IO.PUT_LINE("CONSTRAINT ERROR IN IP PACK");
  9579.                         INTEGER_IO.PUT(PACKED_BUFFER.IP_PTR);
  9580.     when others =>
  9581.       TEXT_IO.PUT_LINE("PACK EM ERROR");
  9582.       INTEGER_IO.PUT(PACKED_BUFFER.IP_PTR);
  9583.       INTEGER_IO.PUT(CSUM);
  9584.     --     SYSTEM.REPORT_ERROR;
  9585.   end PACK_BUFFER_INTO_BIT_STREAM;
  9586. function PHYSICAL_ADDRESS is new UNCHECKED_CONVERSION(THIRTYTWO_BITS ,
  9587.                                                       SYSTEM.ADDRESS);
  9588. function CHECKSUM( START_PTR : in SIXTEEN_BITS ;
  9589.                    END_PTR : in SIXTEEN_BITS ;
  9590.                    PACKED_BUFFER : in PACKED_BUFFER_PTR)
  9591.                                           return SIXTEEN_BITS  is
  9592.         --This subprogram performs a checksum on the internet header only. It
  9593.         --will be the 16 bit one's complement of all 16 bit words in the
  9594.         --header.  The value of the checksum field for computation will be 0.
  9595.         --
  9596.         -- RESTRICTIONS :
  9597.         --
  9598.         --This routine is implementation dependant.  It is currently set for
  9599.         --a VAX 11/780.
  9600. type TWO_WORDS is array(1..2) of SIXTEEN_BITS ;
  9601. type TELEFOOL is array(1..1) of THIRTYTWO_BITS ;
  9602. function CONVERSION is new UNCHECKED_CONVERSION(TELEFOOL, TWO_WORDS);
  9603. HIGH_BYTE : BOOLEAN := TRUE;
  9604. PCSUM : THIRTYTWO_BITS  := 0;
  9605. CSUM : TWO_WORDS :=(0,0);
  9606. CHECKSM : TELEFOOL;
  9607. begin
  9608.  -- ADD UP ALL THE 16 BIT FIELDS. THIS WILL BE SOMEWHAT TRICKY, SO
  9609.  --HANG ON.  MUST SWAP HIGH AND LOW BITS IN EACH WORD. HOWEVER WE WILL
  9610.  --TRY IT THE INTUITIVE WAY FOR NOW.
  9611.                 for I in 0..END_PTR - 1 loop
  9612.                 if (I /= 10) and I /= 11 then -- DON'T ADD IN THE CHECKSUM
  9613.                         if HIGH_BYTE then
  9614.                                 PCSUM := PCSUM +
  9615.                                 THIRTYTWO_BITS (PACKED_BUFFER.BYTE(START_PTR + I))
  9616.                                 * THIRTYTWO_BITS (2**8);
  9617.                                 HIGH_BYTE := FALSE;
  9618.                         else
  9619.                                 HIGH_BYTE := TRUE;
  9620.                                 PCSUM := PCSUM +
  9621.                                 THIRTYTWO_BITS (PACKED_BUFFER.BYTE(START_PTR + I));
  9622.                         end if;
  9623.                 end if;
  9624.                 end loop;
  9625.                 -- GET ONES COMPLEMENT
  9626.                 PCSUM := -PCSUM;
  9627.                 PCSUM := PCSUM - 1;
  9628.                 CHECKSM(1) := PCSUM;
  9629.                 CSUM := CONVERSION(CHECKSM);
  9630.                         -- GET BOTH WORDS AND RETURN LOW WORD.
  9631.                 RETURN CSUM(2); -- IT IS ONE FOR THE VAX
  9632. exception
  9633.     when CONSTRAINT_ERROR =>
  9634.         TEXT_IO.PUT_LINE("CHECKSUM CONSTRAINT ERROR");
  9635.         INTEGER_IO.PUT(START_PTR);
  9636.         --  SYSTEM.REPORT_ERROR;
  9637.     when others =>
  9638.         TEXT_IO.PUT_LINE("CHECKSUM ERROR");
  9639.         --  SYSTEM.REPORT_ERROR;
  9640. end CHECKSUM;
  9641. end IP_UNPACK_AND_PACK_UTILITIES;
  9642.