___________________ TCPDRV Version 2.01 Preliminary Specification for a TCP/IP Application Binary Interface (ABI) to run over MS-DOS. Copyright (c) 1992 by Peter R. Tattam, University of Tasmania. Permission is granted to reproduce and distribute this document without restriction or fee. This document may be re-formatted or translated, but the functional specification of the programming interface described herein may not be changed without the author's permission. The author's name and this notice must appear on any reproduction of this document. ____________ Introduction There has been a need for a standard TCP/IP binary interface for the MS-DOS operating system. Although there are many proprietary specifications for such a system, not one has been accepted as universal. This specification attempts to address the major hurdles facing applications developers writing network applications using TCP/IP on MS-DOS machines. Some applications access the network via the packet driver specification. Although this solution solves the problem of the multiplicity of network hardware, it is unsatisfactory when more than one application wishes to access the same network protocol (TCP/IP) simultaneously. What is required by an application is a standard way of seeing the TCP/IP layer in a manner similar to the machine's file system. This document provides a possible mechanism to provide the TCP/IP services in any application running on MS-DOS. _______________________ Finding the TCP/IP ABI. The TSR (Terminate and Stay Resident) program can attach to an interrupt vector in the range 60H-7FH in a similar manner to a packet driver. The first instruction of the hook should be a JMP NEAR instruction and have after it the string 'TCP_DRVR' (for want of a better name). The vector to attach to should be specifyable since it may not be possible to determine if the vector is free. Calls to the TSR are made using the standard 8086/88 software interrupt calls through this vector. Upon loading the TSR, the IP address, netmask, gateway etc are determined by a suitable method, either directly, or using RARP or BOOTP. One should also be able to pass this information via the command-line, or use the environment variables. The packet layer could be any of a variety of mechanisms. How this is done is totally open to question, but the following information should be accurate once the ABI is loaded and active. This specification is to provide the next layer above the packet driver interface. my IP address netmask gateway IP address(es) domain name server IP address(es) - available for a higher layer than this driver. _____________ General notes All calls return dl = error code (0 if none) (carry set if <> 0) except for the driver existence determination All handles returned are a word value corresponding to an index into a table or list. They can be guaranteed to be unique only, and 0 is allowable. If no handles are available then the returned handle of an open call is 0FFFFH. Handles are also reusable. The current implementation of Trumpet TCP returns handles in steps of 1 starting at 0. This can be useful for a general purpose status program to interrogate the status of TCP connections. Most calls have AL register set to option flags. A standard call has the value 0 and may block the processor. A timeout is provided via DX. If DX = FFFFH then the operation will proceed until done. All timeouts are measured in terms of PC clock ticks (18.2 Hz) A timeout of 0 specifies a non-blocking call and will not return an error if operation times out. One can usually use the status call to determine the status of the tcp connection. The Trumpet TCP implements timeouts. The following calls may block. tcp: open, close, send, recv udp: recv, (send blocks only if arp required) ip: recv, (send blocks only if arp required) All other calls don't block and do not require a timeout. If the option flag 128 (80H) is set then an asynchronous i/o is done. On completion of i/o, an event handler is called. Other options are relevant to the call concerned. Care needs to be taken in multi-program environments such as Windows 3 that the event-handler address is valid. Event handlers are assigned by the attach/detach event operation. Implementation of asynchronous i/o is optional. At present the Trumpet TCP does not implement this function. All register values will be preserved across calls except for those which return values. ____________ Driver hooks ___________ driver_info determine if driver is valid and the functionality of the driver call ah = 00H al = FFH return al = FFH no driver loaded al = 0 driver loaded dh = additional functionality flags 1 = implements timeouts 2 = implements async i/o via events ds:si = pointer to "TCP_DRVR" es:di = pointer to driver info (including IP address, net params, etc) driver_info_rec: myip dword netmask dword gateway dword dnsserver dword timeserver dword mtu word def_ttl byte def_tos byte tcp_mss word tcp_rwin word debug word domain string[255] (db 0,255 dup(0)) _____________ driver_unload unload driver from memory. call ah = 01H return dl = error code ___________ driver_doio perform driver processing Will call event handlers as required Must be called regularly to process packets Can be attached to timer interrupt. Care must be taken with reentrancy. call ah = 02H return ax = no. of free pkts on IP input queue cx = no. of free pkts on IP output queue dl = error code ____________________ driver_critical_flag return the driver's critical flag call ah = 03H return es:di = pointer to critical flag byte dl = error code ________________ copy driver info copy the driver info to a user buffer call ah = 04H cx = size of buffer es:di = pointer to local buffer return cx = bytes stored _________ TCP hooks ________ tcp_open open an active/passive tcp session call ah = 10H al = option flags 0 = normal 1 = listener 128 = asynchronous. Notify by event_call bx = tcp_srce (0 = allocate unused port) cx = tcp_dest (0 = any port when listener) dx = timeout (0 = non-blocking, FFFF = infinite) si:di = ip_dest (dword) (0 = any when listener) return ax = local port no. bx = handle dl = error code no_handles timed_out invalid_session _________ tcp_close close a tcp session call ah = 11H al = option flags 0 = normal 1 = abort session 128 = asynchronous. Notify by event_call bx = handle dx = timeout (0 = non-blocking, FFFF = infinite) return dl = error code bad_handle timed_out invalid_session Note: a session closed with a timeout of 0 will not release the handle. It must either be closed with a non-zero timeout. A non-zero timeout will always release the handle, as will an abort option. A listen for any connection will revert back to an IP address of FFFFFFFF when the connection returns back to the listen state. The handling of listener sessions may change in the future to accomodate compatibility with "socket" implementations. _______ tcp_get read data into buffer call ah = 12H al = option flags 0 = normal (wait till buffer full) 1 = get as much as possible & return 2 = read to (don't include) 128 = asynchronous. Notify by event_call bx = handle es:di = pointer to buffer cx = size of buffer dx = timeout (0 = non-blocking, FFFF = infinite) return buffer has data transferred to it ax = no. bytes transferred dl = error code bad_handle timed_out invalid_session dh = returned flags 2 = read in option 2 8 = urgent data present _______ tcp_put write data to buffer call ah = 13H al = option flags 0 = normal (wait till buffer delivered) 1 = put as much as possible & return 2 = append to data 4 = push (wait till data acknowledged) 8 = urgent data 128 = asynchronous. Notify by event_call bx = handle es:di = pointer to buffer cx = size of buffer dx = timeout (0 = non-blocking, FFFF = infinite) return ax = no. bytes transferred dl = error code bad_handle timed_out invalid_session __________ tcp_status get status of a TCP session call ah = 14H al = option flags 0 = normal 128 = asynchronous. Notify by event_call bx = handle return dl = error code bad_handle dh = tcp_state ax = bytes available for reading cx = bytes still being transmitted es:di = pointer to session info ip_srce dword ip_dest dword ip_prot byte active byte (> 0 is active) _________ UDP Hooks ________ udp_open call ah = 20H al = option flags 0 = normal 128 = asynchronous. Notify by event_call bx = udp_srce (0 = allocate next unused) cx = udp_dest (0 = listen for any) si:di = ip_dest (0/FFFFFFFF = listen for any) return ax = local port no. bx = handle dl = error code no_handles _________ udp_close call ah = 21H al = option flags 0 = normal 128 = asynchronous. Notify by event_call bx = handle return dl = error code bad_handle ________ udp_recv call ah = 22H al = option flags 0 = normal 128 = asynchronous i/o signal via event_call bx = handle es:di = pointer to buffer cx = length dx = timeout (FFFF = infinite) return ax = no. bytes transferred dl = error code bad_handle timed_out bp = ttl & tos (ttl = lo byte, tos = hi byte) 0 = default ttl & tos si = id (note that the IP address of the most recent packet read is available with a status call, if receiving all) ________ udp_send call ah = 23H al = option flags 0 = normal 128 = asynchronous i/o signal via event_call bx = handle es:di = pointer to buffer cx = length bp = ttl & tos (ttl = lo byte, tos = hi byte) 0 = default ttl & tos si = id return ax = no. bytes transferred dl = error code bad_handle __________ udp_status call ah = 24H al = option flags 0 = normal 128 = asynchronous. Notify by event_call return ax = number of packets available cx = size of next packet (0 if none) dl = error code bad_handle es:di = pointer to session info ip_srce dword ip_dest dword ip_prot byte active byte (> 0 is active) ________ IP Hooks _______ ip_open call ah = 30H al = option flags 0 = normal 128 = asynchronous. Notify by event_call bl = protocol si:di = ip_dest (0/FFFFFFFF = listen for any) return ax = handle dl = error code no_handles ________ ip_close call ah = 31H bx = handle return dl = error code bad_handle _______ ip_recv call ah = 32H al = option flags 0 = normal 128 = asynchronous i/o signal via event_call bx = handle es:di = pointer to buffer cx = length dx = timeout (FFFF = infinite) return ax = no. bytes transferred dl = error code bad_handle timed_out bp = ttl & tos (ttl = lo byte, tos = hi byte) 0 = default ttl & tos si = id (note that the IP address of the most recent packet read is available with a status call, if receiving all) _______ ip_send call ah = 33H al = option flags 0 = normal 128 = asynchronous i/o signal via event_call bx = handle es:di = pointer to buffer cx = length bp = ttl & tos (ttl = lo byte, tos = hi byte) 0 = default ttl & tos si = id return ax = no. bytes transferred dl = error code bad_handle _________ ip_status call ah = 34H al = option flags 0 = normal 128 = asynchronous. Notify by event_call return ax = number of packets available cx = size of next packet (0 if none) dl = error code bad_handle es:di = pointer to session info ip_srce dword ip_dest dword ip_prot byte active byte (> 0 is active) _________________________ Event handlers (optional) All registers are saved before event handler called, and restored after event handler done. Information returned is call dependent. Note that DS undefined, so that it is the users responsibility to set up the called environment. Note also that Windows 3.0 has to be managed suitably when performing up-calls asynchronously. ___________________ Attach_event_global allow chaining, but check for duplicates call ax = 4000H es:di = address of event handler upcall return dl = error code already_attached ___________________ Detach_event_global call ax = 4100H es:di = address of event handler upcall return dl = error code not_attached __________________ Attach_event_local no chaining allowed, only 1 per handle call ax = 4200H bx = handle es:di = address of event handler upcall return dl = error code bad_handle already_attached __________________ Detach_event_local call ax = 4300H bx = handle return dl = error code bad_handle not_attached __________ event_call upcall ax = event-id (ah = same as int call, al = subfunction) bx = handle (FFFF if general failure) cx:dx = info (e.g. no of bytes transferred) return registers not preserved ___________ Error Codes no_error = 0; err_badcall = 1; err_critical = 2; err_nohandles = 3; err_badhandle = 4; err_timeout = 5; err_badsession = 6;