saf@CITI.UMICH.EDU.UUCP (04/09/87)
What follows is CITI's draft proposal for a TCP driver interface specification. Readers should be familiar with CITI's Driver Interface Guide, which appeared on this mailing list about a month ago. Address comments and questions to : apple_corps@citi.umich.edu A copy of this in word 3.0 with fancy fonts (symbol, palatino, courier) is available for anonymous FTP from citi.umich.edu. _______________________________________________________________________________ TCP Driver Interface Specification INTRODUCTION The TCP driver layer, part of the CITI MacIP driver, implements the Transmission Control Protocol [RFC 793]. This document describes the program interface to the TCP layer. Driver requests are made by preparing a driver parameter block and a protocol parameter block, and issuing a driver control call. The driver parameter block is described in [CITI MacIP]. DATA STRUCTURES The reader should be familiar with the common C derived types, such as those described in <sys/types.h>, MPW C, and Inside Macintosh [MAC]. All TCP datagrams are described by the TCP header [RFC 793] described below in C: typedef struct tcp_header { u_short tc_lport; /* Source port */ u_short tc_fport; /* Destination port */ u_long tc_seq; /* Sequence number of packet */ u_long tc_ack; /* Acknowledgement number of packet*/ u_short tc_thl : 4; /* Total header length (long-words) */ u_short tc_rsv : 6; /* Reserved */ u_short tc_flags : 6; /* Flag bits */ u_short tc_wnd; /* Window size for sender */ u_short tc_chksum; /* Packet checksum */ u_short tc_urg; /* Urgent data pointer */ } tcp_header_t, *tcp_header_p; For each TCP stream, a TCP client allocates a TCP parameter block, described as follows: typedef struct tcp_param { struct timeval * io_timeout; /* Timeout value */ caddr_t io_buffer; /* Pointer to data */ caddr_t io_buflen; /* Length of data in bytes */ caddr_t io_stream; /* Private TCP data */ u_long io_fhost; /* Destination IP address */ u_short io_fport; /* Destination TCP port */ u_short io_lport; /* Source TCP port */ Boolean io_furg; /* Urgent data flag */ Boolean io_fpush; /* Push data flag */ Boolean io_mark; /* At Mark */ Boolean io_lstasync; /* Listen asynchronously */ tcp_header_p io_tcph; /* Raw TCP header */ u_long io_nclass; /* Class of async notification */ u_long io_ndata; /* Notification data */ caddr_t io_notify; /* Notification routine */ u_long io_userdata; /* User data field */ } tcp_param_t, *tcp_param_p; TCP FUNCTIONS The following functions provide a program interface to the TCP driver layer. Each function has a single argument of type tcp_param_p and returns failure (-1) or success (non-negative). Error status should be examined by the client after each TCP driver call. All TCP functions except tcp_listen are synchronous. 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 non-NULL, the function blocks until the timeout value expires or the call can be completed. TCP notifies clients of asynchronous events by executing a client supplied notification routine. Right and left arrows indicate values passed to and from the driver functions, respectively. int tcp_open(tcp_pb) -> io_buffer -> io_buflen <- io_stream -> io_lport -> io_nclass -> io_notify -> io_userdata csCode TCP_OPEN_S tcp_open creates a TCP stream. If io_lport is non-zero, tcp_open binds the stream to port io_lport. Otherwise, the client must call tcp_setport. TCP clients may specify a receive buffer pointer io_buffer. io_buffer must be a non-relocatable block of size io_buflen. If io_buffer is NULL, TCP will allocate an internal receive buffer A client wishing asynchronous notification should pass the address of its notification routine in io_notify. io_userdata is client data passed by TCP to io_notify. io_nclass is the set of events for which the client accepts notification. It is constructed by taking the bitwise or of the notification identifiers specified under "TCP NOTIFICATION." int tcp_release(tcp_pb) -> io_stream csCode TCP_RELEASE_S tcp_release releases a TCP stream. Input and output buffers are freed and the port is unbound. If the stream is connected tcp_release aborts the connection. int tcp_setport(tcp_pb) -> io_stream -> io_lport csCode TCP_SETPORT_S tcp_setport binds a port to a TCP stream. If io_lport is zero TCP will assign an unused port. int tcp_connect(tcp_pb) -> io_timeout -> io_stream -> io_fhost -> io_fport csCode TCP_CONNECT_S tcp_connect attempts to connect to io_fhost on io_fport. If the connection can not be established in io_timeout TCP gives up. Note that the stream must have been previously bound to a port. Once established, connections may used send and receive data (with tcp_put and tcp_get). int tcp_listen(tcp_pb) -> io_timeout -> io_stream <> io_fhost <> io_fport -> io_lsnasync csCode TCP_LISTEN_S tcp_listen listens for connection requests on io_stream. If io_fport(io_fhost) is non-zero, connection requests are delivered only if they originate at the specified port(host). If io_lsnasync is FALSE, tcp_listen blocks until a connection request arrives. If no request arrives within io_timeout, tcp_listen returns an error. If a connection is established, the foreign host and port are returned in io_fhost and io_fport. If io_lsnasync is TRUE, tcp_listen enters a "listening" state and returns immediately. If TCP receives a connection request for io_stream, TCP notifies the client by running the notification routine (specified at tcp_open). int tcp_abort(tcp_pb) -> io_stream csCode TCP_ABORT_S tcp_abort aborts a connection. Any data in transit is lost. tcp_release should be called after tcp_abort to reclaim buffer space. int tcp_close(tcp_pb) -> io_timeout -> io_stream csCode TCP_CLOSE_S tcp_close negotiates the termination of a connection. All outstanding data is delivered -- i.e., clients may continue to call tcp_get until all input buffers are read. If TCP cannot negotiate the close within io_timeout, an error is returned, but TCP continues to negotiate the close. Clients may call tcp_release after tcp_close to reclaim buffer space. int tcp_put(tcp_pb) -> io_buffer -> io_buflen -> io_stream -> io_furg -> io_fpush csCode TCP_PUT_S tcp_put sends io_buflen bytes of io_buffer on io_stream. The io_fpush and io_furg flags correspond to the "data stream push" and "urgent data signalling" facilities of TCP; see [RFC 793]. tcp_put returns immediately; the TCP driver schedules actual data delivery. int tcp_get(tcp_pb) -> io_timeout <> io_buffer <> io_buflen -> io_stream <- io_furg <- io_mark csCode TCP_GET_S tcp_get requests data on a TCP stream. io_buffer points to a client supplied buffer. io_buflen specifies the length of that buffer in bytes. tcp_get blocks until one of the following conditions occurs: > io_timeout expires. No data is returned. > urgent data is outstanding. All available data is returned (up to io_buflen). io_furg is set. > io_buflen bytes are available. io_buflen bytes are returned. On return, if io_furg is TRUE, there is outstanding urgent data on io_stream. The client should "urgently" read data from TCP until all urgent data has been read. tcp_get sets io_mark TRUE when the last of the urgent data was "gotten." TCP will not deliver both urgent and non-urgent data in the same buffer. int tcp_task() csCode TCP_TASK_S tcp_task allots time to TCP for asynchronous processing. int tcp_request(tcp_pb) -> io_stream -> io_nclass csCode TCP_REQUEST_S tcp_request adds to the set of events for which the client accepts notification. io_nclass is the bitwise or of the notification identifiers specified under "TCP NOTIFICATION." int tcp_cancel(tcp_pb) -> io_stream -> io_nclass csCode TCP_REQUEST_S tcp_cancel subtracts from the set of events for which the client accepts notification. int tcp_control(tcp_pb) <>io_buffer <>io_buflen -> io_stream csCode TCP_CONTROL_S To be specified. TCP NOTIFICATION Clients may specify asynchronous events to be notified of by specifying io_notify during tcp_open and by calling tcp_request and tcp_cancel. Later, as asynchronous events occurr, io_notify is called as follows: int (*io_notify)(tcp_pb) -> io_buflen -> io_stream -> io_fhost -> io_fport -> io_nclass -> io_ndata -> io_userdata io_nclass is the type of event that caused this notification. io_userdata was passwed to tcp_request by the client. io_ndata contains additional specification for the event. Notification routines execute in the driver's context, which is implementation dependent. The notification routine should assume that a5 is not pointing to its globals, no global variables can be accessed and no other routines may be called. The following describes the valid notification classes (io_nclass). TCP_NT_CONNECT Connection Notification -> io_stream -> io_fhost -> io_fport -> io_nclass -> io_userdata Connection notification is delivered when a connection is established with io_fhost on io_fport. To receive connection notification, the client must be "listening" for connections (see tcp_listen). TCP_NT_DATA Data Arrival Notification -> io_buflen -> io_stream -> io_fhost -> io_fport -> io_nclass -> io_userdata Data arrival notification is delivered when a data segment arrives from io_fport on io_fhost. io_buflen is the number of bytes in the segment. TCP_NT_URGENT Urgent Data Notification -> io_stream -> io_fhost -> io_fport -> io_nclass -> io_userdata Urgent data notification is delivered when there is outstanding urgent data somewhere in the stream. The notification is delivered just once -- when the foreign host first puts urgent data in the stream. Once all urgent data has been read by the local host, TCP will again be ready to deliver urgent data notification. TCP_NT_RETRANS Retransmit Notification -> io_stream -> io_fhost -> io_fport -> io_nclass -> io_userdata The client is notified when TCP retransmits data destined for io_fport on io_fhost. TCP_NT_CLOSING Closing Notification -> io_stream -> io_fhost -> io_fport -> io_nclass -> io_ndata -> io_userdata The client is notified when the foreign host begins negotiating a close a connection with io_fhost on io_fport. TCP_NT_CLOSED Closed Notification -> io_stream -> io_fhost -> io_fport -> io_nclass -> io_userdata The client is notified when the connection with io_fhost on io_fport has been gracefully closed. TCP_NT_ERROR Error Notification -> io_stream -> io_fhost -> io_fport -> io_nclass -> io_ndata -> io_userdata The client is notified when an asynchronous error, such as connection reset, occurs. io_ndata identifies the error. References [CITI MacIP] "Mac IP Driver Interface Guide" Center For Information Technology Integration, University of Michigan, Ann Arbor, MI, March 1987. [CITI TCP] "TCP Driver Interface Specification" Center For Information Technology Inte- gration, University of Michigan, Ann Arbor, MI, March 1987. [MAC] Inside Macintosh, Vols I-III, Addison-Wesley, Reading, MA, November 1985. [RFC 793] J. Postel (ed.), "Transmission Control Protocol" RFC 793, SRI International, Men- lo Park, CA, December 1985.