.H 2 "RPC/XDR SYSTEM FUNCTIONALITY"
This chapter dicusses testing concerns for the kernel level RPC and XDR
routines.  Because these routines are only called by the NFS layer
of the kernel (i.e. they are not directly callable by any user level
process), the discussion here will focus on meeting those requirements
of the PRD concerning RPC/XDR that are not discussed elsewhere in this
document.  The main emphasis here will be on meeting the branch coverage
goals as stated in the PRD.  It is assumed that once the coverage has
reached those goals, testing to increase branch coverage will stop, and 
only those areas which need to be especially reliable (noted below) will
receive any further attention.  Testing areas of reliability, recoverability,
and stress are assumed to be hit by the specific chapters discussing those
elements elsewhere in this document.  As much as possible, any test done
to increase code coverage will be put in the scaffold so as to be easily
reproducable.

RESPONSIBLE ENGINEER: Darren Smith

.sp 2
.H 3  "Dependencies on other tests"
.sp 1
The main method for obtaining branch flow numbers will be to run various
subsets of tests discussed elsewhere in this document.  As tests are
added to these areas, they will be run on a kernel with the appropriate
RPC/XDR routines compiled using the Branch Flow Analysis (BFA) tool to
measure any potential increase in coverage.
.sp 2
.H 4 "NFS Functional Tests"
.sp 1
The first BFA results will be obtained by running one pass of the
NFS Functional Test suite as described in chapter 13 of this document.  By
one pass we mean that all the tests shall complete successfully at least
once, not that the tests shall be run completely for 24 hours.  The tests
should be run with at least the node that has the BFA version of the
kernel acting as both a client and as a server.  These tests
should hit the basic functionality of the RPC/XDR code.  Note that this implies
that the NFS Functional tests can complete one pass successfully.
.sp 1
.nf
IMPLEMENT TIME: covered by functional tests
PERFORM TIME: 3 days
TYPE OF TEST: functional
EXPECTED OUTPUT:  The functional tests should complete correctly,
	the BFA data base should be updated, and the major functional
	areas of RPC/XDR should be covered.
.fi
.sp 2
.H 4  "NFS Stress Tests"
.sp 1
A subset of the NFS Stress tests will be used to hit those sections of the
RPC/XDR code which control buffer access by multiple clients/servers at once.
In particular, those tests which have concurrent access by multiple processes
from one machine, and those tests which have multiple clients accessing a
server will be run. The tests should be run with the system with the BFA
kernel as both client and server.  Again, this implies that these tests can
complete at least one pass succesfully.
.sp 1
.nf
IMPLEMENT TIME: covered by NFS stress tests.
PERFORM TIME: 3 days
TYPE OF TEST: stress
EXPECTED OUTPUT: Those areas of the code that control
	access by multiple processes should be covered,
	as shown by the BFA database file.
.fi
.sp 2
.H 3  "Increasing code coverage without triggers"
.sp 1
In addition to the above tests, there are certain conditions which can
be used to increase code coverage to acceptable levels, without requiring
any special kernel changes.  Those areas which in general are most likely
to increase the code coverage while also providing additional testing
are discussed here.
.sp 2
.H 4  "Interrupt NFSD"
.sp 1
Interrupting the NFS daemon (nfsd) will cause several paths to be hit,
including the exit paths and the routines which unregister the NFS
service.   This can be accomplished by an interactive script which prompts
the user to kill the nfsd program on the appropriate machine.
.sp 1
.nf
IMPLEMENT TIME: 0.5 days (to fit in scaffold, document, etc.)
PERFORM TIME: 0.25 days.
TYPE OF TEST: recovery??
EXPECTED OUTPUT: RPC/XDR should exit properly, allowing NFSD to exit
properly.
.fi
.sp 2
.H 4  "RPC Calling Errors"
.sp 1
A great deal of the RPC code deals with detecting various types of errors
that SHOULD never happen through any normal path  of the NFS code. Decoding
errors on the server side can easily be hit by writing special purpose test
programs to be used from the client side.  The server should be running the
BFA code.  In all of these cases, the client should check that the proper error
is returned.  It should be verified that after the following tests have
been executed, normal NFS/RPC transactions can still take place.  To do this,
it is suggested that the NFS functional tests be run after the tests listed
below.
The following is a list of some of these tests cases and the expected results.
As additional cases in this category are defined they will be added to this
list.
.sp 1
.nf
       ERROR CONDITION                      EXPECTED RESULT

1)     The incoming UDP packet contains     RPC timeout due to no reply.
	incomplete RPC header:
            a) less than 4 bytes. (ID)
	    b) less than 8 bytes. (DIRECTION)
            c) various combinations specified
               later that cause decoding
               errors in the RPC header.

2)     The "direction" field is	            RPC timeout due to no reply.
       "REPLY" instead of "CALL"          

3)     The RPC version number is not 2	    RPC timeout due to no reply.

4)     The RPC information is correct,      MSG_ACCEPTED, PROG_UNAVAIL.
       but the program number is not the
       NFS program number.

5)     The RPC information is correct,      MSG_ACCEPTED, PROG_MISMATCH
       but the NFS version number is 0.     

6)     The RPC information is correct,      MSG_ACCEPTED, PROC_UNAVAIL
       but the NFS procedure number is -1

7)     The RPC information is correct,      MSG_DENIED, AUTH_ERROR
       but the authorization type is
       AUTH_SHORT

8)     The RPC information is correct,      MSG_DENIED, AUTH_ERROR
       but the authorization type is
       AUTH_NULL and the NFS procedure
       is not RFS_NULL (0).

9)     The RPC/NFS headers correct, but     MSG_ACCEPTED, no RPC error
       NFS requests are caused to fail by   NFS generates an error message.
       having bad or missing NFS arguments 
.fi
.sp 1
.nf
IMPLEMENT TIME: 5 days
PERFORM TIME: 2 days
TYPE OF TEST: recovery
EXPECTED OUTPUT: RPC/XDR should return appropriate errors. (See above.)
.fi
.sp 2
.H 4  "RPC Replying Errors"
.sp 1
Just as the server side contains checks for various errors, the client
side also does.  However, to produce errors similar to those above 
implies writing a version of NFSD which would produce
error returns in a prescribed manner, and which would be executed in
place of the normal NFSD.  This daemon would essentially produce errors
from the list for the Server above, ranging from no reply to a
reply that had mangled data for the NFS return values.  While this is
possible, the value of the time spent is not clearly worthwhile.  
Therefore, this set of tests should only be done if necessary to meet
requirements for branch coverage as specified in the PRD.
.sp 1
.nf
IMPLEMENT TIME: 7 days.
PERFORM TIME: 2 days.
TYPE OF TEST: recovery??
EXPECTED OUTPUT: The client side should log appropriate errors, 
      but continue functioning correctly on further transmissions.
.fi
.sp 2
.H 3  "Triggers"
.sp 1
One way to increase branch coverage and to hit key spots is to use
"triggers" in the kernel to key some appropriate action in certain
circumstances.  While there are many areas that are important to hit,
the areas discussed here are those which will do the most to increase
branch coverage.  Unless triggers are necessary to meet branch coverage
requirements as stated in the PRD, these tests will not be implemented.
.sp 2
.H 4  "Xdrmbuf_inline()"
.sp 1
The xdrmbuf_inline() routine is used to check if there is enough space
left in the current mbuf to complete a set of operations.  If there is
not enough space, the code is written to "do it the hard way".  The
overwhelming majority of time there is enough space, and in many cases
it is guaranteed by higher levels of code.  However, should this routine
return a failure, normal operation should continue correctly, with no
errors.  Therefore a trigger to cause xdrmbuf_inline() to always fail
should be sufficient to cause a number of extra paths to be covered, and
at the same time test the backup mechanisms in the code.  To perform
this test the trigger should be enabled and one pass of the NFS functional
tests should be executed to a BFA kernel as both client and server.
.sp 1
.nf
IMPLEMENT TIME:  3 days.
PERFORM TIME: 2 days.
TYPE OF TEST: functional
EXPECTED OUTPUT: The system should perform normally.
.fi
.sp 2
.H 4  "M_get()"
.sp 1
The m_get() routine is an mbuf routine located in the kernel networking
architecture code.  It is called in several places both directly and
through the mclgetx() routine.
Should m_get() fail it
means that it was unable to allocate an mbuf, which usually means that it
was out of memory.  It should be possible to configure various amounts of
networking memory to cause this routine to fail at various times.  However,
due to the difficulty of reconfiguring memory, this approach would be both
very time consuming and tedious.  A better method is to have the m_getx()
routine fail randomly.  Over a period of time, the majority of cases that
call mclgetx() or mget() will get a failure.   Some method will need to
be developed which will only cause failures for RPC calls, and not normal
networking operation.
The trigger should be coded to cause this routine to fail at random times,
with how random being
a specified value.  To perform this test the trigger should be enabled and one
pass of the NFS functional tests should be executed to a BFA kernel as both
client and server. 
.sp 1
.nf
IMPLEMENT TIME: 4 days
PERFORM TIME: 2 days
TYPE OF TEST: recovery
EXPECTED OUTPUT: Different error messages logged with no panics.
DEPENDENCIES: As the m_get() routine is under the Peking groups' control,
	any work on this trigger would have to be coordinated with them.
.fi
.sp 2
.H 4  "m_get(), version 2"
.sp 1
As an alternative to the previous method, it might be better to have the
trigger at those places which we wish to be covered.  In this case a
trigger in mclgetx() plus triggers at the places calling m_get() directly
might be more appropriate.  Again, to perform this test the trigger should
be enabled and one pass of the NFS functional tests should be executed to a
BFA kernel as both client and server.
.sp 1
.nf
IMPLEMENT TIME: 3 days.
PERFORM TIME: 2 days.
TYPE OF TEST: Functional
EXPECTED OUTPUT: Various errors logged at appropriate times.
.fi
.sp 2
.H 3  "Important Modules and Code Reviews"
.sp 1
The modules listed below are the areas of the RPC/XDR code which are
of key importance and/or most prone to bugs.  These areas should be
subjected to the additional requirement that 100% of their code shall
either be hit by branch flow coverage or shall be verified as correct
by special code reviews/readings.  Further, as branch flow coverage is
being increased these functions should be given special attention, so
as to increase confidence in these routines.  Any code reviews done
on  these modules shall be done by at least two engineers besides those
responsible for the code.  The list below can be considered as a
priority order for these purposes.
.sp 1
.nf
       Module                    Description

       ku_fastsend()             Special routine to send UPD packets
                                 "fast" by doing its own routing, IP
                                 fragmentation, etc.

       ku_recvfrom(),            Routines which do kernel level sends
       ku_sendto()               and recvs.

       xdrmbuf_*                 XDR routines which manipulate mbufs

       clntkudp_callit()         Main RPC client routine which controls
                                 remote calls.

       svc_getreq()              Main RPC server routine which controls
                                 the decoding and dispatching of incoming
                                 RPC requests.
.fi
.sp 1
.nf
IMPLEMENT TIME: none
PERFORM TIME: 5 days (for code reading in addition to BFA testing).
TYPE OF TEST: Verification
EXPECTED OUTPUT:  Potential bugs found will be analyzed and fixed.
.fi
\"	version 8,	Wed Apr 29 16:58:01 MDT 1987
\" John A Dilley
.H 2 "User RPC/XDR Library"
The tests in this section are designed to exercise the functionality of
user-callable RPC (Remote Procedure Call) and XDR (eXternal Data
representation) functions.
The relevant source files are listed in Appendix 2 of the NFS PRD.
.sp 2
.H 3 "XDR Library Functional Tests"
.sp
.VL 10 0 1
.LI
RESPONSIBLE ENGINEER: Jason Zions
.LE
.sp
.P
Testing of the XDR routines can be simplified by making one assumption:
the Sun implementation, by definition, is correct.  I.e., no matter what the
Sun routines do, regardless of any protocol specifications, our ported code
must behave identically. To do otherwise, even to correct Sun bugs, will
make HP look incompatible.
.P
With this in mind, XDR testing becomes simple. A program,
.BR writer ,
is created. It creates an encoding (i.e. outbound) XDR stream, and calls each
XDR encoding routine several times with various arguments including corner
and error cases. The outbound stream is encoded data is directed to stdout.
.P
Another program,
.BR reader ,
is cloned from
.BR writer.
It expects the exact same data types in the exact same order they were
generated by
.BR writer ,
and expects that stream on stdin. It displays, on stdout, a printable
representation of the data as transmitted.
.P
The following four tests are run. These tests are run on a 300; SUN is
used as a generic name for a Sun host.
.AL 1 0 1
.LI
writer | reader > f1
.LI
writer | remsh SUN reader > f2
.LI
remsh SUN writer | reader > f3
.LI
remsh SUN "writer | reader" > f4
.LE
.P
The contents of files f1, f2, f3, and f4 must be identical for the test to
pass. The lines, if any, which differ easily determine the xdr routines
with defects.
.P
There are several exceptions to this scheme;
one is the routine
.IR xdr_opaque (),
which is defined only for the homogeneous case (in fact, only which encoded
the data with
.IR xdr_opaque ()
may decode it); this routine is tested with versions
of
.B writer
and
.B reader
for the case of 300-300 and Sun-Sun.
.P
Another is the stream positioning calls. Since these produce no visible
output, their correct behavior can only be deduced from directing the
xdr stream to and from files, and overwriting already-written data. A
version of the
.B writer
and
.B reader
programs can be used for this purpose.
.P
The
.IR xdr_void ()
routine takes no arguments and returns nothing; its correctness
must be verified by code read.
.P
Finally, the
.IR xdr_inline ()
routine is a decode-only routine, and must be tested separately. This can
be
done by using the
.B writer
program to create a stream, which is then read completely via the
.IR xdr_inline ()
routine. The results of this read are stuffed into a memory-resident
XDR stream, to which the
.B reader
program is applied. The four intersystem configurations displayed above should
be used to verify correct operation. Also, error cases should be checked as
well.
.P
Following is a reference list of all the XDR functions available:
.fi
.ta 10 30 50 70
.nf
    xdr_accepted_reply,	xdr_array,	xdr_authunix_parms,
    xdr_bool,	xdr_bytes,	xdr_callhdr,
    xdr_callmsg,	xdr_deskey,	xdr_double,
    xdr_enum,	xdr_fhandle,	xdr_fhstatus,
    xdr_float,	xdr_int,	xdr_long,
    xdr_opaque,	xdr_opaque_auth,	xdr_path,
    xdr_path,	xdr_pmap,	xdr_pmaplist,
    xdr_reference,	xdr_rejected_reply,	xdr_replymsg,
    xdr_short,	xdr_string,	xdr_u_int,
    xdr_u_long,	xdr_u_short,	xdr_union,
    xdr_void,	xdr_wrapstring,	xdrmem_create,
    xdrrec_create,	xdrrec_endofrecord,	xdrrec_eof,
    xdrrec_skiprecord,	xdrstdio_create.
.fi
\" .sp
\" The XDR test plan will be written by Jason Zions.
\" .H 4 xdr_accepted_reply
\" .H 4 xdr_array
\" .H 4 xdr_authunix_parms
\" .H 4 xdr_bool
\" .H 4 xdr_bytes
\" .H 4 xdr_callhdr
\" .H 4 xdr_callmsg
\" .H 4 xdr_deskey
\" .H 4 xdr_double
\" .H 4 xdr_enum
\" .H 4 xdr_fhandle
\" .H 4 xdr_fhstatus
\" .H 4 xdr_float
\" .H 4 xdr_int
\" .H 4 xdr_long
\" .H 4 xdr_opaque
\" .H 4 xdr_opaque_auth
\" .H 4 xdr_path
\" .H 4 xdr_pmap
\" .H 4 xdr_pmaplist
\" .H 4 xdr_reference
\" .H 4 xdr_rejected_reply
\" .H 4 xdr_replymsg
\" .H 4 xdr_short
\" .H 4 xdr_string
\" .H 4 xdr_u_int
\" .H 4 xdr_u_long
\" .H 4 xdr_u_short
\" .H 4 xdr_union
\" .H 4 xdr_void
\" .H 4 xdr_wrapstring
\" .H 4 xdrmem_create
\" .H 4 xdrrec_create
\" .H 4 xdrrec_endofrecord
\" .H 4 xdrrec_eof
\" .H 4 xdrrec_skiprecord
\" .H 4 xdrstdio_create

.H 3 "RPC Library Functional Tests"
.sp
.P
The RPC interface is divided into three layers; the tests are divided into
three corresponding sections.  This portion of the test plan discusses
the RPC testing in general terms.

.H 3 "RPC High Level Library Function Tests"
.sp
.VL 10 0 1
.LI
RESPONSIBLE ENGINEER: Jason Zions
.LE
.sp
These routines are found in the library /usr/lib/librpcsvc.a.  They
provide a higher-level interface to RPC; the RPC system itself
should be transparent to users at this level.  The routines
are used to determine various information about remote hosts and the
RPC system residing there.
.P
This layer consists of calls to the higher level RPC remote services:
.IR getrpcport (),
.IR havedisk (),
.IR rnusers (),
.IR rstat (),
.IR rusers (),
.IR rwall (),
.IR yppasswd ().
These calls simply activate the requested service on some remote
system, passing arguments in and receiving results back.
.P
Both the client and server interfaces will be tested. For each of the
client-side routines, simple test drivers will be written to pass
correct data to the server.
.P
A corresponding dummy server will also be written,
which simply accepts the arguments and dumps them into a file for later
verification. The dummy then returns correct data to the requester.
.P
The dummy servers should be registered on both a Sun and a 300.
The tests will verify that the routines behave as documented in the
reference pages and/or other relevant documentation.  The specific
reference pages of interest are
grpcport.3n, rnusers.3n, rstat.3n, rwall.3n, yppasswd.3n.
.sp 2
.H 4 getrpcport
.sp
.I getrpcport
(host, prognum, versnum, proto)
.sp
This test should invoke
.IR getrpcport ()
with various combinations of valid
and invalid hosts, program numbers, version numbers, and protocols.  It
should verify that illegal values are treated properly (eg. NULL, or
unknown protocol, etc).  It must verify that legal values are treated
correctly and the correct port number is returned.
.H 4 havedisk
.sp
.I havedisk
(host)
.sp
This test should invoke
.IR havedisk ()
with valid, invalid and illegal host names (including NULL).  It should
verify that illegal values are treated properly (ie. no core dumps) and
that for valid values the correct information is returned (ie. true for
hosts which have attached disks -- all but discless clients).
.H 4 rnusers
.sp
.I rnusers
(host)
.sp
This test should invoke
.IR rnusers ()
with valid, invalid and illegal host names (including NULL).  It should
verify that illegal values are treated properly (ie. no core dumps) and
that for valid values the correct information is returned (ie. the
number of users logged in on that system).
.H 4 rstat
.sp
.I rstat
(host, statp)
.sp
This test should invoke
.IR rstat ()
with valid, invalid and illegal host names (including NULL).  It should
verify that illegal values are treated properly (ie. no core dumps) and
that for valid values the correct information is returned (ie. the
statp structure is filled in with sensible values for the kernel data
structures).
.H 4 rusers
.sp
.I rusers
(host, up)
.sp
This test should invoke
.IR rusers ()
with valid, invalid and illegal host names (including NULL).  It should
verify that illegal values are treated properly (ie. no core dumps) and
that for valid values the correct information is returned (ie. the up
structure is filled in with valid information about the users logged in
on that system).
.H 4 rwall
.sp
.I rwall
(host, msg)
.sp
This test should invoke
.IR rwall ()
with valid, invalid and illegal host names (including NULL).  It should
verify that all values are treated properly, and that for valid host
names the message pointed to by msg is printed on all terminals logged
in on that system.  Note that this may interfere with, for example,
rlogin tests running at the time.
Care should be taken when running this test.
.H 4 yppasswd
.sp
.I yppasswd
(oldpass, newpw)
.sp
This test should invoke
.IR yppasswd ()
with valid and invalid oldpass values (including NULL).  It should
verify that the newpw information replaces the previous password only
when the oldpass is identical to the old password for the current user's
account.  Note that while this test is running it may not be possible
for tests which supply the password to log in to the current account.
Care should be taken when running this test.
.sp
This test will be written as part of the YP verification suite, not the
RPC/XDR suite.  This section merely serves as a reminder.

.H 3 "RPC Middle Level Library Function Tests"
.sp
.VL 10 0 1
.LI
RESPONSIBLE ENGINEER: Jason Zions
.LE
.sp
These routines are found in /lib/libc.a.
They are used to set up and make RPC calls.  The higher level routines
use these in most cases.  They provide the simplest interface to the RPC
system itself, and are all most users will need to register RPC servers
and make RPC calls.  At this level the only transport available is
UDP/IP.  Applications wishing to use other transports must use the lower
level routines.
.P
The tests at this level will involve a set of clients and corresponding
servers, registered on various machines at various addresses (including
corner and error cases), which pass varying amounts of information back
and forth.  Passed and returned data will be logged on both sides for
later verifications.
.P
The tests will verify all
.IR callrpc ()
and
.IR registerrpc ()
examples from the RPC Programming Guide, as well as corner and error
cases not included in the user documentation.
.H 4 callrpc
.sp
.I callrpc
(host, prog, vers, proc, inproc, in, outproc, out)
.sp
This test should invoke
.IR callrpc ()
with valid, invalid and illegal host names (including NULL).
It should verify that illegal values are treated properly (ie. no core dumps).
It should verify that with valid arguments the remote function is
executed.  The remote function should echo its arguments as its result;
verifying proper behavior will then be reduced to a strcmp between in
and out.  This test should verify that
.IR callrpc ()
returns the correct error values for illegal or incorrect
values of host, prog, vers and proc.
.H 4 registerrpc
.sp
.I registerrpc
(prog, vers, proc, name, inproc, outproc)
.sp
This routine is used to register procedure name with the portmapper.  It
should be tested with valid and invalid prog, vers, proc and name
arguments.  Some of the invalid arguments should be a zero procedure number.
It should be verified that with invalid arguments the
function returns -1.  With valid arguments it should return zero and
should have mapped the function with the portmapper.  It should be
verified that the function can be accessed and that the inproc and
outproc are used to serialize and deserialize the arguments and return
value.  

.H 3 "RPC Lower Level Library Function Tests"
.sp
.VL 10 0 1
.LI
RESPONSIBLE ENGINEER: Jason Zions
.LE
.sp
These routines are also found in /lib/libc.a.
They are used to directly access the RPC system for applications which
need to be able to control the transport or sockets they are using,
provide memory allocation facilities, do user authentication,
change the length of time for retransmissions and/or timeouts, etc.
Users are encouraged to use the higher level routines due to the
complexity of the underlying system with which this level interacts.
.P
A great deal of flexibility exists in these routines.  Since these
routines will now be supported, it will be necessary to write tests to
check all boundary and error cases, in addition to the more "normal"
usage patterns.  In fact, a bulk of the testing should be devoted to the
corner and error cases, since regular usage in the higher level tests as
well as in the RPC-specific commands will cover much of the
functionality of these routines.
.P
The first line of attack will be the porting of all sample programs
from the Sun "Remote Procedure Call Programming Guide," pages 9 through
33.  These routines exercise a wide range of functionality within RPC,
and will provide a good base of tests of the RPC subsystem.
At the time of this writing (April 24, 1987),
a number of these tests have already been
ported and executed.
.P
One good reason for implementing the examples as tests is customer
satisfaction.  Customers using RPC for the first time are likely to
start with the examples in the manual, and would be justifiably upset if
they did not work.  After the examples have been ported and verified,
the documentation group will be made aware of the changes which had to
be made due to syntax errors or other documentation type errors.  The
code required to make them good tests will not be included in the user
documentation.
.P
The second line of attack will be to write new tests for the boundary
and error cases not hit in the documentation examples, and for those
calls which do not have example programs in the RPC Programming Guide.
.P
The lower level routines will be split into two groups: those that need
to be tested, and those that would be nice to test.  The division is
determined by whether or not the routine is documented and what its
function is.  If it's not documented, then it will not be tested in the
first pass (it will only be tested if time remains at the end of the
project) -- users are not expected to make much use of these routines,
so the regular usage they get through the other routines should be
sufficient.  If the routine is documented but can be verified by a code
read much more easily than a separate test case, then it also will not
be tested unless extra implementation time exists.  This is usually the
case for very simple routines (for which writing a separate test case
seems like a waste of time), or very complex routines (for which writing
a separate test case would take longer than may be justified).  The
deferred tests section will be included at the end of this chapter.
.P
Following is a reference list of all the RPC functions available:
.ta 10 30 50 70
.nf
    _authenticate,	_seterr_reply,	_svcauth_null,
    _svcauth_short,	_svcauth_unix,	authnone_create,
    authunix_create,	authunix_create_default,
    clnt_broadcast,	clnt_pcreateerror,	clnt_perrno,
    clnt_perror,	clntraw_create,	clnttcp_create,
    clntudp_bufcreate,	clntudp_create,	get_myaddress,
    nfs_null,	pmap_getmaps,	pmap_getport,
    pmap_rmtcall,	pmap_set,	pmap_unset,
    registerrpc,	rpc_free,	rpc_malloc,
    svc_getreq,	svc_register,	svc_run,
    svc_sendreply,	svc_unregister,	svcerr_auth,
    svcerr_decode,	svcerr_noproc,	svcerr_noprog,
    svcerr_progvers,	svcerr_systemerr,	svcerr_weakauth,
    svcfd_create,	svcraw_create,	svctcp_create,
    svcudp_bufcreate,	svcudp_create,	xprt_register,
    xprt_unregister.
.fi
.bp
.H 4 authnone_create
.sp
.I authnone_create
()
.sp
This routine creates a void authentication handle.  It should be
verified that a valid (but empty) handle is returned.
.H 4 authunix_create
.sp
.I authunix_create
(host, uid, gid, len, aup_gids)
.sp
This routine creates a UNIX authentication handle.  It should be
verified that a valid handle is returned with the uid and gids correctly
encoded.
.H 4 authunix_create_default
.sp
.I authunix_create_default
()
.sp
This routine calls authunix_create with the appropriate arguments.
It should be verified that a valid handle is returned with the
uid and gids correctly encoded.
.H 4 clnt_broadcast
.sp
.I clnt_broadcast
(prog, vers, proc, inproc, in, outproc, out, eachres)
.sp
This routine is used to call an RPC function on all locally connected
hosts.  It should be tested similarly to
.IR callrpc (),
except for the eachresult functionality.  The same valid and invalid
cases should be tested; the echo function should also suffice here.
.H 4 clnt_call
.sp
.I clnt_call
(clnt, proc, inproc, in, outproc, out, tout)
.sp
This macro is used to call the remote procedure associated with the
client clnt.  It should be tested similarly to
.IR callrpc (),
since it provides similar functionality.
.H 4 clnt_destroy
.sp
.I clnt_destroy
(rh)
.sp
This macro is used to destroy a client RPC handle.  It should be
tested with valid and invalid client handles.  The result is dependent
upon the type of handle.  It should be verified that the private data
structures are correctly deallocated.
.H 4 clnt_freeres
.sp
.I clnt_freeres
(clnt, outproc, out)
.sp
This macro is used to free data allocated for a client RPC handle.
It should be verified that the data are correctly decoded by the outproc
into the data area pointed to by out.
.H 4 clnt_geterr
.sp
.I clnt_geterr
(clnt, errp)
.sp
This macro is used to copy the error information from a client RPC handle.
It should be verified that it correctly copies the error information
after several bad RPC calls.
.H 4 clnt_pcreateerror
.sp
.I clnt_pcreateerror
(msg)
.sp
This routine is used to print an error message to standard error
describing why a client RPC handle could not be created.  It should be
verified that the error message is prepended by the string msg and a colon.
.H 4 clnt_perrno
.sp
.I clnt_perrno
(stat)
.sp
This routine is used to print an error message to standard error
describing the error which last occurred.  It should be used after bad
calls to
.IR callrpc ().
.H 4 clnt_perror
.sp
.I clnt_perror
(clnt, msg)
.sp
This routine is used to print an error message to standard error
describing why an RPC call associated with the client clnt failed.
It should be used after bad calls to
.IR clnt_call ().
.H 4 clntraw_create
.sp
.I clntraw_create
(prog, vers)
.sp
This routine is used to create a toy RPC client for testing purposes.
It should be verified that the routine creates a client in the address
space of the caller.  It should be used in conjunction with the
.IR svcraw_create ()
function.
.H 4 clnttcp_create
.sp
.I clnttcp_create
(addr, prog, vers, sock, send, recv)
.sp
This routine is used to create a TCP RPC client.
It should be tested with valid, invalid and illegal values for addr,
prog, vers, sock, send and recv.
It should be verified that with valid arguments, the routine creates
a client which will communicate with the remote program prog, version
vers via socket sock.  Note sock is a return value parameter set to the
socket allocated for the client.  The test should verify that values of
zero for send and recv cause sensible values to be chosen (or at least
that the client and server can still communicate).
This test should be used with a server program that uses the
.IR svctcp_create ()
function.
.H 4 clntudp_bufcreate
.sp
.I clntudp_bufcreate
(addr, prog, vers, wait, sock, send, recv)
.sp
This function is used to create the udp client; it is called by
.IR clntudp_create (),
and is not meant to be used by itself, although a number of programs do
use it.  It allows the user to specify the send and recv buffer sizes.
It is not documented but it available for use.  Since it is
undocumented, it probably should not be tested on the first pass.
.H 4 clntudp_create
.sp
.I clntudp_create
(addr, prog, vers, wait, sock)
.sp
This routine is used to create a UDP RPC client.
It should be tested with valid, invalid and illegal values for addr,
prog, vers and wait.
It should be verified that with valid arguments, the routine creates
a client which will communicate with the remote program prog, version
vers via socket sock.  Note sock is a return value parameter set to the
socket allocated for the client.
This test should be used with a server program that uses the
.IR svcudp_create ()
function.
.H 4 get_myaddress
.sp
.I get_myaddress
(addr)
.sp
This routine is used to get the local host's IP address without calling the
.IR gethostbyname ()
function (and thereby using the Yellow Pages).  It should be verified
that this routine correctly returns the addr structure with the local
host's IP address and the port number of the portmapper (PMAPPORT).
.H 4 pmap_getmaps
.sp
.I pmap_getmaps
(addr)
.sp
This routine is used to interface to the portmap service.  It should be
tested with both valid and invalid addresses, addr.
This routine should return a list of all currently registered programs
on the host located at *addr.
.H 4 pmap_getport
.sp
.I pmap_getport
(addr, prog, vers, proto)
.sp
This routine is used to look up the port number of the given program
prog, version vers, using protocol proto.  It should be tested with valid
and invalid addr, prog, vers and proto values.  It should be verified
that the function returns either zero (for error cases) or the correct
port number of the remote service.
.H 4 pmap_rmtcall
.sp
.I pmap_rmtcall
(addr, prog, vers, proc, inproc, in, outproc, out, tout, port)
.sp
This routine is used to make a remote procedure call through the
portmapper.  It should be tested with valid and invalid values for addr,
prog, vers and proc.  It is not supposed to be used to make general
remote procedure calls, so the test for this function does not have to
be as extensive as the
.IR callrpc ()
and
.IR clnt_call ()
tests.
.H 4 pmap_set
.sp
.I pmap_set
(prog, vers, proto, port)
.sp
This routine is used to make a mapping for the program prog, version
vers, protocol proto.  It should be tested with illegal values for
prog, vers, proto and port.  In these cases, no mapping should be made and
.IR pmap_set ()
should return zero.  With valid arguments it should be verified that
.IR pmap_set ()
registers the triple on port number port.  This test could use
.IR pmap_get ()
to verify the mapping, if the portmapper is to be trusted.
.H 4 pmap_unset
.sp
.I pmap_unset
(prog, vers)
.sp
This routine is used to delete a mapping from the portmapper for the
program prog, version vers.  Note that it should delete
.B all
programs, regardless of protocol (according to the specification).  It
should be tested with valid and invalid values for prog and vers; it
should return one if it succeeds, zero if it fails.
.H 4 svc_destroy
.sp
.I svc_destroy
(xprt)
.sp
This macro is used to destroy the RPC service transport handle xprt.
It should be verified that the private data structures associated with
xprt are freed.  Other than that there should not be any visible changes.
.H 4 svc_freeargs
.sp
.I svc_freeargs
(xprt, inproc, in)
.sp
This macro is used to free data allocated to the transport handle,
xprt.  It should be verified that the macro returns zero when given bad
arguments, and that it correctly frees the data and returns one otherwise.
.H 4 svc_getargs
.sp
.I svc_getargs
(xprt, inproc, in)
.sp
This macro decodes the arguments associated with the transport handle,
xprt.  It should be verified that this macro correctly decodes the
arguments passed to it and returns one.  If invalid arguments are passed
to it, it should return a zero.
.H 4 svc_getcaller
.sp
.I svc_getcaller
(xprt)
.sp
This macro is used to get the network address of the caller associated with the
transport handle, xprt.  It should be verified that it returns the sockaddr_in
structure describing the return address of the client (calling) function.
.H 4 svc_getreq
.sp
.I svc_getreq
(rdfds)
.sp
This routine is designed to be used as a more flexible interface to
.IR select ()
than
.IR svc_run ()
will provide.  It should be verified that when passed a bitmask
describing file descriptors which
.IR select ()
has returned as readable, the function does not return until all of
them have been serviced.  It should be verified that it returns
immediately when passed a bitmask of zero.  It should be tested with a
bitmask which has bits set which do not correspond to readable file
descriptors.  In this case, no action should take place, the call should
simply return after servicing (or not, if in error) them all.
.H 4 svc_register
.sp
.I svc_register
(xprt, prog, vers, dispatch, proto)
.sp
This routine is used to register the program prog, version vers and
protocol proto with the portmapper; service routine dispatch is the
function which handles the service requests.  It should be verified
that if proto is zero, no mapping happens; if proto is nonzero then
prog,vers,proto is mapped to the port xprt->xp_port.  It should be
verified that the dispatch routine is in fact used to handle service
requests destined to the port,vers,proto triple.
.H 4 svc_run
.sp
.I svc_run
()
.sp
This routine is used by servers to loop forever accepting service
requests for the programs it has registered (by using
.IR svc_register (),
for example).  This should be trivial to test, since it takes no
arguments, and never returns!  It should be verified that the registered
services do in fact get invoked when the appropriate requests come in.
This test could easily be combined with the above test.
.H 4 svc_sendreply
.sp
.I svc_sendreply
(xprt, outproc, out)
.sp
This routine is used to send the results of an RPC call back to the
caller associated with the transport handle, xprt.  It should be
verified that it correctly responds to the caller using the XDR routine
outproc to encode the results.  This will likely be tested indirectly by
most of the other tests written; a separate test may not be needed
except perhaps for the boundary and error conditions.
.H 4 svc_unregister
.sp
.I svc_unregister
(prog, vers)
.sp
This routine is used to delete a mapping from the portmapper for the
program prog, version vers.  It
should be tested with valid and invalid values for prog and vers; it
should return one if it succeeds, zero if it fails to undo the mapping.
This is identical to the functionality provided by
.IR pmap_unset ().
.H 4 svcerr_auth
.sp
.I svcerr_auth
(xprt, why)
.sp
This routine is used by a service when RPC authentication fails.  It
should be verified that the client RPC call gets the appropriate error
back from its
.IR clnt_call ()
(or whatever it used).
.H 4 svcerr_decode
.sp
.I svcerr_decode
(xprt)
.sp
This routine is used by a service when RPC parameter decoding fails.
It should be verified that the client RPC call get the appropriate error
message back from its
.IR clnt_call ()
(or whatever) when this happens.
.H 4 svcerr_noproc
.sp
.I svcerr_noproc
(xprt)
.sp
This routine is used by a service when the RPC call is requesting a
procedure number not supported by the server.
It should be verified that the client RPC call get the appropriate error
message back from its
.IR clnt_call ()
(or whatever) when this happens.
.H 4 svcerr_noprog
.sp
.I svcerr_noprog
(xprt)
.sp
This routine is used called when an unregistered program is requested.
It is not used from servers, but from the
.IR svc_getreq ()
function.
It should be verified that the client RPC call get the appropriate error
message back from its
.IR clnt_call ()
(or whatever) when this happens.
.H 4 svcerr_progvers
.sp
.I svcerr_progvers
(xprt)
.sp
This routine is used called when an unregistered program version is requested.
It is not used from servers, but from the
.IR svc_getreq ()
function.
It should be verified that the client RPC call get the appropriate error
message back from its
.IR clnt_call ()
(or whatever) when this happens.
.H 4 svcerr_systemerr
.sp
.I svcerr_systemerr
(xprt)
.sp
This routine is used by a service after some non-RPC related system error
occurs (such as running out of memory, or not being able to open a file).
It should be verified that the client RPC call get the appropriate error
message back from its
.IR clnt_call ()
(or whatever) when this happens.
.H 4 svcerr_weakauth
.sp
.I svcerr_weakauth
(xprt)
.sp
This routine is used by a service when the authentication is
insufficient for the service.
It should be verified that the client RPC call get the appropriate error
message back from its
.IR clnt_call ()
(or whatever) when this happens.
.H 4 svcfd_create
.sp
.I svcfd_create
(fd, send, recv)
.sp
This routine is similar in function to
.IR svctcp_create ()
except that it takes any open UNIX file descriptor as its first
argument.  It returns a service transport.  It is not documented and is
not designed for general use by users, therefore it does not need to be
tested in the first pass.  Internally it's just a way to get to the
makefd_xprt routine, which is a static function.
.H 4 svcraw_create
.sp
.I svcraw_create
()
.sp
This routine is used to create a toy RPC service transport to be used
with the
.IR clntraw_create ()
routine.  It should be verified that this function returns a usable
transport handle, and perhaps that it is a buffer of memory in the
program's address space (this is not portable, however).
.H 4 svctcp_create
.sp
.I svctcp_create
(sock, send, recv)
.sp
This routine is used to create a TCP RPC service transport.  It should
be tested with valid and invalid values for sock, including the special
value RPC_ANYSOCK; in the latter case the RPC subsystem will choose
a socket for the transport handle.  If the socket is not already bound,
.IR svctcp_create ()
will bind it to an arbitrary port on the local machine.
With zero values for send and
recv, suitable (and usable/testable) defaults should be chosen.  The
port bound to should be verified to be the same as what sock was bound
to.  If sock was not bound then it can be
any port which is not in the reserved range (0-1023).
It should be verified that this transport handle can be used for data
transfers with a client RPC program.
.H 4 svcudp_bufcreate
.sp
.I svcudp_bufcreate
(sock, send, recv)
.sp
This routine is used by
.IR svcudp_create ()
to actually do the creation of the transport handle.  It is not
documented and is not supposed to be called by users.  Therefore, it
does not need to be tested in the first pass.
.H 4 svcudp_create
.sp
.I svcudp_create
(sock)
.sp
This routine is used to create a UDP RPC service transport.  It should
be tested with valid and invalid values for sock, including the special
value RPC_ANYSOCK; in the latter case the RPC subsystem will choose
a socket for the transport handle.  If the socket is not already bound,
.IR svcudp_create ()
will bind it to an arbitrary port on the local machine.
The
port bound to should be verified to be the same as what sock was bound
to.  If sock was not bound then it can be
any port which is not in the reserved range (0-1023).
It should be verified that this transport handle can be used for data
transfers with a client RPC program.  Note that since UDP is limited to
8 Kbytes of data, it is not possible to pass huge arguments or return
huge results.
.H 4 xprt_register
.sp
.I xprt_register
(xprt)
.sp
This routine is used to register a RPC service transport handle.  This
is not normally needed by service implementors.  It should be verified
that this function modifies the global bitmap
.I svc_fds
by adding the file descriptor of the transport handle.  It does not have a
return value, therefore testing will be limited to the above check.
.H 4 xprt_unregister
.sp
.I xprt_unregister
(xprt)
.sp
This routine is used to unregister a RPC service transport handle.  This
is not normally needed by service implementors.  It should be verified
that this function modifies the global bitmap
.I svc_fds
by removing the file descriptor of the transport handle.  It does not have a
return value, therefore testing will be limited to the above check.
.H 3 "Deferred RPC Lower Level Library Routines"
.sp
.VL 10 0 1
.LI
RESPONSIBLE ENGINEER: Jason Zions
.LE
.sp
.H 4 "Miscellaneous library routines"
.sp
.I _authenticate
(req, msg)
.br
.I _seterr_reply
(msg, err)
.br
.I _svcauth_null
()
.br
.I _svcauth_short
(req, msg)
.br
.I _svcauth_unix
(req, msg)
.sp
These functions are not documented and are only supposed to be used by other
internal functions.  There is no compelling need to document and test
them at this time.
.H 4 auth_destroy
.sp
.I auth_destroy
(auth)
.sp
This macro is used to destroy authentication information.
It should be tested with valid and invalid auth structures.
Since it indirectly executes the ah_destroy function, it should
be tested with a known (UNIX) authentication structure.  It would be
nice to test with other authentication structures, but this should be
done as a second pass.
.H 4 auth_marshall
.sp
.I auth_marshall
(auth, xdrs)
.sp
This macro is used to marshall authentication information.
It is not documented but it available for use.  Since it is
undocumented, it probably should not be tested on the first pass.
It should be tested with valid and invalid auth structures.
Since it indirectly executes the ah_marshall function, it should
be tested with a known (UNIX) authentication structure.  It is not clear
whether it will be worthwhile to verify that the authentication handle
is correctly marshalled into the xdrs structure.
.H 4 auth_nextverf
.sp
.I auth_nextverf
(auth)
.sp
This macro is used to run the next authentication.
It is not documented but it available for use.  Since it is
undocumented, it probably should not be tested on the first pass.
It should be tested with valid and invalid auth structures.
Since it indirectly executes the ah_nextverf function, it should
be tested with a known authentication structure.  Since both of the
known auth structures do nothing for nextverf, the "normal" case will
not be nearly as interesting as the error cases.
.H 4 auth_refresh
.sp
.I auth_refresh
(auth)
.sp
This macro is used to refresh authentication information.
It is not documented but it available for use.  Since it is
undocumented, it probably should not be tested on the first pass.
It should be tested with valid and invalid auth structures.
Since it indirectly executes the ah_refresh function, it should
be tested with a known (UNIX) authentication structure.  The only effect
of this macro should be to update the aup.aup_time field in the auth
structure.
.H 4 auth_validate
.sp
.I auth_validate
(auth, verfp)
.sp
This macro is used to validate authentication information.
It is not documented but it available for use.  Since it is
undocumented, it probably should not be tested on the first pass.
It should be tested with valid and invalid auth structures.
Since it indirectly executes the ah_validate function, it should
be tested with a known (UNIX) authentication structure.
.H 4 clnt_abort
.sp
.I clnt_abort
(rh)
.sp
This macro is used to abort a client call.
It is not documented but it available for use.  Since it is
undocumented, it probably should not be tested on the first pass.
Since it indirectly executes the cl_abort function, it should
Be tested with a known client op structure.  Since this is a NULL
function for all known client ops, it is very uninteresting.
.H 4 nfs_null
.sp
.I nfs_null
() {}
.sp
This routine is not documented nor used anywhere, but it is present in
the library.  It takes no arguments and returns no value.  There is no
reason to test it; a code read is sufficient: nfs_null() {}.
.H 4 rpc_free
.sp
.I rpc_free
(base)
.sp
This routine is used as a safe front-end to the
.IR free ()
memory allocation library call.  It is used by internal functions,
it is not documented and not designed to be accessed by users.
This function has already been tested by a code read.  An automated test
should not be necessary.
.H 4 rpc_malloc
.sp
.I rpc_malloc
(size)
.sp
This routine is used as a safe front-end to the
.IR malloc ()
memory allocation library call.  It is used by internal functions,
it is not documented and not designed to be accessed by users.
This function has already been tested by a code read.  An automated test
should not be necessary.
.H 4 svc_recv
.sp
.I svc_recv
(xprt, msg)
.sp
This macro is used to actually receive data on the transport handle,
xprt.  It calls the xp_recv function associated with the transport
handle, so behavior will differ for different types of data streams.  It
should be verified that it correctly receives datagrams for UDP streams
and it would be nice to verify that it receives TCP data as well.
This macro is not documented and is not intended to be called by users,
so this test does not have to be implemented in the first pass.
.H 4 svc_reply
.sp
.I svc_reply
(xprt, msg)
.sp
This macro is used to actually send the reply message on the transport handle,
xprt.  It calls the xp_reply function associated with the transport
handle, so behavior will differ for different types of data streams.  It
should be verified that it works correctly for UDP streams
and it would be nice to verify that it receives TCP data as well.
This macro is not documented and is not intended to be called by users,
so this test does not have to be implemented in the first pass.
.H 4 svc_stat
.sp
.I svc_stat
(xprt)
.sp
This macro is used to get the status of the transport handle,
xprt.  It calls the xp_stat function associated with the transport
handle, so behavior will differ for different types of data streams.  It
should be verified that it returns XPRT_IDLE for UDP streams.
and it would be nice to verify that it returns XPRT_IDLE for idle TCP
streams as well, but this would not be possible due to timing problems:
the test would have to know what the status is of pending TCP data.
This macro is not documented and is not intended to be called by users,
so this test does not have to be implemented in the first pass.
