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.