-- File: ArpaAddressTranslationImpl.mesa - last edit:
-- AOF                  3-Mar-88 12:44:17
-- JAV                 17-Aug-87 11:31:45

-- Copyright (C) 1985, 1986, 1987, 1988 by Xerox Corporation. All rights reserved.

DIRECTORY
  ArpaAddressCache USING [Lookup],
  ArpaAddressTranslation USING [
    ErrorRecord, INetAddr, INetAddressOrName, nullINetAddress, ProtocolType],
  ArpaAddressTranslationPriv USING [],
  ArpaRouter USING [InternetAddress],
  ArpaToken USING [
    Decimal, FreeStringHandle, Handle, NilData, StringToHandle, SyntaxError],
  Environment USING [Long],
  Inline USING [HighByte, LowByte],
  String USING [
    AppendChar, AppendDecimal, AppendNumber, AppendString, ExpandString,
    StringBoundsFault, StringToNumber];

ArpaAddressTranslationImpl: PROGRAM
  IMPORTS ArpaAddressCache, ArpaAddressTranslation, ArpaToken, Inline, String
  EXPORTS ArpaAddressTranslation, ArpaAddressTranslationPriv =
  BEGIN
    
  Error: PUBLIC ERROR [errorRecord: ArpaAddressTranslation.ErrorRecord] = CODE;
  
  dot: CHARACTER = '.;
  comma: CHARACTER = ',;
  
  InternetAddressX: TYPE = MACHINE DEPENDENT RECORD [
    InternetAddress(0): SELECT OVERLAID * FROM
      Raw => [IAddress(0): ArpaRouter.InternetAddress],
      
      Working => [
        octet1(0:0..7): [0..256),
	octet2(0:8..15): [0..256),
	octet3(1:0..7): [0..256),
	octet4(1:8..15): [0..256)],
      
      ClassA => [
	addrTypeA(0:0..0): [0..2),
	netNumA(0:1..7): [0..128),
	hostNumA1(0:8..15): [0..256),
	hostNumA2(1:0..15): [0..65534)],  
		<<[class 1 bit][net number 7 bits][host number 24 bits]>>
      ClassB => [
	addrTypeB(0:0..1): [0..4),
	netNumB(0:2..15): [0..16384),
	hostNumB(1:0..15): [0..65534)],	
		<<[class 2 bits][net number 14 bits][host number 16 bits]>>
      ClassC => [
        addrTypeC(0:0..2): [0..8),
	netNumC1(0: 3..15): [0..8192),
	netNumC2(1:0..7): [0..256),
	hostNumC(1: 8..15): [0..256)],	
			<<[class 3 bits][net number 21 bits][host number 8 bits]>>
      ExtendedAddr => [
        addrTypeExtended(0:0..2): [0..8),
	undefined1(0:3..15): [0..8192),
	undefined2(1:0..15): [0..65534)]	
			<<[class 3 bits][undefined 29 bits]>>
      ENDCASE];
      
      <<
      Addresses of class -
        A have a zero in the first bit postition.
        B have a one-zero in the first two bit postitions.
        C have a one-one-zero in the first three bit positions.
        Extended have a one-one-one in the first three bit positions.
      >>

  StringToInternetAddress: PUBLIC PROC[ s: LONG STRING]
    RETURNS[addr: ArpaRouter.InternetAddress] =
    BEGIN
    found: BOOLEAN;
    IF s = NIL THEN ERROR Error[[scanError[0]]];
    [addr, found] ← ArpaAddressCache.Lookup[s];
    IF found THEN RETURN;  --found it in cache
    addr ← LOOPHOLE[ArpaAddressTranslation.INetAddressOrName[s]];
    IF addr # LOOPHOLE[ArpaAddressTranslation.nullINetAddress] THEN
      ERROR Error[[nameLookupProblem[noSuchName]]];
    END;  --StringToInternetAddress
    
  StringToInternetAddressPriv: PUBLIC PROC[s: LONG STRING]
    RETURNS[addr: ArpaRouter.InternetAddress] =
    {RETURN[LOOPHOLE[INetAddress[s]]]};  --StringToInternetAddressPriv

  INetAddress: PUBLIC PROC [s: LONG STRING]
    RETURNS[address: ArpaAddressTranslation.INetAddr] =
    BEGIN
    temp: CARDINAL;
    h: ArpaToken.Handle ← ArpaToken.StringToHandle[s];
    BEGIN
    ENABLE {ArpaToken.NilData, ArpaToken.SyntaxError => GOTO error};
    -- compiled without BoundsFault!

    IF s = NIL OR s.length = 0 THEN GOTO error;
    
    IF (temp ← ArpaToken.Decimal[h]) > 377B THEN GOTO error
    ELSE address.a ← temp;
    IF (temp ← ArpaToken.Decimal[h]) > 377B THEN GOTO error
    ELSE address.b ← temp;
    IF (temp ← ArpaToken.Decimal[h]) > 377B THEN GOTO error
    ELSE address.c ← temp;
    IF (temp ← ArpaToken.Decimal[h]) > 377B THEN GOTO error
    ELSE address.d ← temp;

    EXITS error => address ← ArpaAddressTranslation.nullINetAddress;
    END;
    h ← ArpaToken.FreeStringHandle[h];
    END; -- INetAddress
  
  AppendINetAddress: PUBLIC PROC[
    to: LONG STRING, address: ArpaAddressTranslation.INetAddr] =
    BEGIN
    String.AppendDecimal[to, address.a];
    String.AppendChar[to, '.];
    String.AppendDecimal[to, address.b];
    String.AppendChar[to, '.];
    String.AppendDecimal[to, address.c];
    String.AppendChar[to, '.];
    String.AppendDecimal[to, address.d];
    END; -- AppendINetAddress 
 

  AppendINetAddressAndGrow: PUBLIC PROC[
    to: LONG POINTER TO LONG STRING,
    address: ArpaAddressTranslation.INetAddr,
    z: UNCOUNTED ZONE] =
    BEGIN
    ENABLE String.StringBoundsFault =>
      {String.ExpandString[to, 20, z]; RESUME[to↑]};
    String.AppendDecimal[to↑, address.a];
    String.AppendChar[to↑, '.];
    String.AppendDecimal[to↑, address.b];
    String.AppendChar[to↑, '.];
    String.AppendDecimal[to↑, address.c];
    String.AppendChar[to↑, '.];
    String.AppendDecimal[to↑, address.d];
    END; -- AppendINetAddressAndGrow
 
  AppendProtocol: PUBLIC PROC[
    s: LONG STRING, protocol: ArpaAddressTranslation.ProtocolType,
    radix: CARDINAL ← 10] =
    BEGIN
    temp: LONG STRING ← [20];
    String.AppendNumber[temp, CARDINAL[LOOPHOLE[protocol]], radix];
    IF radix # 10 THEN
       String.AppendChar[temp, 
         SELECT radix FROM
	  8 => 'B,
	  16 => 'H,
	  ENDCASE => ' ];
    String.AppendString[s, 
      SELECT protocol FROM
       icmp => "icmp"L,
       ggp =>  "ggp"L,
       st =>   "st"L,
       tcp =>  "tcp"L,
       egp =>  "egp"L,
       udp =>  "udp"L,
       mitRvd => "mitRvd"L,
       sunRvd => "sunRvd"L,
       ENDCASE => temp];
    END; -- AppendProtocol

  
  InternetAddressToString: PUBLIC PROC[
    addr: ArpaRouter.InternetAddress, s: LONG STRING, radix: CARDINAL] = {
    address: InternetAddressX ← LOOPHOLE[addr];
    radixChar: CHARACTER ← '0;
    SELECT radix FROM
      8 => radixChar ← 'B; 10 => radixChar ← 'D;
      ENDCASE => {radix ← 10; radixChar ← 'D};
    String.AppendNumber[s, address.octet1, radix];
    IF radixChar # '0 THEN String.AppendChar[s, radixChar];
    String.AppendChar[s, dot];
    String.AppendNumber[s, address.octet2, radix];
    IF radixChar # '0 THEN String.AppendChar[s, radixChar];
    String.AppendChar[s, dot];
    String.AppendNumber[s, address.octet3, radix];
    IF radixChar # '0 THEN String.AppendChar[s, radixChar];
    String.AppendChar[s, dot];
    String.AppendNumber[s, address.octet4, radix];
    IF radixChar # '0 THEN String.AppendChar[s, radixChar];
    };  --InternetAddressToString
  
  InternetAddrToTelnetPort: PUBLIC PROC[
    addr: ArpaRouter.InternetAddress, s: LONG STRING, portNumber: CARDINAL] = {
    tempNumber: Environment.Long;
    tempNumber.lu ← LOOPHOLE[addr];
    String.AppendDecimal[s, Inline.HighByte[tempNumber.low]];
    String.AppendChar[s, comma];
    String.AppendDecimal[s, Inline.LowByte[tempNumber.low]];
    String.AppendChar[s, comma];
    String.AppendDecimal[s, Inline.HighByte[tempNumber.high]];
    String.AppendChar[s, comma];
    String.AppendDecimal[s, Inline.LowByte[tempNumber.high]];
    String.AppendChar[s, comma];
    String.AppendDecimal[s, Inline.HighByte[portNumber]];
    String.AppendChar[s, comma];
    String.AppendDecimal[s, Inline.LowByte[portNumber]];
    };  --InternetAddrToTelnetPort
  
  TelnetPortAddressToInternetAddr: PUBLIC PROC[s: LONG STRING] 
    RETURNS[addr: ArpaRouter.InternetAddress, portNumber: CARDINAL ← 0] = 
    BEGIN
    string: LONG STRING ← [20];
    arrayIndex: CARDINAL ← 0;
    tempAddr: InternetAddressX;
    tempPort: MACHINE DEPENDENT RECORD[
      HighHalf(0:0..7): [0..256),
      LowHalf(0:8..15): [0..256)];
    tempNumber: UNSPECIFIED ← 0;
      
      FOR i: CARDINAL IN [0..s.length) DO
	SELECT s[i] FROM
	  comma => {
	    tempNumber ← String.StringToNumber[string];
	    IF tempNumber >= 256 THEN ERROR Error[[scanError[i]]];
	    SELECT arrayIndex FROM
	      0 => tempAddr.octet1 ← tempNumber;
	      1 => tempAddr.octet2 ← tempNumber;
	      2 => tempAddr.octet3 ← tempNumber;
	      3 => tempAddr.octet4 ← tempNumber;
	      4 => tempPort.HighHalf ← tempNumber;
	      5 => tempPort.LowHalf ← tempNumber;
	    ENDCASE => ERROR Error[[scanError[i]]];
	    arrayIndex ← arrayIndex.SUCC;
	    string.length ← 0};
	  IN ['0..'9] => String.AppendChar[string, s[i]]
	ENDCASE => LOOP;
      ENDLOOP;
      IF arrayIndex # 5 THEN ERROR Error[[scanError[s.length]]];
      tempNumber ← String.StringToNumber[string];
      IF tempNumber >= 256 THEN ERROR Error[[scanError[s.length]]];
      tempPort.LowHalf ← tempNumber;
      RETURN[LOOPHOLE[tempAddr], LOOPHOLE[tempPort]];
    END;
  
END.

LOG

 0-000-00 00:00:00  ALD/ISI - added Domain NameServer stuff
 3-Mar-88 12:38:19  AOF - Just cleaning up