-- File: TrapBadPups.mesa - last edit:
-- AOF 3-Feb-88 17:11:30
-- HGM 6-Aug-85 21:04:11
-- Copyright (C) 1984, 1985, 1988 by Xerox Corporation. All rights reserved.
DIRECTORY
Ascii USING [CR, SP],
CmFile USING [Handle, TableError],
Heap USING [Create],
IEEE8023 USING [EncapObject],
Put USING [Text],
SptpProtocol USING [EncapsulationObject],
String USING [AppendChar, AppendLongDecimal, AppendNumber, AppendString],
StringLookUp USING [noMatch, TableDesc],
System USING [
AdjustGreenwichMeanTime, GetGreenwichMeanTime, gmtEpoch, GreenwichMeanTime],
Time USING [AppendCurrent],
Token USING [Decimal, Filtered, FreeTokenString, Item, Line],
Indirect USING [Close, NextValue, OpenSection],
Mailer USING [Level, SendGVMail],
Buffer USING [],
Driver USING [Device],
EthernetOneDriverTypes USING [Encapsulation],
PupDefs USING [
AppendPupAddress, AppendHostName, Body, GetPupContentsBytes, PupBuffer],
ForwarderDefs USING [],
PupRouterDefs USING [NetworkContext, RejectPupWithBadChecksum, SetPupChecksum];
TrapBadPups: MONITOR
IMPORTS
CmFile, Heap, Put, String, System, Time, Token, Indirect, Mailer, PupDefs,
PupRouterDefs
EXPORTS Buffer, ForwarderDefs
SHARES Buffer =
BEGIN
-- EXPORTed TYPEs
Device: PUBLIC <<Buffer>> TYPE = Driver.Device;
to, cc: LONG STRING ← NIL;
troubles: LONG STRING ← NIL; -- Also used as from
z: UNCOUNTED ZONE = Heap.Create[1];
badSequenceNumber: LONG CARDINAL ← 0;
recent: CARDINAL ← 0;
clumpSize: CARDINAL ← 3;
secondsPerPacket: CARDINAL ← 3600; -- one/hour
lastTime: System.GreenwichMeanTime ← System.GetGreenwichMeanTime[];
CollectInfo: PROCEDURE =
BEGIN
cmFile: CmFile.Handle;
Option: TYPE = MACHINE DEPENDENT{
troubles(0), to, cc, clumpSize, secondsPerPacket, noMatch(StringLookUp.noMatch)};
DefinedOption: TYPE = Option [troubles..secondsPerPacket];
CheckType: PROCEDURE [h: CmFile.Handle, table: StringLookUp.TableDesc]
RETURNS [index: CARDINAL] = Indirect.NextValue;
MyNextValue: PROCEDURE [
h: CmFile.Handle,
table: LONG DESCRIPTOR FOR ARRAY DefinedOption OF LONG STRING]
RETURNS [index: Option] = LOOPHOLE[CheckType];
optionTable: ARRAY DefinedOption OF LONG STRING ← [
troubles: "Troubles"L, to: "to"L, cc: "cc"L,
clumpSize: "Clump Size"L, secondsPerPacket: "Seconds Per Packet"L];
cmFile ← Indirect.OpenSection["TrapBadPups"L];
IF cmFile = NIL THEN
BEGIN
Message["Can't find [TrapBadPups] section in parameter file."L];
RETURN;
END;
DO
option: Option;
option ← MyNextValue[cmFile, DESCRIPTOR[optionTable] !
CmFile.TableError =>
BEGIN
IF name[0] # '; THEN Message["Unrecognized parameter: ", name];
RETRY;
END];
SELECT option FROM
noMatch => EXIT;
troubles =>
BEGIN
temp: LONG STRING;
z.FREE[@troubles];
temp ← Token.Item[cmFile];
troubles ← z.NEW[StringBody[temp.length]];
String.AppendString[troubles, temp];
[] ← Token.FreeTokenString[temp];
CheckForRegistry[troubles];
END;
to =>
BEGIN
temp: LONG STRING ← Token.Filtered[cmFile, NIL, Token.Line, whiteSpace, FALSE];
z.FREE[@to];
to ← z.NEW[StringBody[temp.length]];
String.AppendString[to, temp];
[] ← Token.FreeTokenString[temp];
CheckForRegistry[to];
END;
cc =>
BEGIN
temp: LONG STRING ← Token.Filtered[cmFile, NIL, Token.Line, whiteSpace, FALSE];
z.FREE[@cc];
cc ← z.NEW[StringBody[temp.length]];
String.AppendString[cc, temp];
[] ← Token.FreeTokenString[temp];
CheckForRegistry[cc];
END;
clumpSize =>
BEGIN
clumpSize ← Token.Decimal[cmFile];
END;
secondsPerPacket =>
BEGIN
clumpSize ← Token.Decimal[cmFile];
END;
ENDCASE => ERROR;
ENDLOOP;
Indirect.Close[cmFile];
IF troubles = NIL THEN
Message["Please specify somebody in case of TROUBLES"L];
IF to = NIL THEN Message["Please specify somebody to send the message to"L];
RETURN;
END;
CheckForRegistry: PROCEDURE [s: LONG STRING] =
BEGIN
dot: BOOLEAN ← FALSE;
FOR i: CARDINAL IN [0..s.length) DO
SELECT s[i] FROM
'. => dot ← TRUE;
', =>
BEGIN
IF ~dot THEN
BEGIN Message["Registry expected in arg: "L, s]; RETURN; END;
dot ← FALSE;
END;
ENDCASE => NULL;
ENDLOOP;
IF ~dot THEN BEGIN Message["Registry expected in arg: "L, s]; RETURN; END;
END;
Message: PROCEDURE [one, two, three: LONG STRING ← NIL] =
BEGIN
text: STRING = [100];
Time.AppendCurrent[text];
String.AppendString[text, " TrapBadPups: "L];
String.AppendString[text, one];
IF two # NIL THEN String.AppendString[text, two];
IF three # NIL THEN String.AppendString[text, three];
LogString[text];
END;
Filter: PROCEDURE RETURNS [ok: BOOLEAN ← FALSE] =
BEGIN
-- Limit to avg of 1/hour, but allow clumps of 3.
IF lastTime # System.gmtEpoch THEN
BEGIN
seconds: LONG CARDINAL ← System.GetGreenwichMeanTime[] - lastTime;
WHILE seconds > secondsPerPacket DO
IF recent = 0 THEN
BEGIN
lastTime ← System.GetGreenwichMeanTime[];
EXIT;
END;
recent ← recent - 1;
lastTime ← System.AdjustGreenwichMeanTime[lastTime, secondsPerPacket];
ENDLOOP;
END;
IF recent < clumpSize THEN ok ← TRUE;
IF ok THEN recent ← recent + 1;
END;
PrintBadPup: PUBLIC PROCEDURE [b: PupDefs.PupBuffer] =
BEGIN
IF lastTime = System.gmtEpoch THEN lastTime ← System.GetGreenwichMeanTime[];
IF b = NIL THEN RETURN;
badSequenceNumber ← badSequenceNumber + 1;
IF Filter[] THEN MailBadPup[b];
PupRouterDefs.RejectPupWithBadChecksum[b];
END;
maxWords: CARDINAL = 300;
maxBytes: CARDINAL = 600 + maxWords*9;
MailBadPup: PUBLIC PROCEDURE [b: PupDefs.PupBuffer] =
BEGIN
encapsulationLengthWords: NATURAL;
device: Device;
pup: PupDefs.Body = b.pup;
body: STRING = [maxBytes];
size: CARDINAL ← (pup.pupLength - 1)/2;
checksumLoc: LONG POINTER ← @pup.pupLength + size;
words: CARDINAL ← (PupDefs.GetPupContentsBytes[b] + 1)/2;
p: LONG POINTER;
context: PupRouterDefs.NetworkContext = b.fo.context;
hack: BOOLEAN ← pup.pupType = echoMe OR pup.pupType = iAmEcho;
Info: PROCEDURE [s: LONG STRING, level: Mailer.Level] =
BEGIN -- Krock because Put.Line is not Atomic
copy: LONG STRING ← z.NEW[StringBody[s.length + 2]];
String.AppendString[copy, s];
LogString[copy];
z.FREE[@copy];
END;
O7: PROCEDURE [n: WORD] =
BEGIN
temp: STRING = [10];
String.AppendNumber[temp, n, 8];
THROUGH [temp.length..7) DO String.AppendChar[body, Ascii.SP]; ENDLOOP;
String.AppendNumber[body, n, 8];
END;
Time.AppendCurrent[body];
String.AppendString[body, " ***** Bad software checksum on Pup from net "L];
String.AppendNumber[body, context.pupNetNumber, 8];
String.AppendChar[body, Ascii.CR];
String.AppendString[body, "Bad pup number "L];
String.AppendLongDecimal[body, badSequenceNumber];
String.AppendString[body, " has a checksum of "L];
String.AppendNumber[body, checksumLoc↑, 8];
PupRouterDefs.SetPupChecksum[b]; -- Fix it up
String.AppendString[body, ", but it should be "L];
String.AppendNumber[body, checksumLoc↑, 8];
String.AppendChar[body, Ascii.CR];
String.AppendString[body, "Might be from: "L];
PupDefs.AppendPupAddress[body, pup.source];
String.AppendString[body, " = "L];
PupDefs.AppendHostName[body, pup.source];
String.AppendChar[body, Ascii.CR];
String.AppendString[body, "Driver length: "L];
String.AppendNumber[body, b.fo.driver.length, 10];
String.AppendChar[body, Ascii.CR];
String.AppendString[body, "Encap: "L];
p ← b.linkLayer.blockPointer;
device ← b.fo.network;
encapsulationLengthWords ← SELECT device.device FROM
ethernet => SIZE[ethernet IEEE8023.EncapObject],
ethernetOne => SIZE[EthernetOneDriverTypes.Encapsulation],
phonenet => SIZE[pup SptpProtocol.EncapsulationObject],
ENDCASE => 0;
FOR i: CARDINAL IN [0..encapsulationLengthWords) DO
O7[(p + i)↑];
IF hack THEN String.AppendChar[body, ' ];
ENDLOOP;
String.AppendChar[body, Ascii.CR];
String.AppendString[body, "Header:"L];
p ← b.pup;
FOR i: CARDINAL IN [0..11 - 1) DO
O7[(p + i)↑];
IF hack THEN String.AppendChar[body, ' ];
ENDLOOP;
FOR i: CARDINAL ← 0, i + 1 UNTIL i >= MIN[words, maxWords] DO
IF (i MOD 10) = 0 THEN
BEGIN
String.AppendChar[body, Ascii.CR];
String.AppendString[body, IF i = 0 THEN "Body: "L ELSE " "L];
END;
O7[pup.pupWords[i]];
IF hack THEN
BEGIN
IF pup.pupBytes[2*i] # (2*i MOD 400B)
OR pup.pupBytes[2*i + 1] # ((2*i + 1) MOD 400B) THEN
String.AppendChar[body, '←]
ELSE String.AppendChar[body, ' ];
END;
ENDLOOP;
String.AppendChar[body, Ascii.CR];
Put.Text[NIL, body];
IF troubles # NIL AND to # NIL THEN
BEGIN
[] ← Mailer.SendGVMail[
"Bad Pup Checksum info"L, to, cc, body, troubles, Info];
END;
END;
LogString: PROCEDURE [s: LONG STRING] =
BEGIN
String.AppendChar[s, '.];
String.AppendChar[s, Ascii.CR];
Put.Text[NIL, s];
END;
-- initialization
CollectInfo[];
END.