The following strange things surfaced in the Sun NIS+ implementation
which I consider bugs (except maybe one; see below). These were observed
in Solaris 2.5.1 without any NIS+ patches applied. I don't know now many
have been fixed.

NIS+ client library can SEGV during nis_list(3)
-----------------------------------------------
If a client does an nis_list() on a table using callbacks, and the table is
empty (or is a link), the server returns two things: the callback returns
an NIS_PARTIAL error via cbproc_error_1() and the NIS_IBLIST procedure
itself returns an nis_result struct with a status of NIS_CBRESULTS _and_ a
copy of the table object. (Without the callback, the table object and the
NIS_PARTIAL error are returned together in the nis_result.) The NIS+
client code in libnsl seems to depend on this behavior and will SEGV if
it doesn't get it. For example, if the server returns an NIS_PARTIAL error
via callback but doesn't supply a copy of the table object via the
procedure result, it seems as though the code tries to dereference the
result->object.object_val pointer and explodes because
result->object.object_val is NULL. It should check result->object.object_len
first and signal an error instead of crashing.

It may be that the observed NIS_PARTIAL behavior is mandated by
documentation somewhere. This in itself is not unreasonable, however
the blind assumption that an NIS_PARTIAL status will _always_ be
accompanied by an object in the nis_result structure is a bug: the code
should check first and signal an error if result->object.object_len < 1
rather than crashing.

rpc.nisd doesn't abort directory removals correctly
---------------------------------------------------
The NIS+ server sometimes botches the removals of directories that contain
directories themselves. I.e. an nisrmdir on a directory that contains
tables or other objects is fine: everything in the directory will be
removed and the directory itself destroyed. But an nisrmdir on a directory
that contains a subdirectory will fail. It appears that rpc.nisd handles
removals thusly: the NIS_RMDIR procedure goes through the directory and
deletes each object it encounters, _until_ it encounters another directory.
If it finds no other directories, then the removal is completed, but if
if _does_ encounter a directory, it aborts the removal attempt and tries
to rollback all the other removals it did up to that point (presumeably
from its transaction log). However, if a removal is aborted, the rollback
doesn't necessarily work properly: if the directory contains tables, they
are not restored correctly -- the tables are put back but only the first
entry in each table is preserved.

(If you think about it, it's not possible to roll back the removal of
a table if too much time has passed between the table's creation and
its removal. After enough time has gone by, the server will prune its
transaction logs to remove log entries that have been propagated to all
servers. If you wait until all of the ADD_ENTRY records have been purged
from the transaction log and then remove the table, rolling back the
removal will be impossible: you can put back the table itself, but you
can't restore its contents since all the log entries related to the
population of the table are gone. What you can do is turn the
table removal into a 'soft removal' operation where the table itself is
actually kept around and the server just makes it look as though it's
been removed. Then actual deletion of the table file can then be
postponed until the removal action can be committed. This is what the
FreeBSD server does.)

Directory signatures don't work
-------------------------------
The NIS+ server in all Solaris releases up to and including 2.5.1
does not sign directory objects (and nis_cachemgr has been lobotomized
so that it doesn't complain). This is supposedly fixed in Solaris 2.6.
The FreeBSD rpc.nisd and nis_cachemgr handle this correctly. NOTE:
this means you must run nis_cachemgr with the -u flag on a FreeBSD
NIS+ client if there are Solaris 2.5.x servers on the network.

Some NIS+ utilities are insane
------------------------------
Some NIS+ utilities don't do proper sanity tests on the results
returned from the NIS+ client library, meaning that they sometimes
miss error conditions and try to grope around in nis_result structures
for objects that aren't there. nisls is one example. I'm not certain
how much of this is due to bugs in libnsl itself.


Server locator code sometimes takes too long to find servers on other subnets
-----------------------------------------------------------------------------
Supposing you have two servers and a client. The master server and the
client are on one subnet and the replica server is on a different subnet.
Now kill the rpc.nisd process on the master server. What's supposed to
happen is that the client will attempt to 'ping' both servers to see
which one responds the fastest and select that one (or at the very least
favor it over the others). If the master server is dead, there's no question
that the replica will appear to respond the fastest, and indeed the locator
code does eventually select the replica server. But it takes a long time
before it makes up its mind, usually on the order of about 5 seconds.
It should get a response from the replica and bind to it much faster than
this.

The NIS_UPDKEYS procedure is not implemented
--------------------------------------------
The Sun NIS+ implementation doesn't seem to use the NIS_UPDKEYS
procedure even though it's in the RPC protocol definition file (they
use nis_modify() instead). The FreeBSD server implements the procedure
on the odd chance somebody needs it. I'm not sure if this constitutes
a bug, but it seemed strange to me at any rate.


