CONTENTS

*** Introduction
*** Unresolved Issues
*** System Issues
*** Troubleshooting a PPP Connection
*** Understanding PPP
*** FAQ
*** PPP.Log
*** PPPFSM.Mod
*** PPPHDLC.Mod
*** PPPIPCP.Mod
*** PPPLCP.Mod
*** PPPMain.Mod
*** PPPPAP.Mod
*** PPPTools.Mod

*** Introduction

The original PPP for XOberon was written by Martin Aeschlimann and Claude Knaus. Edgar Schwarz ported to ETH Oberon / PC Native. Studying the PPP*.Mods and writing these notes has given me a big respect for the work of creating and porting. Thanks Claude, Martin and Edgar!

The notes in this file are primarily relevant to someone having trouble with PPP. I recommend reading these notes before installing and compiling the modified *.Mod files. If you decide to get the modified files, consider putting them in your HOME partition and comparing with the files in SYS using Diff.Do. Diff.Do SYS:PPPFSM.Mod HOME:PPPFSM.Mod for example.

*** Unresolved Issues

Help with these is always welcome.

(1) Can the packet identifier be fixed as described under PPPFSM.Mod following? If there is a reason not to do this, please let me know.

(2) Name server addresses need to be handled properly. Refer to the first CASE statement in PPPIPCP.ReqCI. Several modules need small changes to achieve this.

(3) I do not understand the strategy for dealing with multiple options in one frame. For example, Oberon might receive a frame containing 3 options. Oberon could choose to accept one and to reject another and fail to recognize the third. As I understand, this would require two packets from Oberon to the peer but I do not see this implemented. Any thoughts? How does the Linux PPP handle such possibilities?

*** System Issues

NetSystem.Mod specifies this syntax.

NetSystem.SetUser { service ":" ["//"] [ user [ ":" password ] "@" ] host [ "/" ] } "~"

Prior to availability of PPP, the terms "service" and "host" were OK. They now seem a little inappropriate and confusing. For example, DIAL is not a host and pap is a protocol rather than a service. I suggest replacing "service" with "servicetype" and "host" with "servicename" in descriptions of NetSystem.SetUser.

The syntax of Oberon.Text allows multiple Devices, Device0 .. Device9. In PC Native Oberon 05.01.2003 the maximal number of Devices, MaxDevices, is set in NetBase.Mod to 2. If required this limit can be increased to 10 at most, with subsequent recompilation of NetBase.Mod. Multiple Devices allow the use of various network hardware and protocol options without changing Oberon.Text. For example Oberon.Text might define these three Devices.

 
   Device0 = { "PPPMain.InstPPP", "COM1"} 
   Device1 = { "PPPMain.InstPPP", "COM2 \silent"} 
   Device2 = { "Net3Com509.InstallDevice", "" } 

This allows the usual (extroverted?) option for PPP to be invoked with
 
    Dialer.Dial DIAL Device0 ~ 
whereas the "silent" option is invoked with
 
    Dialer.Dial DIAL Device1 ~ . 

Device2 allows for an Ethernet connection. Note that two different PPPs can not be installed on the same COM port and that NetBase.Mod must be recompiled with MaxDevices* = 3 or more for this example to work.

Logically, the parameters of a service, as supplied by NetSystem.SetUser, the name of a dial script, a command to invoke PPP and a Device<m> might be associated with Route<n> in Oberon.Text. I wonder about a command such as NetSystem.Connect Route<n>?

Chris Glur and others have mentioned difficulties resulting when a domain name contains "@" and other characters used in the syntax of the NetSystem.SetUser command. This problem was addressed by the IETF in RFC 2396. The escape scheme of RFC 2396 is implemented in pe.URI.Mod and is discussed in the FAQ below.

In the summer or fall of 2002 the Native Oberon mailing list received a message questioning redundancy in the argument of the CALL command in the dial script when a PAP service is accessed. A small benefit of the hypothetical NetSystem.Connect command could be elimination of this redundancy.

*** Troubleshooting a PPP Connection

Begin at the lowest level, the modem, and work to the highest level, the browser, mail handler and etc.

Information about modems can be found at the Kermit site, http://kermit.columbia.edu/. Look for the file KERMIT.BWR in the DOS distribution, and others.

A modem has two speeds: interface and modulation. The interface speed is between the computer and the modem. The modulation speed is between the modem and the telephone network. Unless referring specifically to the interface, specifications usually refer to the modulation speed.

The interface speed of an internal modem or computer serial port is set in Oberon.Text in a DIAL script. For example
     Init = { COM1 57600 }     {* modem port and speed *}.
As can be seen in V24.Start, allowed values of this speed are whole divisors of 115200 b/s. Hence, Oberon allows these speeds for the interface.

 
115200 
 57600 
 38400 
 19200 
 14400

The maximal interface speed of a modem is usually higher than the modulation speed.

An external modem connects to a serial port and buffering is an issue. An internal modem connects directly to the system bus. Buffering between computer and internal modem is not an issue or is less critical than with an external modem. Perhaps someone who knows about busses and modem circuitry can elaborate.

The interface speed should be set in the dial script to min(p, m) where p is the highest speed at which the the serial port of the computer can operate and m is the highest speed at which the serial port of the modem can operate. Some of the old IDE I/O cards used in desktop PCs were not reliable above 9600 b/s! Serial ports in laptop PCs are buffered better. My old Toshiba Satellite T2100 operates reliably at 38400 b/s; never tested 57600 b/s.

In absence of specifications, the interface speed can be set empirically. Try one of these settings. If communication fails, adjust to a slower speed.

 
  Modulation      Interface 
    14400           19200 
    28800           38400 
    57600           57600 

Before attempting to make a DIAL script, try the V24.Panel. Execute Desktops.OpenDoc V24.Panel . Set the interface speed in the window. Parameters are COM port, interface speed, bits/byte, number of stop bits, parity. Click the Open button. Key in the modem initialization. For the majority of cases, ATZ will work. More information about initialization is available in the Kermit documentation and elsewhere on the Web.

After the modem acknowledges initialization, in most cases with OK, key in the dial command. For example, ATD T5392157 . The T invokes tone rather than pulse dialing. After a few to several seconds you should see a response from the remote system. If it allows a "terminal" or "dialup" connection you should get a prompt such as "login: ". In any case, you will at least have established that your modem can communicate with the remote modem.

The next objective is to obtain a working DIAL script. It can be built up step by step. Rather than assume the characters which will be returned by the remote system, begin with something such as this, adapted to your environment. Replace "GulfNet" with any name you fancy, set the COM port and speed in Init and replace 5392157 with the number for your server.

{* This is for the Motorola MODMSURFR *} 
GulfNet = { 
     Init = { COM1 38400 }     {* modem port and speed *} 
     Dial = { 
          "ATZ"  
          10 "OK"  
          "ATD T5392101"  
          60 "ZZ" 
     } 
}

"ZZ" is unlikely to be returned by the local modem, the remote modem or the remote system. Consequently the script just waits for all characters returned within 60 seconds. The System.Log will show the complete reply. Move it to the user track for easier reading. Choose a string of characters from the reply which indicates unambiguously, completion of the modem-modem connection. For example GulfNet yields this.

 
{|ATD T5392101||CONNECT 38400|~ ... 

The strange characters beginning with ~ are the the PPP negotiations. The modem-modem connection isidentified by "CONNECT 38400". Hence, "ZZ" in the script can be replaced with "400". This is my dial script.

{* This is for the Motorola MODMSURFR *} 
GulfNet3 = { 
     Init = { COM1 38400 }     {* modem port and speed *} 
     Dial = { 
          "ATZ"  
          10 "OK"  
          "ATD T5392101"  
          60 "400" 
          CALL "PPPMain.StartInst GulfNet3 peter" 
     } 
}

If the server does not prompt for a userid and password it should expect PAP (Password Authentication Protocol) authentication.

*** Understanding PPP

These documents at least should be studied to understand PPP. They are available from http://www.ietf.org/. Begin with 1548.

RFC 1172 PPP Initial Configuration
RFC 1332 IPCP
RFC 1334 Authentication
RFC 1548 PPP
RFC 1549 PPP in HDLC Framing
RFC 1877 Name Server Addresses

In _The School of Niklaus Wirth_, Pub. Morgan Kaufmann, 2000, p. 107, Jurg Gutknecht gives an EBNF description of the Oberon file transfer protocol and makes this cogent observation. "The following two examples illustrate convincingly that a few lines of formal text, in combination with expressive names, are worth more than a thousand pages of verbose and lengthy explanations." Anyone care to contribute an EBNF specification of PPP?

When PPP begins operation, at least two protocols, LCP and IPCP must be negotiated between the two computers. LCP, Link Control Protocol, is the more fundamental and is negotiated first. IPCP, Internet Protocol Control Protocol, is more abstract and is negotiated after LCP. If PAP is required it is between LCP and IPCP.

The negotiations of the protocols are essentially a conversation between two automata. Of course, these automata are softwares in the respective computers. In Oberon PPP the automaton is implemented in PPPFSM.Mod. FSM is the acronym for finite state machine, a synonym for automaton.

*** FAQ

Q. My telephone connection can be severed while PPP is operating. In some instances the RJ11 connector is accidently pulled out of the socket in the wall or modem. Otherwise the fault is in the telephone network. The mouse pointer becomes frozen. Is there any recovery other than rebooting?

A. Refer to the OSI scheme of communication.
http://en.wikipedia.org/wiki/OSI-model
PPP operates at the network layer. When PPP is interrupted, higher level protocols will also be operating. For example, http might be retrieving a Web page. A timer in the higher protocol must expire before the event loop of Oberon can resume. Refer to NetTools.TimeOut and Input.TimeUnit. The default setting is one minute.

After the higher level protocols have timed out, the Oberon event loop will resume cycling. PPPMain.StopInst can be executed. With the communication fault repaired, a new connection can be initiated with Dialer.Dial.

Q1. My new ISP for PPP assigned me the userid orca@pender and I chose the password sal:mon . I executed

 
NetSystem.SetUser dialup:orca@pender:sal:mon@gulfnet ~ . 

SetUser then prompted me for a password. It failed to recognize the password in the argument of SetUser. How can these annoying problems be solved?

Q2. An FTP server can require an email address as password. To retrieve the installation files for Bluebottle I executed
NetSystem.SetUser
ftp:download:goose@canada.com@bluebottle.ethz.ch ~ .
NetSystem.Show reported
NetSystem.SetUser ftp:download@canada.com ~ .
It takes the host to be canada.com and ignores everything from the second @ onward.

A1&A2. The argument of NetSystem.SetUser can be viewed as a URI as specified in RFC 1738, http://www.apps.ietf.org/rfc/rfc1738.html . The possibility of the characters /, : and @ appearing in a URI is addressed in RFC 2396, http://www.apps.ietf.org/rfc/rfc2396.html . Ambiguity is avoided by encoding the characters which are syntactically significant. In ETH Oberon / PC Native 05.01.2003 this encoding and decoding is implemented in HyperDocs.ESC and HyperDocs.UnESC. Logically the ESC and UnESC procedures would better be defined in and exported from NetSystem. HyperDocs is at a more abstract level and should import the procedures rather than define redundantly. Rather than alter HyperDocs or NetSystem I made the new module named URI.

HyperDocs.ESC takes the string to be escaped as a VAR argument and modifies it in place. This is not so good for NetSystem where the user authentication parameters are always in escaped form when seen by the user yet must be available in literal form for communications. For efficiency we might think of defining the TYPE PasswordDesc to contain both escaped and literal forms of the parameters. I rely on the simpler and less efficient mechanism of unescaping the authentication parameters whenever they are communicated from user to system and then of escaping them when they are displayed to the user. This requires the ability to escape without altering the literal form. Hence, UnESC needs distinct source and target parameters.

The examples of the foregoing questions work correctly when @ and : are submitted in encoded form as described in RFC 2396. The hexadecimal ordinal of @ is 40 and of : is 3A. Hence,

 
NetSystem.SetUser 
dialup:orca%40pender:sal%3Amon@gulfnet 
ftp://download:goose%40canada.com@bluebottle.ethz.ch ~ . 

SetUser applies URI.UnESC before storing the parameters. NetSystem.Show applies URI.ESC again before displaying them. pe.URI.Mod contains several checks for fault conditions.

*** PPP.Log

Tip: do not open the log while PPP is active. Execute PPPTest.LogOff before PPPTest.ShowLog.

Incoming and outgoing frames are now marked with notations '<-<-<- Frame ...' and '->->-> Frame ...' respectively. This is intended to enhance readability and facilitate discussion and troubleshooting.

The following is a list of small changes in the source texts for PPP which help to make them and the logs more understandable for me. Apologies to Edgar Schwarz for tampering.

*** PPPFSM.Mod

The acronym FSM is explained.

In the revision history, "addes" -> "added".

According to RFC 1548 a packet identifier is one octet; ie. the identifier is in {0..255}. ID and reqID in FSMDesc are SHORTINTs which are in {-128..127} in Native Oberon. This seems OK provided no packet identifier exceeds 127. The VicomSoft Router does emit packets with identifiers in {128..255} and the negative id numbers appearing in PPP.Log are confusing at best. Also, I wonder whether ambiguous id numbers can occur. Seems that ID, reqID and the ids in various procedures might be declared INTEGER with the cost of a little more memory. Comments?

In PPPFSM.Input, the report "new Input" immediately after "FSM.Input" seems redundant. "new Input" is deleted.

In PPPFSM.SendConfReq, following OutLog("FSM.SendConfReq", "", f); ... there are two line breaks. Deletion of one Debug.Ln does not appear to violate a spacing pattern.

The terms "FSM.Input" and "FSM.SendData" are not symmetrical. "FSM.SendData" is more meaningful to me. I've changed "FSM.Input" to "FSM.ReceiveData".

*** PPPHDLC.Mod

VAR declaration added. 
     FrameCount: INTEGER;  (* pe: number frames, for reference. *) 

(* save uncomplete frames between calls to Reveive *) 
Probably meant to be this. 
(* Save incomplete frames between calls to Receive *) 

(*es??? die V24 und Loginsachen macht doch der Dialer. Oder ? *) 
=? (* V24 login is handled in the Dialer, isn't it? *) 

"Pustekuchen, macht Devicepolling" 
=? "Begin communicating with the remote system." 

(*es auskommentiert: der Trick ist irgendwie alle Zeichen zu sammeln, 
     die man ohne Maskierung (EscSymbol) senden kann. Wenn man dann 
     auf eines trifft, verpackt man es und schickt die Dinger von zuvor  
     auf weg. Das ist mir etwas zu undurchsichtig. *) 
=  
(* Translation & remark from T.F.  
     "Section commented out: The trick is to somehow collect all the  
     characters that can be sent without escaping (EscSymbol).  Once we  
     come across a character that needs escaping, we send all the previously  
     collected characters followed by the escaped character.  
©      
     It is probably some kind of "optimized code" that was translated and when  
     it did not work was finally replaced by the version below the  
     commented-out code.  From what I can tell the active code is better  
     anyways (simpler).  If optimization is needed, AosIO could be used to collect  
     the characters in a much simpler way." *) 

Debug output modified to make the log more readable. 
In PPPHDLC.CheckPacket 
          IF debug THEN 
               (* pe *) Debug.String('->->-> Frame '); Debug.Int(FrameCount, 5);  
               Debug.String(' received from peer.'); Debug.Ln; 
               INC(FrameCount); (* pe *) 

In PPPHDLC.SendPacket 
          IF debug THEN 
               (* pe *) Debug.String('<-<-<- Frame '); Debug.Int(FrameCount, 5);  
               Debug.String(' going to peer.'); Debug.Ln; 
               INC(FrameCount); (* pe *)

Initialize FrameCount in the body of the module.      (* pe *) FrameCount := 0;

*** PPPIPCP.Mod

Added constants to represent the four nameserver options described in RFC 1877; DNSAddr0 .. NBNSAddr1. Edgar or anyone else who prefers other names (DNS0 ..?) is welcome to comment.

A VicomSoft router sends his IP address and a DNS address in one frame. Oberon PPP 2.1 does not recognize the DNS address option and rejects the packet. Vicom requests in this manner and Oberon rejects, until failure occurs.

In procedure ReqCI, added DNSAddr0 after Addr in the CaseLabelList. This allows Oberon to accept the IP address for the VicomSoft router. This works when the Vicom IP address and DNS address are the same. Have not tested when the two addresses differ. While Oberon accepts the requested DNS address it does not yet update the DNS address established in Oberon.Text.

Added debug output in the CASE statement in RejCI to report the Addr case and the unknown option case.

*** PPPLCP.Mod

In PPPLCP.ReqCI change Debug.String("RejPCComp") to Debug.String("RejPFComp"). The acronym represents "Reject Protocol-Field-Compression".

For legibility add a blank after each "Rej" acronym. Eg. Debug.String("RejIllegal0") becomes Debug.String("RejIllegal0 ").

For consistency, change Debug.String("Rej: NegUPap ") to Debug.String("RejNegUPap ").

*** PPPMain.Mod

 
(*  
     ToDo: 
          SendPacket ueberpruefen, falls nicht alle characters gesendet 

                     Spaeter: Routing von PacketTools entkoppeln *) =? (*      ToDo:           A careful review of SendPacket in case not all characters are sent.

                     Later: Routing in PacketTools encapsulation (??). *)

In PPPMain.LCPUp add Debug.Ln after the two "Debug.String"s.

In PPPMain.IPCPDown add Out.String("PPP connection closed."); Out.Ln;.

*** PPPPAP.Mod

RFC 1334 specifies the syntax of Authenticate-Ack and Authenticate-Nak packets returned in response to an Authenticate-Request. The Authenticate-Nak message is copied to PPP.Log in plain text. The Authenticate-Ack message should also be reported in plain text in PPP.Log.

*** PPPTools.Mod

PPPTools.OutPacket invokes Debug.Ln following the loop if the loop did not end with Debug.Ln.

This version of OutPacket does not use MOD. I've tested it in a test-wrapper module and used it in PPPTools.

 
PROCEDURE OutPacket (VAR p: ARRAY OF CHAR; pos, len: INTEGER); 
     CONST 
          octetsPerchunk = 4;  (* Upper bound on octet count in a chunk. *) 
          chunksPerline = 4;  (* Upper bound on chunk count in a line. *) 
     VAR i, octet, octetsPerchunk, chunk, chunksPerline: INTEGER; 
BEGIN 
     i := 0;  (* Counter for the characters in p. *) 
     octet := 0;  (* Counter for the characters in an ouput chunk. *) 
     chunk := 1;  (* Counter for the chunks on one line. *) 
     WHILE i < len DO 
          IF octet = octetsPerchunk THEN (* Start a new chunk. *) 
               IF chunk = chunksPerline THEN (* Also start a new line. *) 
                    Debug.Ln; chunk := 1; octet := 1 
               ELSE (* chunk < chunksPerline.  
                    Start the new chunk on the same line. *) 
                    Debug.String(" "); INC(chunk); octet := 1 
               END 
          ELSE (* octet < octetsPerchunk.  
               Report the character in the current line and chunk. *) 
               INC(octet) 
          END; 
          (* Debug.String(" "); Debug.Char(p[pos + i]); *) 
          Debug.HexByte(p[pos + i]);  
          INC(i); 
     END; (* i = len *)  
     Debug.Ln; Debug.String("Finished OutPacket."); Debug.Ln 
END OutPacket; 

Valid CSS! HTML5 conformance

Best viewed with a Web browser.

HTML.Compile * Desktops.OpenDoc PPPnotes.html ET.OpenAscii PPPnotes.html FTP.Open "easthope@easthope.ca" FTP.PutFiles PPPnotes.html => "/public_html/PPPnotes.html" ~ FTP.Close