18775 Formal protocol documentation needed
authorDavid Powell <david.e.powell@oracle.com>
Wed, 03 Aug 2011 13:07:44 -0700
changeset 760 5220578b3b77
parent 759 0aa521216e66
child 761 ffd45e0b2905
18775 Formal protocol documentation needed
.hgignore
usr/src/doc/Makefile.doc
usr/src/doc/manpage/man-rad.xml
usr/src/doc/rad-dev/Makefile
usr/src/doc/rad-dev/a-logistics.xml
usr/src/doc/rad-dev/a-protocol.xml
usr/src/doc/rad-dev/b-references.xml
usr/src/doc/rad-dev/c-concepts-data.xml
usr/src/doc/rad-dev/c-concepts-namespace.xml
usr/src/doc/rad-dev/macros.xsl
usr/src/doc/rad-dev/rad-devguide.xml
usr/src/lib/libradproto/common/protocol.x
--- a/.hgignore	Mon Aug 01 14:12:59 2011 -0700
+++ b/.hgignore	Wed Aug 03 13:07:44 2011 -0700
@@ -38,6 +38,7 @@
 ^usr/src/cmd/zmgr/zmgr$
 ^usr/src/doc/manpage/.*\.1m?$
 ^usr/src/doc/rad-dev/rad-devguide.html$
+^usr/src/doc/rad-dev/.*-proc.xml$
 ^usr/src/java/vpanels/java.policy$
 ^usr/src/java/vpanels/vp$
 ^usr/src/lib.*_jni/.*\.h
--- a/usr/src/doc/Makefile.doc	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/doc/Makefile.doc	Wed Aug 03 13:07:44 2011 -0700
@@ -28,14 +28,10 @@
 # The location of the DocBook XSL stylesheets to use.  Most systems
 # should provide a catalog which automatically maps from the
 # DOCBOOK_XSL URL to a local path.
-#
-# STYLESHEET would ideally be set to profile-docbook.xsl, but the
-# stylesheets shipped with Solaris are old and broken.  The effect
-# is that the STATUS variable, described below, doesn't work.
 
 DOCBOOK_XSL=	http://docbook.sourceforge.net/release/xsl/current
 
-STYLESHEET=	docbook.xsl
+STYLESHEET=	profile-docbook.xsl
 FO_XSL=		$(DOCBOOK_XSL)/fo/$(STYLESHEET)
 HTML_XSL=	$(DOCBOOK_XSL)/html/$(STYLESHEET)
 MAN_XSL=	$(DOCBOOK_XSL)/manpages/$(STYLESHEET)
@@ -43,8 +39,7 @@
 # The sections of the documentation that make comments intended for an
 # internal audience are given a status of "private".  Setting STATUS to
 # something other than "private" will cause those sections to be
-# eliminated from the generated output.  Currently broken (see
-# STYLESHEET comment, above.)
+# eliminated from the generated output.
 
 STATUS=	private
 DBOPTS=	\
@@ -58,10 +53,12 @@
 # We assume xsltproc, xmllint, and Apache fop are all in the user's
 # path.
 
-XSLTPROC=	xsltproc --xinclude --nonet $(DBOPTS)
+XSLTPROC=	xsltproc --xinclude --nonet
 XMLLINT=	xmllint --xinclude --postvalid --noout
+
+DBXSLTPROC=	$(XSLTPROC) $(DBOPTS)
 FOP=		fop
 
 # Commands
 
-XSLT.man = $(XSLTPROC) $(MAN_XSL) $<
+XSLT.man = $(DBXSLTPROC) $(MAN_XSL) $<
--- a/usr/src/doc/manpage/man-rad.xml	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/doc/manpage/man-rad.xml	Wed Aug 03 13:07:44 2011 -0700
@@ -519,7 +519,6 @@
         </para>
     </refsection>
 
-    <!-- Style sheets currently shipped misrender this section
     <refsection><title>Attributes</title>
 	<para>
 	    See <citerefentry>
@@ -548,7 +547,6 @@
 	    </tgroup>
 	</informaltable>
     </refsection>
-    -->
 
     <refsection><title>See Also</title>
     <para>
--- a/usr/src/doc/rad-dev/Makefile	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/doc/rad-dev/Makefile	Wed Aug 03 13:07:44 2011 -0700
@@ -25,16 +25,21 @@
 
 include ../Makefile.doc
 
+# Macro-processed files
+
+PROC=	a-protocol-proc.xml
+
 # Our primary source and output files
 
 SRCS=	rad-devguide.xml
+
 TXT=	$(SRCS:%.xml=%.txt)
 HTML=	$(SRCS:%.xml=%.html)
 PDF=	$(SRCS:%.xml=%.pdf)
 FO=	$(SRCS:%.xml=%.fo)
 EXAMPLES= api_example.h api_example_impl.c
 
-CLEAN_FILES += $(EXAMPLES) $(FO)
+CLEAN_FILES += $(EXAMPLES) $(FO) $(PROC)
 CLOBBER_FILES += $(TXT) $(HTML) $(PDF)
 
 # Targets.  Since some users may not have Apache fop installed, the
@@ -45,11 +50,13 @@
 examples:
 	$(ADRGEN) -c example.xml
 
-html:	examples
-	$(XSLTPROC) --stringparam generate.toc "book toc" -o $(HTML) $(HTML_XSL) $(SRCS)
+docbook: examples $(PROC)
 
-# The old Solaris stylesheets misrender FO variablelists.  This has
-# a noticeable effect on pdf output
+html: docbook
+	$(DBXSLTPROC) --stringparam generate.toc "book toc" -o $(HTML) $(HTML_XSL) $(SRCS)
+
+%-proc.xml: %.xml
+	$(XSLTPROC) -o $@ macros.xsl $<
 
 pdf: fo
 	$(FOP) $(FO) -pdf $(PDF) 2> /dev/null
@@ -57,8 +64,8 @@
 txt: fo
 	$(FOP) $(FO) -txt $(TXT) 2> /dev/null
 
-fo:	examples
-	$(XSLTPROC) -o $(FO) $(FO_XSL) $(SRCS)
+fo:	docbook
+	$(DBXSLTPROC) -o $(FO) $(FO_XSL) $(SRCS)
 
 # lint produces many benign errors due to older DocBook schemata not
 # allowing for use of XInclude.  The rest are meaningful.
--- a/usr/src/doc/rad-dev/a-logistics.xml	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/doc/rad-dev/a-logistics.xml	Wed Aug 03 13:07:44 2011 -0700
@@ -1,19 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
 <!--
-	PDL HEADER START
+  PDL HEADER START
 
-	Public Documentation License Notice
+  Public Documentation License Notice
 
-	The contents of this Documentation are subject to the Public
-	Documentation License Version 1.01 (the "License"); you may only
-	use this Documentation if you comply with the terms of this License.
-	A copy of the License is available at
-	http://www.opensolaris.org/os/community/documentation/license.
+  The contents of this Documentation are subject to the Public
+  Documentation License Version 1.01 (the "License"); you may only
+  use this Documentation if you comply with the terms of this License.
+  A copy of the License is available at
+  http://www.opensolaris.org/os/community/documentation/license.
 
-	PDL HEADER END
+  PDL HEADER END
 
-	Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+  Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 -->
 
 <appendix><title><command>rad</command> development</title>
@@ -70,11 +70,10 @@
 
 <varlistentry>
 <term><filename class='directory'>
-usr/src/cmd/rad
+usr/src/cmd/rad/daemon
 </filename></term>
 <listitem><para>
-The source code for rad.  Building here will build both rad and
-its modules.
+The source code for <command>rad</command>.
 </para></listitem>
 </varlistentry>
 
@@ -129,7 +128,8 @@
 usr/src/java/rad
 </filename></term>
 <listitem><para>
-The source code for the Java and JMX <command>rad</command> clients.
+The source code for the Java and <acronym>JMX</acronym>
+<command>rad</command> clients.
 </para></listitem>
 </varlistentry>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/doc/rad-dev/a-protocol.xml	Wed Aug 03 13:07:44 2011 -0700
@@ -0,0 +1,1331 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<!--
+  PDL HEADER START
+
+  Public Documentation License Notice
+
+  The contents of this Documentation are subject to the Public
+  Documentation License Version 1.01 (the "License"); you may only
+  use this Documentation if you comply with the terms of this License.
+  A copy of the License is available at
+  http://www.opensolaris.org/os/community/documentation/license.
+
+  PDL HEADER END
+
+  Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+-->
+
+<appendix xmlns:rm="rad-macros">
+<title><command>rad</command> binary protocol</title>
+
+<!--
+  While it's not a very traditional way to document binary protocols,
+  BNF might be a clearer way to communicate some of the optional
+  paths.  We should consider adding it as an addition to the textual /
+  diagrammatical description.
+-->
+
+<para>
+In addition to supporting multiple transports, <command>rad</command>
+is capable of talking different protocols.  The default (and currently
+only) protocol is a proprietary binary protocol designated
+<literal>rad</literal>.  This appendix documents version 1 of this
+protocol.
+</para>
+
+<section><title>Overview</title>
+    <para> 
+    The <literal>rad</literal> protocol is a bi-directional binary protocol
+    that operates over a single stream.  Communication in both directions
+    takes the form of discrete messages.  These messages are framed using
+    <acronym>RPC</acronym> record marking (See <quote>RECORD MARKING
+    STANDARD</quote> in <citation>RPC</citation>).
+    </para>
+
+    <para> 
+    The individual messages take the formats documented below.  Even though
+    <acronym>RPC</acronym> record marking permits skipping messages of
+    unknown format, both the client and the server are free to immediately
+    drop the connection when an invalid message is seen.
+    </para>
+
+    <para>
+    The <literal>rad</literal> protocol is built using
+    <citation>XDR</citation>, so for simplicity and clarity the
+    <acronym>XDR</acronym> primitive type names and syntax will be used
+    throughout this appendix.  For example:
+    </para>
+
+    <itemizedlist>
+    <listitem>
+    <quote><literal>FOO&lt;&gt;</literal></quote> would represent a
+    variable-length array of <literal>FOO</literal>s, communicated as
+    an <literal>unsigned int</literal> containing the size followed by
+    that number of <literal>FOO</literal>s.
+    </listitem>
+    <listitem>
+    <quote><literal>FOO[n]</literal></quote> would represent a
+    fixed-length array of a predetermined size, communicated only as
+    the <literal>n</literal> <literal>FOO</literal>s.
+    </listitem>
+    <listitem>
+    <quote><literal>FOO *</literal></quote> would represent an optional
+    value, communicated as a <literal>boolean</literal> value followed
+    by a <literal>FOO</literal> if and only if the
+    <literal>boolean</literal> value was true.
+    </listitem>
+    </itemizedlist>
+
+</section>
+
+<section><title>Common data formats</title>
+    <para>
+    There are a few types and concepts that appear repeatedly
+    throughout the <literal>rad</literal> protocol.  They are described
+    here.
+    </para>
+
+    <section id="op-data-def"><title>Operations</title>
+    <para>
+    The various operations one can perform against the server are
+    communicated with an operation code.
+    </para>
+
+    <rm:proto name="OP-CODE">
+	<rm:data field="op_code" size="4" type="int">
+	<rm:codedef label="operation" prefix="oc">
+	    <rm:code num="0" name="INVOKE" />
+	    <rm:code num="1" name="GETATTR" />
+	    <rm:code num="2" name="SETATTR" />
+	    <rm:code num="3" name="LOOKUP" />
+	    <rm:code num="4" name="DEFINE" />
+	    <rm:code num="5" name="LIST" />
+	    <rm:code num="6" name="SUB" />
+	    <rm:code num="7" name="UNSUB" />
+	</rm:codedef>
+	</rm:data>
+    </rm:proto>
+    </section>
+
+    <section id="error-data-def"><title>Errors</title>
+    <para>
+    Errors in the <literal>rad</literal> protocol are communicated by
+    an error code, and optionally structured error data.
+    </para>
+
+    <rm:proto name="ERROR-CODE">
+	<rm:data field="error_code" size="4" type="int">
+	<rm:codedef label="error" prefix="ec">
+	    <rm:code num="0" name="ok" />
+	    <rm:code num="1" name="object" />
+	    <rm:code num="2" name="nomem" />
+	    <rm:code num="3" name="notfound" />
+	    <rm:code num="4" name="priv" />
+	    <rm:code num="5" name="system" />
+	    <rm:code num="6" name="exists" />
+	    <rm:code num="7" name="mismatch" />
+	    <rm:code num="8" name="illegal" />
+	</rm:codedef>
+	</rm:data>
+    </rm:proto>
+    
+    <para>
+    For object-specific errors, <literal>EC-OBJECT</literal>, the
+    format of the structured data is defined by the object's interface
+    definition.  For the remainder, save for <literal>EC-OK</literal>
+    (which is defined for completeness, but should never appear in the
+    protocol), the format is defined during the initial connection
+    handshake.  See <xref linkend="proto-handshake" />.
+    </para>
+    </section>
+
+    <section id="time-data-def"><title>Time</title>
+    <para>
+    When a time needs to be represented in the <literal>rad</literal>
+    protocol, it is communicated as seconds and nanoseconds offset from
+    the epoch (January 1, 1970 UTC).  
+    </para>
+    
+    <para>
+    It is important to note that the accuracy of such time data is
+    determined by its context.  In most, if not all, cases, the full
+    nanosecond precision is only relevant when compared to time data
+    obtained from the same host.
+    </para>
+
+<rm:proto name="TIME-DATA">
+    <rm:data field="secs" size="8" type="hyper">
+	number of seconds
+    </rm:data>
+    <rm:data field="nsecs" size="4" type="int">
+	number of nanoseconds (<mathphrase>0 &le; nsec &le;
+	10<superscript>9</superscript></mathphrase>)
+    </rm:data>
+</rm:proto>
+    </section>
+
+    <section id="name-data-def"><title>Object names</title>
+    <para>
+    <command>rad</command> object names are structured, consisting of a
+    domain and one or more key-value pairs.  When an object name or
+    pattern needs to be represented in the <literal>rad</literal>
+    protocol, this structure is flattened to a canonical string
+    format.  This string format consists of the domain, followed by a
+    colon (':'), followed by comma-separated key-value pairs.  Each
+    key-value pair consists of the name, followed by an equals sign
+    ('='), followed by the value.
+    </para>
+
+    <para>
+    Because keys and values may contain the special characters '=' or
+    ',', a quoting algorithm is applied when constructing the string.
+    The following substitutions are applied to keys and values:
+    </para>
+
+    <table><title>Object Name Escaping</title>
+    <tgroup cols='2'>
+    <thead>
+    <row><entry>Plain Text</entry><entry>Escaped Text</entry></row>
+    </thead>
+    <tbody>
+    <row><entry>\</entry><entry>\S</entry></row>
+    <row><entry>,</entry><entry>\C</entry></row>
+    <row><entry>=</entry><entry>\E</entry></row>
+    </tbody>
+    </tgroup>
+    </table>
+
+    <para>
+    Note that under this transformation, backslashes are only found as
+    part of quoted characters, and commas and equals signs, when
+    present, always have their special meaning.  Object names that use
+    no special characters are passed through unchanged.  These facts
+    can be used to simplify parsing or preprocessing of
+    string-formatted object names.
+    </para>
+
+<rm:proto name="NAME-DATA">
+    <rm:data field="name" size="variable" type="string&lt;&gt;">
+	flattened object name
+    </rm:data>
+</rm:proto>
+
+    <example>
+    An object name in the domain <quote>com.example</quote> with the
+    following keys and values:
+
+    <informaltable>
+    <tgroup cols='2'>
+    <thead>
+    <row><entry>Key</entry><entry>Value</entry></row>
+    </thead>
+    <tbody>
+    <row><entry>directory</entry><entry>C:\</entry></row>
+    <row><entry>first,last</entry><entry>Doe,John</entry></row>
+    </tbody>
+    </tgroup>
+    </informaltable>
+
+    would be represented by the string
+    <quote>com.example:directory=C:\S,first\Clast=Doe\CJohn</quote>.
+    </example>
+    </section>
+
+    <section id="adr-data"><title><acronym>ADR</acronym> data</title>
+    <para>
+    Central to the <literal>rad</literal> protocol is the communication
+    of data defined by <acronym>ADR</acronym>.  Most
+    <acronym>ADR</acronym> primitives map directly to
+    <acronym>XDR</acronym> types:
+    </para>
+
+    <table>
+    <title>Primitive <acronym>ADR</acronym> to Wire Type Mapping</title>
+    <tgroup cols='2'>
+    <thead>
+    <row>
+    <entry><acronym>ADR</acronym> Type</entry>
+    <entry>Wire Type</entry>
+    </row>
+    </thead>
+    <tbody>
+    <row>
+    <entry>boolean</entry>
+    <entry><acronym>XDR</acronym> <literal>boolean</literal></entry>
+    </row>
+    <row>
+    <entry>integer</entry>
+    <entry><acronym>XDR</acronym> <literal>int</literal></entry>
+    </row>
+    <row>
+    <entry>uinteger</entry>
+    <entry><acronym>XDR</acronym> <literal>unsigned int</literal></entry>
+    </row>
+    <row>
+    <entry>long</entry>
+    <entry><acronym>XDR</acronym> <literal>hyper</literal></entry>
+    </row>
+    <row>
+    <entry>ulong</entry>
+    <entry><acronym>XDR</acronym> <literal>unsigned hyper</literal></entry>
+    </row>
+    <row>
+    <entry>float</entry>
+    <entry><acronym>XDR</acronym> <literal>float</literal></entry>
+    </row>
+    <row>
+    <entry>double</entry>
+    <entry><acronym>XDR</acronym> <literal>double</literal></entry>
+    </row>
+    <row>
+    <entry>string</entry>
+    <entry><acronym>XDR</acronym> <literal>string&lt;&gt;</literal></entry>
+    </row>
+    <row>
+    <entry>opaque</entry>
+    <entry><acronym>XDR</acronym> <literal>opaque&lt;&gt;</literal></entry>
+    </row>
+    <row>
+    <entry>password</entry>
+    <entry><acronym>XDR</acronym> <literal>string&lt;&gt;</literal></entry>
+    </row>
+    <row>
+    <entry>time</entry>
+    <entry><literal>TIME-DATA</literal>
+    (see <xref linkend="time-data-def" />)</entry>
+    </row>
+    <row>
+    <entry>name</entry>
+    <entry><literal>NAME-DATA</literal>
+    (see <xref linkend="name-data-def" />)</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+
+    <para>
+    Optional <acronym>ADR</acronym> data of any type is represented as
+    <acronym>XDR</acronym> optional data.
+    </para>
+
+    <rm:proto name="OPTIONAL-DATA">
+	<rm:data field="data" size="varies" type="ADR-DATA *">
+	    Optional encoded data
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    Array data is communicated as an <acronym>XDR</acronym> array of
+    the element data.  That is, it is represented by an
+    <acronym>XDR</acronym> <literal>unsigned int</literal> whose value
+    is the number of array elements, followed by that number of element
+    data.
+    </para>
+
+    <rm:proto name="ARRAY-DATA">
+	<rm:data field="elements" size="varies" type="ADR-DATA&lt;&gt;">
+	    array elements
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    Structure data is communicated by communicating each structure
+    field in the order they are defined.  This may consist of a mixture
+    of optional and non-optional data.
+    </para>
+
+    <rm:proto name="STRUCT-DATA">
+	<rm:data field="fields" size="varies" type="ADR-DATA[n]">
+	    fixed-length array of structure fields
+	    (n = type-defined field count)
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    Enumeration data is communicated as an <acronym>XDR</acronym>
+    <literal>unsigned int</literal> whose value is the 1-based index
+    into the list of enumerated values (i.e. 1 would be the first
+    enumerated value, n would be the nth enumerated value).  A value of
+    0 represents the fallback value.  For enumerations without a
+    fallback value, the 0 value is unused.
+    </para>
+
+    <rm:proto name="ENUM-DATA">
+	<rm:data field="value" size="4" type="unsigned int">
+	    0 if fallback, 1-based index otherwise
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    Union data is communicated as an <acronym>XDR</acronym>
+    <literal>unsigned int</literal> whose value is the 1-based index
+    into the list of union arms.  A value of 0 represents the default
+    arm.  When a non-default arm is selected, the arm is followed by
+    that arm's data.  When the default arm is selected, it is first
+    followed by the discriminant data value, and then is followed by
+    the default arm's data.
+    </para>
+
+    <rm:proto name="UNION-DATA (non default)">
+	<rm:data field="arm_index" size="4" type="unsigned int">
+	    1-based index into list of arms
+	</rm:data>
+	<rm:data field="arm_data" size="varies" type="ADR-DATA">
+	    Arm data
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="UNION-DATA (default)">
+	<rm:data field="arm_index" size="4" type="unsigned int">
+	    0
+	</rm:data>
+	<rm:data field="discriminant" size="4" type="ENUM-DATA | boolean">
+	    discriminant value
+	</rm:data>
+	<rm:data field="arm_data" size="varies" type="ADR-DATA">
+	    Arm data
+	</rm:data>
+    </rm:proto>
+
+    </section>
+
+    <!-- Consider switching this section and the previous section -->
+    <section><title><acronym>ADR</acronym> types</title>
+    <para>
+    As discussed in <xref linkend="adr-data" />, the
+    <acronym>ADR</acronym> data communicated by the
+    <literal>rad</literal> protocol has a structure determined by its
+    type.  Before that data can be communicated to the client, however,
+    the types themselves must be communicated.
+    </para>
+
+    <para>
+    For efficiency, type data is communicated using a system of type
+    spaces and type references.  A type space is an array of type
+    definitions that is referenced by a protocol-defined set of
+    consumers.  A consumer referring to a type will use a type
+    reference, which points to either a primitive type or to an element
+    of the type space.
+    </para>
+
+    <para>
+    Both type references and type spaces need to refer to the various
+    types.  They do this using an integral type code:
+    </para>
+
+    <rm:proto name="TYPE-CODE">
+	<rm:data field="type_code" size="4" type="int">
+	<rm:codedef label="type" prefix="tc">
+	    <rm:code num="0" name="void" />
+	    <rm:code num="1" name="boolean" />
+	    <rm:code num="2" name="integer" />
+	    <rm:code num="3" name="uinteger" />
+	    <rm:code num="4" name="long" />
+	    <rm:code num="5" name="ulong" />
+	    <rm:code num="6" name="float" />
+	    <rm:code num="7" name="double" />
+	    <rm:code num="8" name="time" />
+	    <rm:code num="9" name="string" />
+	    <rm:code num="10" name="opaque" />
+	    <rm:code num="11" name="password" />
+	    <rm:code num="12" name="name" />
+	    <rm:code num="13" name="enum" />
+	    <rm:code num="14" name="array" />
+	    <rm:code num="15" name="struct" />
+	    <rm:code num="16" name="union" />
+	</rm:codedef>
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    Concretely, a type reference consists of an XDR int whose value is
+    one of the above type constants.  If the type is an enum, array,
+    union, or struct, the type reference also includes an XDR int whose
+    value is an index into the current type space:
+    </para>
+
+    <rm:proto name="TYPEREF (basic type)">
+	<rm:data field="type_code" size="4" type="TYPE-CODE">
+	    a primitive type code
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="TYPEREF (derived type)">
+	<rm:data field="type_code" size="4" type="TYPE-CODE">
+	    <literal>TC-ENUM</literal>, <literal>TC-ARRAY</literal>,
+	    <literal>TC-STRUCT</literal>, or <literal>TC-UNION</literal>
+	</rm:data>
+	<rm:data field="type_index" size="4" type="int">
+	    type space index
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    A type space is a topologically sorted array of type definitions.
+    A derived type may only reference derived types defined earlier in
+    the type space.  That is, a type reference used by the type at
+    index <mathphrase>X</mathphrase> may only reference a primitive
+    type or a derived type a index less than
+    <mathphrase>X</mathphrase>.  Recursively defined types are not
+    supported.
+    </para>
+
+    <para>
+    Apart from a common distinguishing type code, each derived type is
+    defined differently.  Arrays are the simplest.  An array definition
+    consists of only a reference to the element type:
+    </para>
+
+    <rm:proto name="ARRAY-TYPE">
+	<rm:data field="type_code" size="4" type="TYPE-CODE">
+	    <literal>TC-ARRAY</literal>
+	</rm:data>
+	<rm:data field="element_type" size="varies" type="TYPEREF">
+	    the element type
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    A structure type definition consists of a name and an array of
+    field definitions.  The order in which the fields are specified in
+    <literal>STRUCT-TYPE</literal> is the order used to serialize the
+    fields in <literal>STRUCT-DATA</literal>.
+    </para>
+
+    <rm:proto name="FIELD-TYPE">
+	<rm:data field="name" size="varies" type="string&lt;&gt;">
+	    the field name
+	</rm:data>
+	<rm:data field="optional" size="4" type="boolean">
+	    is the field value optional?
+	</rm:data>
+	<rm:data field="type" size="varies" type="TYPEREF">
+	    the field type
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="STRUCT-TYPE">
+	<rm:data field="type_code" size="4" type="TYPE-CODE">
+	    <literal>TC-STRUCT</literal>
+	</rm:data>
+	<rm:data field="name" size="varies" type="string&lt;&gt;">
+	    the structure name
+	</rm:data>
+	<rm:data field="fields" size="varies" type="FIELD-TYPE&lt;&gt;">
+	    ordered list of structure fields
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    A union type definition consists of a name, a reference to the
+    discriminant type, optionally a default arm specification, and an
+    array of arm definitions.  The arm index referenced by
+    <literal>UNION-DATA</literal> is an index into the array of arms
+    defined by the corresponding <literal>UNION-TYPE</literal>.
+    </para>
+
+    <rm:proto name="ARM-TYPE">
+	<rm:data field="value" size="4" type="ENUM-DATA | boolean">
+	    the discriminant value that selects this arm
+	</rm:data>
+	<rm:data field="optional" size="4" type="boolean">
+	    is the arm's value optional?
+	</rm:data>
+	<rm:data field="type" size="varies" type="TYPEREF">
+	    the arm's type
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="UNION-TYPE (without default arm)">
+	<rm:data field="type_code" size="4" type="TYPE-CODE">
+	    <literal>TC-UNION</literal>
+	</rm:data>
+	<rm:data field="name" size="varies" type="string&lt;&gt;">
+	    the union name
+	</rm:data>
+	<rm:data field="disc_type" size="varies" type="TYPEREF">
+	    the discriminant type
+	</rm:data>
+	<rm:data field="hasdefault" size="4" type="boolean">
+	    false
+	</rm:data>
+	<rm:data field="arms" size="varies" type="ARM-TYPE&lt;&gt;">
+	    ordered list of arms
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="UNION-TYPE (with default arm)">
+	<rm:data field="type_code" size="4" type="TYPE-CODE">
+	    <literal>TC-UNION</literal>
+	</rm:data>
+	<rm:data field="name" size="varies" type="string&lt;&gt;">
+	    the union name
+	</rm:data>
+	<rm:data field="disc_type" size="varies" type="TYPEREF">
+	    the discriminant type
+	</rm:data>
+	<rm:data field="hasdefault" size="4" type="boolean">
+	    true
+	</rm:data>
+	<rm:data field="def_optional" size="4" type="boolean">
+	    is the default arm value optional?
+	</rm:data>
+	<rm:data field="def_type" size="varies" type="TYPEREF">
+	    the default arm type
+	</rm:data>
+	<rm:data field="arms" size="varies" type="ARM-TYPE&lt;&gt;">
+	    ordered list of arms
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    Lastly, an enum type definition consists of a name, an optional
+    fallback value, and a list of enumeration values.  The value index
+    referenced by <literal>ENUM-DATA</literal> is an index into the
+    array of values defined by the corresponding
+    <literal>ENUM-TYPE</literal>.
+    </para>
+
+    <rm:proto name="VALUE-TYPE">
+	<rm:data field="name" size="varies" type="string&lt;&gt;">
+	    the value's name
+	</rm:data>
+	<rm:data field="value" size="4" type="int">
+	    the value's assigned value
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="ENUM-TYPE">
+	<rm:data field="type_code" size="4" type="TYPE-CODE">
+	    <literal>TC-ENUM</literal>
+	</rm:data>
+	<rm:data field="name" size="varies" type="string&lt;&gt;">
+	    the enum name
+	</rm:data>
+	<rm:data field="fb_name" size="varies" type="string&lt;&gt; *">
+	    the fallback value's name, if one exists
+	</rm:data>
+	<rm:data field="values" size="varies" type="VALUE-TYPE&lt;&gt;">
+	    ordered list of values
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    The type space itself is an array.  Each element is one of these
+    four type definitions (<literal>ARRAY-TYPE</literal>,
+    <literal>STRUCT-TYPE</literal>, <literal>UNION-TYPE</literal>, or
+    <literal>ENUM-TYPE</literal>).
+    </para>
+
+    <rm:proto name="TYPESPACE">
+	<rm:data field="types" size="varies" type="?-TYPE&lt;&gt;">
+	    ordered list of types in the type space
+	</rm:data>
+    </rm:proto>
+
+    </section>
+
+    <section><title><acronym>API</acronym> definitions</title>
+    <para>
+    The ultimate description of the interactions permitted with a
+    particular object is its <acronym>API</acronym> definition.  An
+    <acronym>API</acronym> definition contains many elements: an
+    interface name, a list of versioned <acronym>API</acronym> names
+    the <acronym>API</acronym> supports, and definitions of the
+    <acronym>API</acronym>'s attributes, methods, and events.
+    </para>
+
+    <para>
+    Each <acronym>API</acronym> name has a set of stabilities and
+    versions:
+    </para>
+
+    <rm:proto name="STABILITY-CODE">
+	<rm:data field="stability_code" size="4" type="int">
+	<rm:codedef label="stability" prefix="sc">
+	    <rm:code num="1" name="private" />
+	    <rm:code num="2" name="uncommitted" />
+	    <rm:code num="3" name="committed" />
+	</rm:codedef>
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="VERSION-DATA">
+	<rm:data field="stability" size="4" type="STABILITY-CODE">
+	    stability version applies to
+	</rm:data>
+	<rm:data field="major" size="4" type="int">
+	    major version number
+	</rm:data>
+	<rm:data field="minor" size="4" type="int">
+	    minor version number
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="APINAME-DATA">
+	<rm:data field="api_name" size="varies" type="string&lt;&gt;">
+	    API name
+	</rm:data>
+	<rm:data field="versions" size="varies" type="VERSION-DATA&lt;&gt;">
+	    API versions by stability
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    An attribute consists of a name, stability, various flags, a type,
+    and separate, optional read and write error types.
+    </para>
+
+    <rm:proto name="ATTRIBUTE-TYPE">
+	<rm:data field="aname" size="varies" type="string&lt;&gt;">
+	    attribute name
+	</rm:data>
+	<rm:data field="stability" size="4" type="STABILITY-CODE">
+	    stability
+	</rm:data>
+	<rm:data field="readable" size="4" type="boolean">
+	    is attribute readable?
+	</rm:data>
+	<rm:data field="writable" size="4" type="boolean">
+	    is attribute writable?
+	</rm:data>
+	<rm:data field="optional" size="4" type="boolean">
+	    is attribute optional?
+	</rm:data>
+	<rm:data field="type" size="varies" type="TYPEREF">
+	    attribute type
+	</rm:data>
+	<rm:data field="read_error" size="varies" type="TYPEREF *">
+	    error data on read, if applicable
+	</rm:data>
+	<rm:data field="write_error" size="varies" type="TYPEREF *">
+	    error data on write, if applicable
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    A method looks a lot like an attribute.  It has a name, stability,
+    a result type, only a single optional error type, and an array of
+    argument definitions.
+    </para>
+
+    <rm:proto name="ARGUMENT-TYPE">
+	<rm:data field="argname" size="varies" type="string&lt;&gt;">
+	    argument name
+	</rm:data>
+	<rm:data field="optional" size="4" type="boolean">
+	    is argument optional?
+	</rm:data>
+	<rm:data field="type" size="varies" type="TYPEREF">
+	    argument type
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="METHOD-TYPE">
+	<rm:data field="mname" size="varies" type="string&lt;&gt;">
+	    method name
+	</rm:data>
+	<rm:data field="stability" size="4" type="STABILITY-CODE">
+	    stability
+	</rm:data>
+	<rm:data field="optional" size="4" type="boolean">
+	    is result optional?
+	</rm:data>
+	<rm:data field="result_type" size="varies" type="TYPEREF">
+	    result type
+	</rm:data>
+	<rm:data field="error" size="varies" type="TYPEREF *">
+	    error data, if applicable
+	</rm:data>
+	<rm:data field="args" size="varies" type="ARGUMENT-TYPE&lt;&gt;">
+	    arguments
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    An event consists only of a name, stability, and type.
+    </para>
+
+    <rm:proto name="EVENT-TYPE">
+	<rm:data field="ename" size="varies" type="string&lt;&gt;">
+	    method name
+	</rm:data>
+	<rm:data field="stability" size="4" type="STABILITY-CODE">
+	    stability
+	</rm:data>
+	<rm:data field="event_type" size="varies" type="TYPEREF">
+	    event type
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    Finally, an API definition combines all the above elements.
+    </para>
+
+    <rm:proto name="API-TYPE">
+	<rm:data field="ifname" size="varies" type="string&lt;&gt;">
+	    interface name (domain)
+	</rm:data>
+	<rm:data field="apis" size="varies" type="APINAME-DATA&lt;&gt;">
+	    API names and versions implemented
+	</rm:data>
+	<rm:data field="types" size="varies" type="TYPESET&lt;&gt;">
+	    Types used by API definition
+	</rm:data>
+	<rm:data field="attributes" size="varies" type="ATTRIBUTE-TYPE&lt;&gt;">
+	    API attributes
+	</rm:data>
+	<rm:data field="methods" size="varies" type="METHOD-TYPE&lt;&gt;">
+	    API methods
+	</rm:data>
+	<rm:data field="events" size="varies" type="EVENT-TYPE&lt;&gt;">
+	    API events
+	</rm:data>
+    </rm:proto>
+
+    </section>
+
+</section>
+<section id="proto-handshake"><title>Connection Initialization</title>
+    <para>
+    Once a connection has been established between a client and server,
+    a short synchronous handshake initiates the rad protocol.  The
+    server begins by sending a <literal>SERVER-HELLO</literal>
+    message.  This message specifies the minimum and maximum protocol
+    versions (inclusive) recognized by the server.
+    </para>
+
+    <rm:proto name="SERVER-HELLO">
+	<rm:data field="protocol" size="3" type="string[3]">
+	    <quote>RAD</quote>
+	</rm:data>
+	<rm:data field="min_ver" size="4" type="int">
+	    minimum supported version
+	</rm:data>
+	<rm:data field="max_ver" size="4" type="int">
+	    maximum supported version
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    The client then replies with a <literal>CLIENT-HELLO</literal>
+    message specifying the version it wishes to use.  This version may
+    not be less than the server's minimum version or greater than the
+    server's maximum version.
+    </para>
+
+    <rm:proto name="CLIENT-HELLO">
+	<rm:data field="protocol" size="3" type="string[3]">
+	    <quote>RAD</quote>
+	</rm:data>
+	<rm:data field="version" size="4" type="int">
+	    client-selected version
+	</rm:data>
+	<rm:data field="locale" size="varies" type="string&lt;256&gt;">
+	    client locale
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    Part of the <literal>rad</literal> protocol is the communication of
+    structured error data on request failures.  For consistency with
+    the object-specific errors that server-side objects are permitted
+    to return, the errors returned by rad when requests fail for other
+    reasons are also defined using <acronym>ADR</acronym>.  After the
+    server receives and accepts a <literal>CLIENT-HELLO</literal>
+    message, it replies with <literal>ERRORS</literal> to communicate
+    those type definitions:
+    </para>
+
+    <rm:proto name="ERRORS">
+	<rm:data field="error_space" size="varies" type="TYPESPACE">
+	    typespace containing error types
+	</rm:data>
+	<rm:data field="errors" size="varies" type="TYPEREF&lt;&gt;">
+	    errors types, starting with <literal>EC-NOMEM</literal>
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    The <literal>TYPEREF</literal>s refer to the types defined in the
+    <literal>error_space</literal> <literal>TYPESPACE</literal>.  The
+    types define the first <literal>error_count</literal> errors,
+    starting from the first non object-specific error,
+    <literal>EC-NOMEM</literal>.  Any errors for which types are not
+    defined have type <quote>void</quote>.
+    </para>
+
+    <!--
+      These errors are defined in ADR for convenience and for
+      architectural consistency.  However, from a interface perspective
+      they should be part of the protocol and documented here.
+    -->
+
+    <para>
+    At this point, the handshake is complete and normal client-server
+    communication can occur.
+    </para>
+</section>
+
+
+<section><title>Messages</title>
+    <para>
+    Normal communication consists of an asynchronous exchange of
+    messages: <literal>REQUEST</literal>s from the client to the
+    server, <literal>RESPONSE</literal>s from the server to the client,
+    and <literal>EVENT</literal>s from the server to the client.
+    </para>
+
+    <para>
+    A <literal>REQUEST</literal> is the <literal>rad</literal>
+    equivalent of a low-level remote procedure call.  It consists of a
+    client-selected, non-zero serial number, an operation code, and an
+    opaque, operation-specific, variable-length payload.
+    </para>
+
+    <rm:proto name="REQUEST">
+	<rm:data field="serial" size="8" type="hyper">
+	    client-specified serial number
+	</rm:data>
+	<rm:data field="opcode" size="4" type="OP-CODE">
+	    operation code (see <xref linkend="op-data-def" />)
+	</rm:data>
+	<rm:data field="payload" size="varies" type="opaque&lt;&gt;">
+	    request payload
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    The server will respond to every <literal>REQUEST</literal> with a
+    <literal>RESPONSE</literal>.  The structure of a
+    <literal>RESPONSE</literal> varies depending on whether the server
+    was successful in processing the client's request.  A
+    <literal>RESPONSE</literal> consists of the serial number of the
+    corresponding <literal>REQUEST</literal>, a boolean indicating
+    whether the request was successful, and either an
+    operation-specific opaque payload (in the case of success), or an
+    error code and an error-specific error payload (in the case of
+    failure):
+    </para>
+
+    <rm:proto name="RESPONSE (successful)">
+	<rm:data field="serial" size="8" type="hyper">
+	    serial number of REQUEST
+	</rm:data>
+	<rm:data field="success" size="4" type="boolean">
+	    true
+	</rm:data>
+	<rm:data field="payload" size="varies" type="opaque&lt;&gt;">
+	    response payload
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="RESPONSE (failure)">
+	<rm:data field="serial" size="8" type="hyper">
+	    serial number of REQUEST
+	</rm:data>
+	<rm:data field="success" size="4" type="boolean">
+	    false
+	</rm:data>
+	<rm:data field="error" size="4" type="ERROR-CODE">
+	    error code (see <xref linkend="error-data-def" />)
+	</rm:data>
+	<rm:data field="payload" size="varies" type="opaque&lt;&gt;">
+	    error payload
+	</rm:data>
+    </rm:proto>
+
+    <para>
+    The <literal>rad</literal> protocol doesn't require the client to
+    wait for a <literal>RESPONSE</literal> before sending another
+    <literal>REQUEST</literal>.  However, the server implementation may
+    place limits on the number of outstanding requests that can be
+    handled simultaneously.  A client with an outstanding
+    <literal>REQUEST</literal> must assume that a subsequent
+    <literal>REQUEST</literal> will block until the
+    <literal>RESPONSE</literal> from the outstanding
+    <literal>REQUEST</literal> is read.
+    </para>
+
+    <para>
+    Lastly, a client may (via a <literal>REQUEST</literal>) subscribe
+    to asynchronous event sources.  When an event occurs, the server
+    will send an <literal>EVENT</literal> message to the client.  An
+    <literal>EVENT</literal> message will include the object ID of the
+    source object (more later), the time of the event, the name of the
+    event, and an event-specific opaque payload.  An
+    <literal>EVENT</literal> message is distinguished from a
+    <literal>RESPONSE</literal> by having a serial number of 0.
+    </para>
+
+    <rm:proto name="EVENT">
+	<rm:data field="serial" size="8" type="hyper">
+	    0
+	</rm:data>
+	<rm:data field="source" size="8" type="hyper">
+	    id of generating object
+	</rm:data>
+	<rm:data field="sequence" size="8" type="hyper">
+	    sequence number of event
+	</rm:data>
+	<rm:data field="timestamp" size="12" type="TIME-DATA">
+	    time of event
+	</rm:data>
+	<rm:data field="name" size="varies" type="string&lt;&gt;">
+	    event name
+	</rm:data>
+	<rm:data field="payload" size="varies" type="opaque&lt;&gt;">
+	    event payload
+	</rm:data>
+    </rm:proto>
+
+</section>
+
+
+<section><title>Operations</title>
+    <para>
+    Each operation that a client can perform against a
+    <command>rad</command> server has its own request and response
+    payloads.  To facilitate processing without needing to fully decode
+    the payload, they are communicated as variable-lengthed
+    <literal>opaque</literal> data in the <literal>REQUEST</literal>
+    and <literal>RESPONSE</literal>.
+    </para>
+
+    <para>
+    For consistency and flexibility, all <acronym>ADR</acronym> data
+    referenced by these payloads is communicated as
+    <literal>OPTIONAL-DATA</literal>, which in turn is wrapped as
+    <literal>opaque</literal> data.
+    </para>
+
+    <rm:proto name="PAYLOAD-DATA">
+	<rm:data field="data" size="varies" type="opaque&lt;&gt;">
+	    encapsulated <literal>OPTIONAL-DATA</literal>
+	</rm:data>
+    </rm:proto>
+
+    <section><title>INVOKE</title>
+
+    <para>
+    INVOKE makes a method call against a <command>rad</command> object,
+    identified by its object ID.
+    </para>
+
+    <rm:proto name="INVOKE-REQUEST">
+	<rm:data field="objectid" size="8" type="hyper">
+	    Object ID, returned by lookup
+	</rm:data>
+	<rm:data field="mname" size="varies" type="string&lt;&gt;">
+	    the method to invoke
+	</rm:data>
+	<rm:data field="arguments" size="varies" type="PAYLOAD-DATA&lt;&gt;">
+	    array of method arguments
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="INVOKE-RESPONSE">
+	<rm:data field="result" size="varies" type="PAYLOAD-DATA">
+	    the return value of method call, if any
+	</rm:data>
+    </rm:proto>
+
+    <rm:errors op="INVOKE">
+	<rm:error code="EC-OBJECT">
+	    The method call was made but failed for an object-specific
+	    reason.
+	</rm:error>
+	<rm:error code="EC-NOTFOUND">
+	    <literal>objectid</literal> isn't a known object id, or the
+	    object doesn't have the method <literal>mname</literal>.
+	</rm:error>
+	<rm:error code="EC-MISMATCH">
+	    The wrong number of arguments were provided, or a
+	    non-optional argument was missing.
+	</rm:error>
+	<rm:error code="EC-NOMEM">
+	    The server had insufficient resources to complete the
+	    operation.
+	</rm:error>
+	<rm:error code="EC-SYSTEM">
+	    An unexpected internal error occurred.
+	</rm:error>
+    </rm:errors>
+
+    </section>
+
+    <section><title>GETATTR</title>
+
+    <para>
+    GETATTR reads an attribute of a <command>rad</command> object,
+    identified by its object ID.
+    </para>
+
+    <rm:proto name="GETATTR-REQUEST">
+	<rm:data field="objectid" size="8" type="hyper">
+	    Object ID, returned by lookup
+	</rm:data>
+	<rm:data field="aname" size="varies" type="string&lt;&gt;">
+	    the attribute to read
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="GETATTR-RESPONSE">
+	<rm:data field="result" size="varies" type="PAYLOAD-DATA">
+	    the value of the attribute
+	</rm:data>
+    </rm:proto>
+
+    <rm:errors op="GETATTR">
+	<rm:error code="EC-OBJECT">
+	    An attempt to read the attribute was made, but failed for
+	    an object-specific reason.
+	</rm:error>
+	<rm:error code="EC-NOTFOUND">
+	    <literal>objectid</literal> isn't a known object id, or the
+	    object doesn't have the attribute <literal>aname</literal>.
+	</rm:error>
+	<rm:error code="EC-ILLEGAL">
+	    <literal>aname</literal> refers to a write-only attribute.
+	</rm:error>
+	<rm:error code="EC-NOMEM">
+	    The server had insufficient resources to complete the
+	    operation.
+	</rm:error>
+	<rm:error code="EC-SYSTEM">
+	    An unexpected internal error occurred.
+	</rm:error>
+    </rm:errors>
+
+    </section>
+
+    <section><title>SETATTR</title>
+
+    <para>
+    SETATTR reads an attribute of a <command>rad</command> object,
+    identified by its object ID.  The response payload for a SETATTR
+    request is empty.
+    </para>
+
+    <rm:proto name="SETATTR-REQUEST">
+	<rm:data field="objectid" size="8" type="hyper">
+	    Object ID, returned by lookup
+	</rm:data>
+	<rm:data field="aname" size="varies" type="string&lt;&gt;">
+	    the attribute to write
+	</rm:data>
+	<rm:data field="value" size="varies" type="PAYLOAD-DATA">
+	    the new value of the attribute
+	</rm:data>
+    </rm:proto>
+
+    <rm:errors op="SETATTR">
+	<rm:error code="EC-OBJECT">
+	    An attempt to write the attribute was made, but failed for
+	    an object-specific reason.
+	</rm:error>
+	<rm:error code="EC-NOTFOUND">
+	    <literal>objectid</literal> isn't a known object id, or the
+	    object doesn't have the attribute <literal>aname</literal>.
+	</rm:error>
+	<rm:error code="EC-MISMATCH">
+	    <literal>aname</literal> has a non-optional value and
+	    <literal>value</literal> was NULL.
+	</rm:error>
+	<rm:error code="EC-ILLEGAL">
+	    <literal>aname</literal> refers to a read-only attribute.
+	</rm:error>
+	<rm:error code="EC-NOMEM">
+	    The server had insufficient resources to complete the
+	    operation.
+	</rm:error>
+	<rm:error code="EC-SYSTEM">
+	    An unexpected internal error occurred.
+	</rm:error>
+    </rm:errors>
+
+    </section>
+
+    <section><title>LOOKUP</title>
+
+    <para>
+    LOOKUP attempts to find the named object in the server's namespace,
+    returning the object and API IDs of the object if it exists.  Since
+    an object isn't usable until its API has been DEFINEed, the client
+    may request the API definition be provided as part of the LOOKUP
+    response.  For the same reason, the server may unilaterally decide
+    to provide the API definition if it believes the client hasn't seen
+    it yet.
+    </para>
+
+    <rm:proto name="LOOKUP-REQUEST">
+	<rm:data field="name" size="varies" type="NAME-DATA">
+	    object name
+	</rm:data>
+	<rm:data field="define" size="4" type="boolean">
+	    include object definition?
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="LOOKUP-RESPONSE">
+	<rm:data field="objectid" size="8" type="hyper">
+	    ID of the object
+	</rm:data>
+	<rm:data field="apiid" size="8" type="hyper">
+	    ID of the object's API
+	</rm:data>
+	<rm:data field="definition" size="varies" type="API-TYPE *">
+	    the definition of the object's API
+	</rm:data>
+    </rm:proto>
+
+    <rm:errors op="LOOKUP">
+	<rm:error code="EC-NOTFOUND">
+	    <literal>name</literal> doesn't exist.
+	</rm:error>
+	<rm:error code="EC-NOMEM">
+	    The server had insufficient resources to complete the
+	    operation.
+	</rm:error>
+	<rm:error code="EC-SYSTEM">
+	    An unexpected internal error occurred.
+	</rm:error>
+    </rm:errors>
+
+    </section>
+
+    <section><title>DEFINE</title>
+
+    <para>
+    DEFINE requests a definition of the specified API ID.
+    </para>
+
+    <rm:proto name="DEFINE-REQUEST">
+	<rm:data field="apiid" size="8" type="hyper">
+	    API ID
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="DEFINE-RESPONSE">
+	<rm:data field="definition" size="varies" type="API-TYPE">
+	    the definition of the API
+	</rm:data>
+    </rm:proto>
+
+    <rm:errors op="DEFINE">
+	<rm:error code="EC-NOTFOUND">
+	    <literal>apiid</literal> isn't a known
+	    <acronym>API</acronym> ID.
+	</rm:error>
+	<rm:error code="EC-NOMEM">
+	    The server had insufficient resources to complete the
+	    operation.
+	</rm:error>
+	<rm:error code="EC-SYSTEM">
+	    An unexpected internal error occurred.
+	</rm:error>
+    </rm:errors>
+
+    </section>
+
+    <section><title>LIST</title>
+
+    <para>
+    LIST requests an enumeration of all objects present in the server
+    that match the specified object name pattern.  The empty string
+    matches all server objects.
+    </para>
+
+    <rm:proto name="LIST-REQUEST">
+	<rm:data field="pattern" size="varies" type="NAME-DATA">
+	    object name pattern
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="LIST-RESPONSE">
+	<rm:data field="names" size="varies" type="NAME-DATA&lt;&gt;">
+	    the definition of the API
+	</rm:data>
+    </rm:proto>
+
+    <rm:errors op="LIST">
+	<rm:error code="EC-NOMEM">
+	    The server had insufficient resources to complete the
+	    operation.
+	</rm:error>
+	<rm:error code="EC-SYSTEM">
+	    An unexpected internal error occurred.
+	</rm:error>
+    </rm:errors>
+
+    </section>
+
+    <section><title>SUB and UNSUB</title>
+
+    <para>
+    SUB and UNSUB subscribe and unsubscribe, respectively, to the named
+    event of the specified object.  The response payload for a
+    successful SUB or UNSUB is empty.
+    </para>
+    
+    <para>
+    Note that it is possible to receive an <literal>EVENT</literal>
+    that has been UNSUBed after a successful UNSUB.
+    </para>
+
+    <rm:proto name="SUB-REQUEST">
+	<rm:data field="objectid" size="8" type="hyper">
+	    ID of the object
+	</rm:data>
+	<rm:data field="event" size="varies" type="string&lt;&gt;">
+	    event name
+	</rm:data>
+    </rm:proto>
+
+    <rm:proto name="UNSUB-RESPONSE">
+	<rm:data field="objectid" size="8" type="hyper">
+	    ID of the object
+	</rm:data>
+	<rm:data field="event" size="varies" type="string&lt;&gt;">
+	    event name
+	</rm:data>
+    </rm:proto>
+
+    <rm:errors op="SUB">
+	<rm:error code="EC-NOTFOUND">
+	    <literal>objectid</literal> isn't a known object id, or the
+	    object doesn't have the event <literal>event</literal>.
+	</rm:error>
+	<rm:error code="EC-EXISTS">
+	    The client is already subscribed to <literal>event</literal>.
+	</rm:error>
+	<rm:error code="EC-NOMEM">
+	    The server had insufficient resources to complete the
+	    operation.
+	</rm:error>
+	<rm:error code="EC-SYSTEM">
+	    An unexpected internal error occurred.
+	</rm:error>
+    </rm:errors>
+
+    <rm:errors op="UNSUB">
+	<rm:error code="EC-NOTFOUND">
+	    <literal>objectid</literal> isn't a known object id, the
+	    object doesn't have the event <literal>event</literal>, or
+	    the client isn't subscribed to <literal>event</literal>.
+	</rm:error>
+	<rm:error code="EC-NOMEM">
+	    The server had insufficient resources to complete the
+	    operation.
+	</rm:error>
+	<rm:error code="EC-SYSTEM">
+	    An unexpected internal error occurred.
+	</rm:error>
+    </rm:errors>
+
+    </section>
+
+</section>
+
+</appendix>
--- a/usr/src/doc/rad-dev/b-references.xml	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/doc/rad-dev/b-references.xml	Wed Aug 03 13:07:44 2011 -0700
@@ -1,19 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE bibliography PUBLIC "-//OASIS//DTD DocBook V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
 <!--
-	PDL HEADER START
+  PDL HEADER START
 
-	Public Documentation License Notice
+  Public Documentation License Notice
 
-	The contents of this Documentation are subject to the Public
-	Documentation License Version 1.01 (the "License"); you may only
-	use this Documentation if you comply with the terms of this License.
-	A copy of the License is available at
-	http://www.opensolaris.org/os/community/documentation/license.
+  The contents of this Documentation are subject to the Public
+  Documentation License Version 1.01 (the "License"); you may only
+  use this Documentation if you comply with the terms of this License.
+  A copy of the License is available at
+  http://www.opensolaris.org/os/community/documentation/license.
 
-	PDL HEADER END
+  PDL HEADER END
 
-	Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+  Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 -->
 
 <bibliography><title>References</title>
@@ -29,6 +29,19 @@
 </biblioentry>
 
 <biblioentry>
+<abbrev>RPC</abbrev>
+<copyright>
+    <year>1995</year>
+    <holder>The Internet Society</holder>
+</copyright>
+<editor>
+    <personname><firstname>R.</firstname><surname>Srinivasan</surname></personname>
+</editor>
+<title>RFC 1831</title>
+<subtitle>RPC: Remote Procedure Call Protocol Specification Version 2</subtitle>
+</biblioentry>
+
+<biblioentry>
 <abbrev>XDR</abbrev>
 <copyright>
     <year>2006</year>
--- a/usr/src/doc/rad-dev/c-concepts-data.xml	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/doc/rad-dev/c-concepts-data.xml	Wed Aug 03 13:07:44 2011 -0700
@@ -189,14 +189,15 @@
     <para>
     In some situations, data may be declared as optional.  Optional
     data is nullable, that is it can take on a "non-value" (e.g.
-    <symbol>NULL</symbol> in C, or <symbol>null</symbol> in Java).
-    Inversely, non-optional data cannot be NULL.  Only data of type
-    <type>opaque</type>, <type>string</type>, <type>password</type>,
-    <type>array</type>, or <type>structure</type> may be declared
-    optional.  Additionally, only <type>structure</type> fields and
-    certain API (see below) types can be optional.  Specifically,
-    <type>array</type> data cannot be optional (the <type>array</type>
-    type is actually more like a list than an array).
+    <literal>NULL</literal> in C, or <literal>null</literal> in Java).
+    Inversely, non-optional data cannot be <literal>NULL</literal>.
+    Only data of type <type>opaque</type>, <type>string</type>,
+    <type>password</type>, <type>array</type>, or
+    <type>structure</type> may be declared optional.  Additionally,
+    only <type>structure</type> fields and certain API (see below)
+    types can be optional.  Specifically, <type>array</type> data
+    cannot be optional (the <type>array</type> type is actually more
+    like a list than an array).
     </para>
 
     <para>
--- a/usr/src/doc/rad-dev/c-concepts-namespace.xml	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/doc/rad-dev/c-concepts-namespace.xml	Wed Aug 03 13:07:44 2011 -0700
@@ -1,19 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
 <!--
-	PDL HEADER START
+  PDL HEADER START
 
-	Public Documentation License Notice
+  Public Documentation License Notice
 
-	The contents of this Documentation are subject to the Public
-	Documentation License Version 1.01 (the "License"); you may only
-	use this Documentation if you comply with the terms of this License.
-	A copy of the License is available at
-	http://www.opensolaris.org/os/community/documentation/license.
+  The contents of this Documentation are subject to the Public
+  Documentation License Version 1.01 (the "License"); you may only
+  use this Documentation if you comply with the terms of this License.
+  A copy of the License is available at
+  http://www.opensolaris.org/os/community/documentation/license.
 
-	PDL HEADER END
+  PDL HEADER END
 
-	Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+  Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 -->
 
 <section><title>The <command>rad</command> Namespace</title>
@@ -173,11 +173,12 @@
 
     <note>
     <para>
-    Though all the <command>rad</command> clients support an
-    inconsistency in behavior between <literal>LIST</literal> and
-    <literal>DESCRIBE</literal>, the <command>rad</command> server
-    doesn't yet support publishing objects that aren't enumerated by
-    <literal>LIST</literal>.
+    These operations represent the most basic set of operations one
+    needs to discuss communication with a <command>rad</command>
+    server.  For efficiency, the <literal>rad</literal> protocol
+    further divides <literal>DESCRIBE</literal> into separate
+    <literal>LOOKUP</literal> and <literal>DEFINE</literal>
+    operations.
     </para>
     </note>
     </section>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/doc/rad-dev/macros.xsl	Wed Aug 03 13:07:44 2011 -0700
@@ -0,0 +1,118 @@
+<?xml version="1.0"?>
+<!--
+  Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+  
+  CDDL HEADER START
+  
+   The contents of this file are subject to the terms of the
+   Common Development and Distribution License (the "License").
+   You may not use this file except in compliance with the License.
+  
+   You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+   or http://www.opensolaris.org/os/licensing.
+   See the License for the specific language governing permissions
+   and limitations under the License.
+  
+   When distributing Covered Code, include this CDDL HEADER in each
+   file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+   If applicable, add the following below this CDDL HEADER, with the
+   fields enclosed by brackets "[]" replaced with your own identifying
+   information: Portions Copyright [yyyy] [name of copyright owner]
+  
+  CDDL HEADER END
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:rm="rad-macros">
+
+    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"
+	omit-xml-declaration="no"
+	doctype-public="-//OASIS//DTD DocBook V4.4//EN"
+	doctype-system="http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
+	/>
+
+    <!-- By default, pass everything through -->
+
+    <xsl:template match="node()|@*">
+	<xsl:copy>
+	    <xsl:apply-templates select="node()|@*" />
+	</xsl:copy>
+    </xsl:template>
+
+    <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'" />
+    <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
+
+    <!-- Creates a list of errors -->
+
+    <xsl:template match="rm:errors">
+	<para>
+	    <xsl:value-of select="@op" />
+	    <xsl:text> can fail for the following reasons:</xsl:text>
+	</para>
+	<variablelist>
+            <xsl:apply-templates select="rm:error" />
+	</variablelist>
+    </xsl:template>
+
+    <xsl:template match="rm:error">
+	<varlistentry>
+	    <term><literal><xsl:value-of select="@code" /></literal></term>
+	    <listitem><para><xsl:apply-templates /></para></listitem>
+	</varlistentry>
+    </xsl:template>
+
+    <!-- Creates a list of constants -->
+
+    <xsl:template match="rm:codedef">
+        <para><xsl:value-of select="@label" /><xsl:text> code:</xsl:text>
+        <variablelist spacing="compact">
+            <xsl:apply-templates select="rm:code" />
+	</variablelist></para>
+    </xsl:template>
+
+    <xsl:template match="rm:code">
+	<varlistentry>
+	    <term><xsl:value-of select="@num" /></term>
+	    <listitem><literal>
+		<xsl:value-of select="translate(../@prefix, $lower, $upper)"/>
+		<xsl:text>-</xsl:text>
+		<xsl:value-of select="translate(@name, $lower, $upper)" />
+	    </literal></listitem>
+	</varlistentry>
+    </xsl:template>
+
+    <!-- Creates a table out of a simple protocol definition -->
+
+    <xsl:template match="rm:proto">
+	<table><title><xsl:value-of select="@name" /></title>
+	    <tgroup cols='4'>
+		<colspec colnum="1" colwidth="2*" />
+		<colspec colnum="2" colwidth="1*" />
+		<colspec colnum="3" colwidth="2*" />
+		<colspec colnum="4" colwidth="4*" />
+		<thead>
+		    <row>
+			<entry>Field Name</entry>
+			<entry>Length</entry>
+			<entry>Type</entry>
+			<entry>Description</entry>
+		    </row>
+		</thead>
+		<tbody>
+		    <xsl:apply-templates select="rm:data" />
+		</tbody>
+	    </tgroup>
+	</table>
+    </xsl:template>
+
+    <xsl:template match="rm:data">
+	<row>
+	    <entry><literal><xsl:value-of select="@field" /></literal></entry>
+	    <entry><xsl:value-of select="@size" /></entry>
+	    <entry><literal><xsl:value-of select="@type" /></literal></entry>
+	    <entry><xsl:apply-templates /></entry>
+	</row>
+    </xsl:template>
+
+</xsl:stylesheet>
+
--- a/usr/src/doc/rad-dev/rad-devguide.xml	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/doc/rad-dev/rad-devguide.xml	Wed Aug 03 13:07:44 2011 -0700
@@ -1,19 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
 <!--
-	PDL HEADER START
+  PDL HEADER START
 
-	Public Documentation License Notice
+  Public Documentation License Notice
 
-	The contents of this Documentation are subject to the Public
-	Documentation License Version 1.01 (the "License"); you may only
-	use this Documentation if you comply with the terms of this License.
-	A copy of the License is available at
-	http://www.opensolaris.org/os/community/documentation/license.
+  The contents of this Documentation are subject to the Public
+  Documentation License Version 1.01 (the "License"); you may only
+  use this Documentation if you comply with the terms of this License.
+  A copy of the License is available at
+  http://www.opensolaris.org/os/community/documentation/license.
 
-	PDL HEADER END
+  PDL HEADER END
 
-	Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+  Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 -->
 
 <book xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -31,5 +31,7 @@
 
 	<xi:include href="a-logistics.xml" />
 
+	<xi:include href="a-protocol-proc.xml" />
+
 	<xi:include href="b-references.xml" />
 </book>
--- a/usr/src/lib/libradproto/common/protocol.x	Mon Aug 01 14:12:59 2011 -0700
+++ b/usr/src/lib/libradproto/common/protocol.x	Wed Aug 03 13:07:44 2011 -0700
@@ -69,7 +69,7 @@
 };
 
 struct resp_invoke {
-	argument *result;
+	argument result;
 };