[comp.protocols.appletalk] UDP Interface Specification

saf@CITI.UMICH.EDU (10/07/87)

					UDP DRIVER INTERFACE SPECIFICATION (Final Draft, 10/6/87)



ABOUT THE UDP DRIVER
--------------------

The UDP driver layer, one of the CITI MacIP drivers, implements the User Datagram 
Protocol [RFC 768].  This document describes the interface to UDP.

UDP DATA STRUCTURES
-------------------

The reader should be familiar with the common C derived types, such as those described in 
<sys/types.h>, <sys/time.h>, MPW C, and Inside Macintosh.

Clients are given the option of writing data from a character array or from a Write Data 
Structure (WDS).  The WDS is a "gather write" structure.  It specifies a list and ordering of  
buffers to write in a single operation.

Within the WDS, wds_index is an index into an array of buffer descriptors, pointing to the 
first buffer to write.  UDP clients must pass wds_index as 3 or more, and allocate the 
corresponding buffer descriptors.  The first three buffer descriptors will be used by lower 
level protocols for protocol headers.  Terminate the buffer descriptor array with a descriptor 
specifying length zero.

	typedef struct bd {	/* Buffer descriptor */
		unsigned short	bl;		/* Buffer length */
		Ptr				bp;		/* Buffer pointer */
	} bd_t, *bd_p;

	typedef struct wds {	/* Write data structure */
		unsigned long	wds_index;		/* Current descriptor index */
		bd_t 			wds_buffer[];	/* List of descriptors */
	} wds_t, *wds_p;

The following is a sample WDS.  wds_index is 3, so the first buffer descriptor is 
wds_buffer[3].  Descriptors wds_buffer[0], wds_buffer[1], and wds_buffer[2] 
will be used for lower layer protocol headers.  DATA LEN and DATA PTR are the length 
of and a pointer to the client's buffer.  This example shows the minimal WDS for UDP 
clients.

		+-----------------------+
		|            3          |	wds_index (long)
		+-----------------------+
		|                       |	buffer length #0 (word)
		+-----------------------+
		|                       |	buffer pointer #0 (pointer)
		+-----------------------+
		|                       |	buffer length #1 (word)
		+-----------------------+
		|                       |	buffer pointer #1 (pointer)
		+-----------------------+
		|                       |	buffer length #2 (word)
		+-----------------------+
		|                       |	buffer pointer #2 (pointer)
		+-----------------------+
		|        DATA LEN       |	buffer length #3 (word)
		+-----------------------+
		|        DATA PTR       |	buffer pointer #3 (pointer)
		+-----------------------+
		|           0           |	buffer length #4 (word)
		+-----------------------+
		|         UNUSED        |	buffer pointer #4 (pointer)
		+-----------------------+
		            .
		            .
		            .


Version information on the UDP driver is returned in the following 
structure:

	typedef struct udp_version {
		unsigned char	version[32];	/* Version number */
		unsigned char	specdesc[32];	/* Specification description */
		unsigned char	site[32];		/* Originating site */
	} udp_version_t, *udp_version_p;


If UDP is configured to collect statistics, that information is returned in the following 
structure (NOTE: this structure is not finalized!):

	typedef struct udp_stats {		/* Not yet defined */
		} udp_stats_t, *udp_stats_p;


UDP FUNCTIONS
-------------

The following functions provide a program interface to the UDP driver layer.  Each 
function returns success (0) or an error code.  Error code identifiers are defined in 
net_errno.h.  The return type for all functions is long.

UDP may notify clients of asynchronous events by executing a client-supplied notification 
routine.  Execution of the notification routine is called delivery of notification.  Clients are 
notified of an event if and only if they have specifically requested notification of that event.  
Clients request  and cancel notification of events by setting a mask and passing it to 
udp_request and udp_cancel, respectively.

Some functions accept io_timeout as a parameter.  For these routines, if io_timeout is 
NULL, the function blocks forever, or until the call can be completed.  If io_timeout is 
not NULL, the function blocks until the timeout value expires or the call can be completed.  
Implementation-dependent restrictions may apply as to when a client can block.  If it is 
illegal for a call to block, the error E_CANTBLOCK is returned.

Some functions accept (and in certain cases return) io_flags as a parameter.  io_flags is 
a long-word bitmask of control flags.  A list of all flags is given in "UDPJCONSTANTS."

Right and left arrows indicate values passed to and from the driver functions, respectively.


udp_create (io_stream, io_lport)
	<-	Ptr				*io_stream	UDP stream descriptor
	->	unsigned short	io_lport	Local UDP port

udp_create creates a UDP stream.  If io_lport is non-zero, the local port is set in 
io_stream, otherwise, a subsequent call to udp_setport must set the local port.  Once the 
local port is set, the stream can be used to send and receive datagrams.

Errors returned are:
	E_NOMEM
	E_PORTINUSE


udp_delete (io_stream)
	->	Ptr	io_stream	UDP stream descriptor

udp_delete deletes  a UDP stream.  Outstanding datagram buffers are deallocated and 
pending events are flushed.

Errors returned are:
	E_BADSTREAM


udp_setport (io_stream, io_lport)
	->	Ptr				io_stream	UDP stream descriptor
	->	unsigned short	*io_lport	Local UDP port

udp_setport sets the port for a UDP stream.  The UDP driver retains the binding of a 
stream to a port, so that incoming datagrams can be delivered to the proper stream and 
outbound datagrams show the correct address.  If io_lport is zero, the driver will assign 
an unused port.

Errors returned are:
	E_BADSTREAM
	E_PORTINUSE


udp_request (io_stream, io_nclass, io_notify, io_userdata, io_flags)
	->	Ptr				io_stream	UDP stream descriptor
	->	unsigned long	io_nclass	Set of events to notify on
	->	ProcPtr			io_notify	Notification routine
	->	unsigned long	io_userdata	Passed to notification routine
	->	unsigned long	io_flags	Control flags

udp_request sets up notification for a stream.  io_notify is a pointer to the client's 
notification routine.  io_userdata is passed to the client's notification routine.

io_nclass is the bitwise or of the notification identifiers to notify on.  So that clients may 
request to add to current notifications, io_nclass is bitwise ored to the existing bits.  
Values for io_nclass are defined in the section "UDPJNOTIFICATION."  When a UDP 
stream is created, the default value for io_nclass is UDP_NT_NONE (i.e., no notification).

Special behavior can be specified with io_flags.  The following flags are defined:

UDP_FLAG_NEWNOTIFY	io_notify should replace the previous io_notify.  Clients 
					may disable notification by passing NULL for io_notify 
					and setting this flag.  Notification may be re-enabled later by 
					setting IP_FLAG_NEWNOTIFY and io_notify .

UDP_FLAG_NEWUDATA	io_userdata should replace the previous io_userdata.

Errors returned are:
	E_BADSTREAM
	E_BADNOTIFICATION
	E_BADFLAG


udp_cancel (io_stream, io_nclass)
	->	Ptr				io_stream	UDP stream descriptor
	->	unsigned long	io_nclass	Events not to notify on

udp_cancel subtracts from the set of events for which the client accepts notification.  
io_nclass is the bitwise or of the notification identifiers to subtract, specified in 
"UDPJNOTIFICATION."

Errors returned are:
	E_BADSTREAM
	E_BADNOTIFICATION
	
	
udp_alloc (io_stream, io_buffer, io_buflen)
	->	Ptr				io_stream	UDP stream descriptor
	<-	Ptr				*io_buffer	Pointer to a datagram buffer
	->	unsigned long	io_buflen	Requested buffer length

udp_alloc allocates a UDP buffer, returning io_buffer, a pointer to a datagram buffer .

Errors returned are:
	E_BADSTREAM
	E_NOMEM


udp_free (io_stream, io_buffer)
	->	Ptr	io_stream	UDP stream descriptor
	->	Ptr	io_buffer	Pointer to a datagram buffer

udp_free frees a UDP datagram buffer.  io_buffer must point to a datagram buffer 
allocated by udp_alloc or udp_get.

Errors returned are:
	E_BADSTREAM
	E_BADPTR


udp_put (io_stream, io_buffer, io_buflen, io_fhost, io_fport, io_flags)
	->	Ptr				io_stream	UDP stream descriptor
	->	Ptr				io_buffer	Output buffer
	->	unsigned long	io_buflen	Buffer length (bytes)
	->	unsigned long	io_fhost	Destination host
	->	unsigned short	io_fport	UDP port on io_fhost
	->	unsigned long	io_flags	Control flags

udp_put sends a datagram on the stream specified by io_stream.  io_buffer is a 
datagram buffer.  If the flag UDP_FLAG_USEWDS is not set (see below), clients must allocate 
io_buffer by calling udp_alloc and free them by calling udp_free.

Before calling udp_put, the client must bind io_lport, either in udp_create or 
udp_setport.  The destination host and port, passed in io_fhost and io_fport, 
respectively, must be non-zero. 

Special behavior can be specified with io_flags.  The following flags are defined:

UDP_FLAG_MAKESUM	If set, a UDP checksum will be computed and included in 
					the UDP header of the outgoing datagram, otherwise the 
					checksum will be set to zero.

UDP_FLAG_USEWDS		If set, io_buffer is a pointer into a client-allocated WDS 
					(i.e., type wds_p).  The client must allocate the structure, 
					leaving room for lower layer protocol headers, as specified 
					in the section "UDPJDATAJSTRUCTURES."

					Note that if UDP_FLAG_USEWDS is set,  datagram buffers need 
					not be allocated and freed with udp_alloc and udp_free.  
					Also, io_buflen is ignored.

Errors returned are:
	E_BADSTREAM
	E_BADWDS
	E_BADFLAG
	E_NOMEM
	E_DTGTOOBIG
	E_CANTRESOLVEADDR
	E_HWWRITEERR


udp_get (io_stream, io_buffer, io_buflen, io_fhost, io_lhost io_fport, 	
		   io_lhost, io_timeout, io_flags)
	->	Ptr				io_stream	UDP stream descriptor
	<-	Ptr				*io_buffer	Input buffer
	<>	unsigned long	io_buflen	Input buffer length (bytes)
	<-	unsigned long	*io_fhost	Foreign host
	<-	unsigned short	*io_fport	UDP port on io_fhost
	<-	unsigned long	*io_lhost	Local host
	<-	unsigned short	*io_lport	UDP port on io_lhost
	->	struct timeval	*io_timeout	Timeout value
	<>	unsigned long	*io_flags	Control flags

udp_get requests a buffer from a UDP stream.  Note that io_buffer is allocated by the 
driver, but should be freed by the client (see udp_free).

If io_timeout is NULL, udp_get blocks until a datagram arrives.  If io_timeout is not 
NULL and a datagram is not available within the timeout period, udp_get returns an error.

Before calling udp_get, the client must bind io_lport, either in udp_create or 
udp_setport.

For the parameters io_fhost, io_fport, io_lhost, io_lport, and io_flags, the client 
may pass NULL if it does not need the returned values.

No values are currently defined for io_flags.

Errors returned are:
	E_BADSTREAM
	E_TIMEDOUT
	E_CANTBLOCK
	
	
udp_control (io_stream, io_buffer, io_buflen, io_control)
	->	Ptr				io_stream	UDP stream descriptor
	<>	Ptr				io_buffer	Data used by control call
	<>	unsigned long	*io_buflen	Size of io_buffer (bytes)
	->	unsigned long	io_control	Specifies control operation

udp_control performs various operations for a UDP stream.  io_control selects an 
operation and is the only mandatory parameter.  Parameters that are not required by 
individual control operations may be passed as NULL.

General errors returned by udp_control are:
	E_BADSTREAM
	E_BADCONTROL

Currently defined control operations are:

	UDP_CTL_VERSION
		->	io_stream	UDP stream descriptor
		<>	io_buffer	Pointer to udp_version_t structure
		->	io_control	Control operation

	Returns version information.  Clients pass a pointer to a structure of type 
	udp_version_t, as defined in the section "UDPJDATAJSTRUCTURES."

	No specific errors are returned for this control.


	UDP_CTL_STATS
		->	io_stream	UDP stream descriptor
		<>	io_buffer	Pointer to udp_stats_t structure
		->	io_control	Control operation

	No specific errors are returned for this control.


	UDP_CTL_PERM_STREAM
		->	io_stream	UDP stream descriptor
		->	io_control	Control operation

	This stream should never be deallocated by the system.

	No specific errors are returned for this control.


udp_task ()

Clients should call udp_task periodically to allow UDP time for asynchronous 
processing (e.g., to process incoming datagrams).

Errors returned are:
	E_CANTBLOCK


UDP NOTIFICATION
----------------

Clients may request and cancel notification of asynchronous events by calling 
udp_request and udp_cancel, respectively.  As asynchronous events occur, the 
notification routine io_notify is called with the following parameters:

(*io_notify)(io_stream, io_buffer, io_buflen, io_fhost, io_fport, 
			 io_lhost, io_lport, io_nclass, io_ndata, io_userdata)
	->	Ptr				io_stream
	->	Ptr				io_buffer
	->	unsigned long	io_buflen
	->	unsigned long	io_fhost
	->	unsigned short	io_fport
	->	unsigned long	io_lhost
	->	unsigned short	io_lport
	->	unsigned long	io_nclass
	->	unsigned long	io_ndata
	->	unsigned long	io_userdata

io_nclass is the type of event that caused this notification.  io_userdata was passed to 
udp_request by the client.  io_ndata contains additional specification for the event.

The following describes the valid notification classes (io_nclass):

	UDP_NT_DATA:  Data Arrival Notification
		->	io_stream
		->	io_fhost
		->	io_fport
		->	io_lhost
		->	io_lport
		->	io_nclass
		->	io_userdata

	Data arrival notification is delivered when a datagram arrives on io_stream, from 
	io_fport on io_fhost.

	UDP_NT_ERROR  Error Notification
		->	io_stream
		->	io_buffer
		->	io_buflen
		->	io_fhost
		->	io_fport
		->	io_lhost
		->	io_lport
		->	io_nclass
		->	io_ndata
		->	io_userdata

	The client is notified when an asynchronous error occurs, (e.g., destination unreachable 
	messages).  io_ndata identifies the error.  For all errors, an ICMP destination unreachable 
	datagram is returned in io_buffer.  io_buflen is the length of that datagram.  For more 
	information on ICMP, refer to [RFCJ792].

	Errors delivered are:
		E_NETUN
		E_HOSTUN
		E_PROTOUN
		E_PORTUN


UDP ERROR CODES
---------------

Following is a description of all possible error codes returned by UDP:

	E_NOMEM
		Not enough memory to perform operation.
	E_PORTINUSE
		Port number is already in use by another client.
	E_BADSTREAM
		Stream descriptor was not found in this driver's list of streams.
	E_BADNOTIFICATION
		Invalid notification class.
	E_BADFLAG
		Invalid control flag bit is set in io_flags.
	E_BADCONTROL
		Invalid control identifier.
	E_BADPTR
		Invalid pointer; could not verify that pointer points to valid data.
	E_BADWDS
		Invalid WDS structure or pointer.
	E_DTGTOOBIG
		Datagram is too long to be handled by this driver.
	E_CANTRESOLVEADDR
		Unable to determine the next destination IP address that leads 	to the 
		requested destination IP address.
	E_HWWRITEERR
		Hardware failed in writing datagram to network.
	E_CANTBLOCK
		Current context does not allow a blocking call.
	E_TIMEDOUT
		Could not perform operation within requested timeout period.