Skip to main content

     
  TPF : Library : Newsletters

Designing an Internet Server on TPF

Miguel Delatorre, IBM TPF Development

In the Fall 1998 issue of the TPF Systems Technical Newsletter I wrote the first article of a three-part series about a sample client/server application. In that article I briefly mentioned the Internet daemon support provided with TPF program update tape (PUT) 9. I glossed over the details, but as I sit here writing parts 2 and 3, I thought it would be a good idea to further explain the communication options available in a TCP/IP environment for TPF. The Internet daemon supports an abundance of possible configuration options. At times, it may even seem overwhelming and, as if that was not enough, TPF also supports several user exits through the socket interface. Therefore, I would like to level-set and describe some of the options that are currently available.

User Exits

The TPF socket implementation allows for several user exits at different points during processing. As the name implies, user exits are points during processing where additional processing may be done outside the inherent system path. To that end, six user exits are defined within the TPF socket implementation:

  • socket accept
  • socket activation
  • socket connect
  • socket cycle-up
  • socket deactivation
  • socket system error.

The socket accept user exit provides a systemwide point where additional processing may take place before an application will be given control after issuing the accept() C language application programming interface (API). Keep in mind that this user exit is intended to service every accept() function call in the TPF system, so if there is processing that needs to be done for every accept() function call, regardless of the application, this is the place to insert the additional processing. I caution using this user exit because there may be times when a trusted client/server application will issue many accept() function calls but does not want the overhead of the additional processing.

The socket activation user exit is entered during system cycle-up and during ZCLAW ACTIVATE functional message processing at or above computer room agent set (CRAS) state. This user exit activates socket server applications and is called for each
TCP/IP offload device connected to the TPF system.

The socket connect user exit is called during Common Link Access to Workstation (CLAW) connect processing and allows CLAW applications to be activated.

The socket cycle-up user exit is entered only once during system cycle-up after all active offload devices are connected to the TPF system. When the TPF system successfully issues the socket cycle-up user exit, this user exit activates server applications for all TCP/IP offload devices that are connected to the TPF system.

The socket deactivation user exit is entered during system cycle-down and during ZCLAW INACTIVATE processing. Additional scenarios exist, but only these are key to this discussion.

The socket system error user exit is entered when a socket application must exit as a result of a system error.

Internet Daemon

The Internet daemon is the ubiquitous interface to access the Internet from any Internet Protocol (IP) server environment. The TPF Internet daemon goes one step beyond the standard interface: it provides simple protection against disruptive Internet server applications and an overwhelming amount of Internet requests, and it has the capability to create processes with predefined file system user and group access permissions.

The basic Internet daemon configuration can be done through one functional message: ZINET. The ZINET functional message supports ADD, ALTER, DELETE, DISPLAY, START, STOP, and HELP (also known as ?). In addition to these positional parameters, there are over 15 keyword parameters, some of which are mutually exclusive. My favorite entry is ZINET HELP. To configure a server application (for example, as in the tftp configuration of the Internet daemon), a user would type the following entry:

ZINET ADD S-TFTP PGM-CTFT MODEL-WAIT PORT-69 P-UDP

For a complete, detailed outline of the available ZINET entries, see TPF 4.1 Operations.

A. Simple Protection against Disruptive Server Applications

The Internet daemon has a built-in error threshold parameter to protect the TPF system against disruptive server applications. This parameter indicates how many errors an Internet server application may receive before the Internet daemon stops the Internet server application. In TPF vernacular, the Internet daemon will keep an Internet server application from streaming dumps and will display a message to the console advising manual intervention when the error threshold is achieved. The Internet daemon achieves this process by executing a tpf_fork() function and establishing a parent/child relationship between itself and the Internet server application. When the Internet server application exits, regardless of the exit method (for example, a dump or the exit() function), the Internet daemon is notified by the system with the application server exit status. On close inspection of the exit status, the Internet daemon determines how to proceed. Let us look at an example.

Suppose we wanted to add this functionality to the tftp server defined previously. I will define my tftp Internet daemon configuration with two additional keyword parameters: SERVErrors and SERVETime. The first parameter specifies the number of Internet server application process instances that can end in error before the Internet daemon listener stops the Internet server application. The second parameter specifies the sampling time interval, in seconds, that the Internet daemon listener uses to determine the Internet server application error rate threshold. The entry is as follows:

ZINET ALTER S-TFTP SERVE-5 SEVERT-60

B. Simple Protection against Overwhelming Numbers of Requests

Another option the Internet daemon supports is the maximum number of concurrent Internet servers allowed to execute. This option provides a very simple throttling mechanism to control application servers from depleting the system of its resources. When I say simple, I mean simple. The only value considered is the number of concurrent applications. No allowance is given to whether there are enough system resources to execute the application aside from what is already provided by the create ECB macros, which in this case will be tpf_fork(). Let's look at another example built on top of the previous example. This will use the MAXPROC parameter to specify the maximum number of Internet server application process instances for every IP address that the Internet daemon listener allows in the TPF system. The previously defined WAIT model has an implicit MAXPROC value of 1, so I will change the model from WAIT to NOWAIT. The NOWAIT model is also supported by the TPF tftp server. I will elaborate a little more on the model types in a later section. The new alter command for the Internet daemon configuration is:

ZINET ALTER S-TFTP MODEL-NOWAIT MAXPROC-5

C. File System Access Control

On many UNIX servers, the Internet daemon is configured to execute application server programs using a predefined user name. This name corresponds to a name defined in the file system password/group file. Because TPF has a file system with similar characteristics of UNIX- and POSIX-compatible systems, the Internet daemon establishes a user identity for the application server. The user name identity is later implicitly used by the application program to determine file access control. By default, the Internet daemon creates the application server process with a user name of nobody. By using this method, even a malicious application server cannot modify files that do not belong to it. File read, write, and execute access control is based on the user name assigned to a process. Let's look at the entry to modify the user name:

ZINET ALTER S-TFTP USER-NOBODY

The following is the Internet daemon/tftp server display:

ZINET D S-TFTP                                                        
CSMP0097I 17.23.07 CPU-B SS-BSS  SSU-HPN  IS-01                       
INET0024I 17.23.07 START OF ZINET DISPLAY OF ACTIVE SERVER            
SERVER - TFTP               PROCID - B    ACTIVATION - AUTO                   
PGM                 - CTFT                         PARM   -                                          
PROTOCOL            - UDP   PORT          - 00069  MODEL         - NOWAIT            
SERVERRORS          - 00005 SERVETIME     - 00060  USER          - nobody                 
MAXPROC             - 00005 TIMEOUT       - 00000  STATE         - NORM                   
AORLENGTH           - 00000                                                    
IP - ANY            SOCKET     - 00000038          COUNT - 0000000002             
TOTAL COUNT - 0000000002             
END OF DISPLAY+                                                       

Internet Daemon Models

In addition to the typical values (port, protocol, and so on) that an Internet server (socket) application needs during initialization, the Internet daemon may be configured in four processing models:

  • WAIT
  • NOWAIT
  • AOR
  • NOLISTEN.

Suppose I wanted to write an application that could not run concurrently with another copy of itself running. This may seem archaic for most TPF users, but there are times when it is not worth the additional design effort to allow multiple copies of a program to run concurrently. One quick example is a utility that runs once a day. The WAIT model is the perfect solution and will cause the Internet daemon to stop listening while an application server executes. On completion, the Internet daemon is notified by the system and will return to listening on a given port.

A little more robust than the WAIT model is the NOWAIT model. Using this option of the Internet daemon will allow application servers to run concurrently up to a given maximum number, if desired. Why a maximum? Suppose I wanted to dedicate a system to Internet servers and mission-critical applications (not to imply the others are not), but I was afraid the Internet traffic might overrun the mission-critical application. I would use the MAXPROC keyword parameter to throttle the number of ECBs executing concurrently for the Internet and the remainder may be used for the mission-critical applications. The Internet daemon always keeps a running count of the concurrent servers, without any special programming on the application side, and stops listening once the maximum is reached.

The NOLISTEN model is, by far, the simplest. The Internet daemon creates a process during cycle-up to CRAS or NORM state based on the configuration file. No additional processing takes place, although the ZINET functional messages will still apply and an operator may enter a ZINET STOP command to mark the server as inactivated. For the application server to reap the full benefit of this feature, it may call the inetd_getServerStatus() API of the Internet daemon. The function is in the CINET6 segment of the Internet daemon and may be compiled with any application server. Every time the server entry is cycled from inactive and active, a new process is created.

The last model to mention is the AOR model. No throttling is provided above the ECB create processing supported by the activate_on_receipt() socket API. An operator may still use the ZINET START and ZINET STOP entries to activate the application server upon Internet request.

Filters

According to Webster's dictionary, a filter is a device through which a liquid or gas can be passed through to separate out suspended matter. While the socket user exits provide a means for filtering socket-level connections, they do not offer the granularity needed for individual servers. In addition, during real-time processing, the only user exit offered for an Internet server is through the socket accept() API, which calls segment C542. Translated, this means TPF only supports a user exit for TCP sockets and, because User Datagram Protocol (UDP) uses socket datagrams, UDP does not have a user exit supported by the accept() function call. For example, suppose that we wanted to validate every tftp transaction that came into TPF without modifying the existing source code for tftp. Because tftp uses UDP, we would not be able to do so with the user exit. Besides, if we could, would we want to do the same for all the other Internet applications through the same user exit? Probably not. So what we need is a method of filtering requests without modifying the existing code that works.

A. How They Work

The simplest and, by far, the most common type of TCP/IP or UDP/IP filter is the UNIX tcpd utility. Originally written and compiled by Wietse Venema at Eindhoven University of Technology in the Netherlands in 1990, tcpd has grown to be a common tool found in many platforms. The source code and binaries are freeware that is available to anyone who wishes to use them without a fee. The TPF system does not support tcpd at this time, but the concepts still apply and may be used during the design of an Internet application that uses the TPF Internet daemon. The tcpd utility, also known as the TCP/IP daemon wrapper package, is an Internet server application invoked by the Internet daemon. The tcpd utility will perform whatever task is required (such as client validation, logging, and so on) and, in turn, will invoke the desired application server. It will act as a wrapper of the Internet server application.

B. Configuration

Another handy Internet daemon parameter that I have purposely neglected to mention until now is the PARAM optional keyword parameter of the Internet daemon configuration entry. This parameter specifies a parameter string to be passed to the Internet server application. This is somewhat uneventful considering that it is only a 1- to 8-alphanumeric character string passed to the Internet application through the argv variable of the C language main() function, but consider this: Suppose we place the real application server name in the PARAM optional keyword parameter and call the tcpd program from the Internet daemon instead. The tcpd program will be invoked on every Internet request and, in turn, will interrogate the argv variable of its main() function and call by name the real Internet application once it has finished processing. I can use this method for any server I currently have defined without modifying a single line of existing code. The best part is that it is not application specific. I can add as many Internet daemon entries to call tcpd and, in the PARAM field, use the real application segment name. The entry for the existing tftp server would be as follows:

ZINET ALTER S-TFTP PGM-TCPD PARAM-CTFT

C. Security and Miscellaneous

The tcpd utility provides a simple form of access control. Straight out of the package it provides the capability to look up client IP addresses and validate them against known valid users or known invalid users. Based on that information, the client program may be granted or refused access into the system. It also tries to eliminate the simplest form of remote host name, spoofing by validating the remote host name against a second known Domain Name Server (DNS). There is a long list of additional services provided by the tcpd utility that are outside the scope of this article. However, worth mentioning are systemwide access logging and status provided by the tcpd wrapper.

As with any design consideration, one of the drawbacks of using the tcpd method of calling Internet applications from the Internet daemon is that it will only be called once per server request. If the application server does not exit immediately after servicing each request, but instead attempts to handle new requests, the tcpd utility will not get a chance to validate the subsequent requests. This is the condition where server daemons, not the Internet daemon, listen on their own assigned ports for incoming requests.

Conclusion

Now that I am done taking this detour, I can go back to my original endeavor of designing a system status client/server application. I am free to design my application; and if I need additional processing for client validation or logging, I will be able to add it without a major rewrite.