-- File: ArpaHostTableImpl.mesa - last edit: -- AOF 12-Mar-87 17:49:14 -- JAV 25-Feb-87 14:58:51 -- Copyright (C) 1986, 1987 by Xerox Corporation. All rights reserved. DIRECTORY ArpaAddressCache USING [AddEntry], ArpaAddressTranslation USING [StringToInternetAddress], ArpaHostTable USING [], ArpaRouter USING [GetAddress, InternetAddress, unknownInternetAddress], ArpaTypes USING [InternetAddress], Environment USING [Byte], ESCAlpha USING [aDAND, aDXOR], Heap USING [systemZone], Inline USING [DBITAND], Mopcodes USING [zESC, zIOR], Stream USING [Byte, EndOfStream, GetByte, Handle], String USING [ AppendChar, AppendSubString, CopyToNewString, Equivalent, FreeString, MakeString, StringBoundsFault, SubStringDescriptor]; ArpaHostTableImpl: PROGRAM IMPORTS ArpaAddressCache, ArpaAddressTranslation, ArpaRouter, Heap, Inline, Stream, String EXPORTS ArpaHostTable, ArpaRouter = BEGIN zone: UNCOUNTED ZONE ¬ Heap.systemZone; Tab: Environment.Byte ¬ 11B; CR: Environment.Byte ¬ 15B; SP: Environment.Byte ¬ 40B; comma: Environment.Byte ¬ 54B; colon: Environment.Byte ¬ 72B; semiColon: Environment.Byte ¬ 73B; InternetAddress: PUBLIC TYPE = ArpaTypes.InternetAddress; SkipLine: PROCEDURE [stream: Stream.Handle] = BEGIN char: Environment.Byte ¬ 0; WHILE char # CR DO char ¬ Stream.GetByte[stream ! Stream.EndOfStream => EXIT] ENDLOOP END; ParseHostsFile: PUBLIC PROCEDURE [fileStream: Stream.Handle] RETURNS [success: BOOLEAN ¬ TRUE] = BEGIN tokens: ARRAY [0..6) OF LONG STRING; EOF, charInHole: BOOLEAN ¬ FALSE; keyword: LONG STRING ¬ String.MakeString[zone, 256]; backChar: Environment.Byte ¬ 0; netMask: ArpaRouter.InternetAddress ¬ ArpaRouter.unknownInternetAddress; GetKeyword: PROCEDURE [string: LONG STRING] = BEGIN char: Environment.Byte ¬ 0; WHILE ~EOF DO IF charInHole THEN {char ¬ backChar; charInHole ¬ FALSE} ELSE char ¬ Stream.GetByte[fileStream ! Stream.EndOfStream => { EOF ¬ TRUE; CONTINUE}]; IF char = semiColon THEN {SkipLine[fileStream]; LOOP}; IF char = colon THEN EXIT; IF char = SP OR char = Tab THEN { WHILE char # colon DO IF EOF THEN EXIT; char ¬ Stream.GetByte[fileStream ! Stream.EndOfStream => {EOF ¬ TRUE; CONTINUE}]; ENDLOOP; EXIT}; IF ~EOF THEN String.AppendChar[string, LOOPHOLE[char] ! String.StringBoundsFault => { string ¬ String.CopyToNewString[s, zone, 30]; String.FreeString[zone, s]; RESUME[string]}]; ENDLOOP; END; GetTokens: PROCEDURE [numberOfTokens: CARDINAL] RETURNS [EOF: BOOLEAN ¬ FALSE] = BEGIN i: CARDINAL ¬ 0; char: Environment.Byte ¬ 0; EOL, CRSeen: BOOLEAN ¬ FALSE; WHILE ~EOL DO char ¬ Stream.GetByte[fileStream ! Stream.EndOfStream => { EOL ¬ EOF ¬ TRUE; CONTINUE}]; SELECT char FROM SP => IF EOL THEN CRSeen ¬ EOL ¬ FALSE; Tab => NULL; colon => {i ¬ i + 1; IF i > numberOfTokens THEN RETURN}; semiColon => {SkipLine[fileStream]; EOL ¬ TRUE; LOOP}; CR => CRSeen ¬ TRUE; ENDCASE => IF CRSeen THEN {backChar ¬ char; charInHole ¬ EOL ¬ TRUE} ELSE String.AppendChar[tokens[i], LOOPHOLE[char] ! String.StringBoundsFault => { tokens[i] ¬ String.CopyToNewString[s, zone, 30]; String.FreeString[zone, s]; RESUME[tokens[i]]}]; ENDLOOP; END; BuildNetMask: PROCEDURE [addr: ArpaRouter.InternetAddress] RETURNS [netMask: ArpaRouter.InternetAddress] = BEGIN InternetAddress: TYPE = MACHINE DEPENDENT RECORD[a, b: WORD]; classAMask: InternetAddress ¬ [100000B, 0B]; classBMask: InternetAddress ¬ [140000B, 0B]; classCMask: InternetAddress ¬ [160000B, 0B]; classA: InternetAddress ¬ [0B, 0B]; classB: InternetAddress ¬ [100000B, 0B]; classC: InternetAddress ¬ [140000B, 0B]; Mask: InternetAddress ¬ [0B, 0B]; SELECT TRUE FROM (Inline.DBITAND[LOOPHOLE[addr], LOOPHOLE[classAMask]] = LOOPHOLE[classA, LONG UNSPECIFIED]) => Mask ¬ [177400B, 0B]; (Inline.DBITAND[LOOPHOLE[addr], LOOPHOLE[classBMask]] = LOOPHOLE[classB, LONG UNSPECIFIED]) => Mask ¬ [177777B, 0B]; (Inline.DBITAND[LOOPHOLE[addr], LOOPHOLE[classCMask]] = LOOPHOLE[classC, LONG UNSPECIFIED]) => Mask ¬ [177777B, 177400B]; ENDCASE => --unimplemented extended addressing or unrecognizable. Mask ¬ [0B, 0B]; netMask ¬ LOOPHOLE[Mask]; END; AddrMismatch: PROCEDURE [mask, test, target: ArpaRouter.InternetAddress] RETURNS[BOOLEAN] = MACHINE CODE {Mopcodes.zESC, ESCAlpha.aDXOR; Mopcodes.zESC, ESCAlpha.aDAND; Mopcodes.zIOR}; LocalNet: PROCEDURE [addr: ArpaRouter.InternetAddress] RETURNS [true: BOOLEAN] = {RETURN[~AddrMismatch[netMask, ArpaRouter.GetAddress[], addr]]}; GetAddr: PROCEDURE [addrStr: LONG STRING] RETURNS [ addr: ArpaRouter.InternetAddress ¬ ArpaRouter.unknownInternetAddress] = BEGIN first: BOOLEAN ¬ TRUE; string: LONG STRING ¬ [256]; commaPosition, prevComma: CARDINAL ¬ 0; tempSubString: String.SubStringDescriptor; firstAddr: ArpaRouter.InternetAddress ¬ addr; FOR i: CARDINAL IN [0..addrStr.length) DO IF addrStr.text[i].ORD = comma OR (i = addrStr.length - 1) THEN BEGIN tempSubString ¬ [addrStr, prevComma, i - prevComma + (IF i = addrStr.length - 1 THEN 1 ELSE 0)]; String.AppendSubString[string, @tempSubString ! String.StringBoundsFault => { prevComma ¬ i + 1; string.length ¬ 0; LOOP}]; prevComma ¬ i + 1; addr ¬ ArpaAddressTranslation.StringToInternetAddress[string]; string.length ¬ 0; IF first THEN {first ¬ FALSE; firstAddr ¬ addr}; IF LocalNet[addr] THEN RETURN[addr]; END; ENDLOOP; IF firstAddr # ArpaRouter.unknownInternetAddress THEN RETURN[firstAddr]; END; AddEntry: PROCEDURE = BEGIN commaPosition, prevComma: CARDINAL ¬ 0; string: LONG STRING ¬ [256]; tempSubString: String.SubStringDescriptor; addr: ArpaRouter.InternetAddress ¬ ArpaRouter.unknownInternetAddress; netMask ¬ BuildNetMask[ArpaRouter.GetAddress[]]; addr ¬ GetAddr[tokens[0]]; FOR i: CARDINAL IN [0..tokens[1].length) DO IF tokens[1].text[i].ORD = comma OR (i = tokens[1].length - 1) THEN BEGIN tempSubString ¬ [tokens[1], prevComma, i - prevComma + (IF i = tokens[1].length - 1 THEN 1 ELSE 0)]; String.AppendSubString[string, @tempSubString ! String.StringBoundsFault => { prevComma ¬ i + 1; string.length ¬ 0; LOOP}]; prevComma ¬ i + 1; ArpaAddressCache.AddEntry[string, addr]; string.length ¬ 0; END; ENDLOOP; END; FOR index: CARDINAL IN [0..6) DO tokens[index] ¬ String.MakeString[zone, 50]; ENDLOOP; WHILE ~EOF DO GetKeyword[keyword]; SELECT TRUE FROM String.Equivalent[keyword, "NET"L] => { EOF ¬ GetTokens[2]; SkipLine[fileStream]}; String.Equivalent[keyword, "GATEWAY"L] => { EOF ¬ GetTokens[5]; SkipLine[fileStream]}; String.Equivalent[keyword, "HOST"L] => { EOF ¬ GetTokens[5]; AddEntry[]}; < SkipLine[fileStream];>> ENDCASE => SkipLine[fileStream]; keyword.length ¬ 0; FOR index: CARDINAL IN [0..6) DO tokens[index].length ¬ 0; ENDLOOP; ENDLOOP; FOR index: CARDINAL IN [0..6) DO String.FreeString[zone, tokens[index]]; ENDLOOP; END; END.