@nataliapc/mcp-openmsx
Version:
Model context protocol server for openMSX automation and control
1,045 lines (780 loc) • 108 kB
Markdown
# TCP/IP UNAPI specification
## Index
[1. Introduction](#1-introduction)
[1.1. Design goals](#11-design-goals)
[1.2. Specification scope](#12-specification-scope)
[1.3. Modularity](#13-modularity)
[2. API identifier and version](#2-api-identifier-and-version)
[3. Error codes](#3-error-codes)
[4. API routines](#4-api-routines)
[4.1. Information gathering routines](#41-information-gathering-routines)
[4.1.1. UNAPI_GET_INFO: Obtain the implementation name and version](#411-unapi_get_info-obtain-the-implementation-name-and-version)
[4.1.2. TCPIP_GET_CAPAB: Get information about the TCP/IP capabilities and features](#412-tcpip_get_capab-get-information-about-the-tcpip-capabilities-and-features)
[4.1.3. TCPIP_GET_IPINFO: Get IP address](#413-tcpip_get_ipinfo-get-ip-address)
[4.1.4. TCPIP_NET_STATE: Get network state](#414-tcpip_net_state-get-network-state)
[4.2. ICMP echo request (PING) routines](#42-icmp-echo-request-ping-routines)
[4.2.1. TCPIP_SEND_ECHO: Send ICMP echo message (PING)](#421-tcpip_send_echo-send-icmp-echo-message-ping)
[4.2.2. TCPIP_RCV_ECHO: Retrieve ICMP echo response message](#422-tcpip_rcv_echo-retrieve-icmp-echo-response-message)
[4.3. Host name resolution routines](#43-host-name-resolution-routines)
[4.3.1. TCPIP_DNS_Q: Start a host name resolution query](#431-tcpip_dns_q-start-a-host-name-resolution-query)
[4.3.2. TCPIP_DNS_S: Obtains the host name resolution process state and result](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result)
[4.4. UDP protocol related routines](#44-udp-protocol-related-routines)
[4.4.1. TCPIP_UDP_OPEN: Open a UDP connection](#441-tcpip_udp_open-open-a-udp-connection)
[4.4.2. TCPIP_UDP_CLOSE: Close a UDP connection](#442-tcpip_udp_close-close-a-udp-connection)
[4.4.3. TCPIP_UDP_STATE: Get the state of a UDP connection](#443-tcpip_udp_state-get-the-state-of-a-udp-connection)
[4.4.4. TCPIP_UDP_SEND: Send an UDP datagram](#444-tcpip_udp_send-send-an-udp-datagram)
[4.4.5. TCPIP_UDP_RCV: Retrieve an incoming UDP datagram](#445-tcpip_udp_rcv-retrieve-an-incoming-udp-datagram)
[4.5. TCP protocol related routines](#45-tcp-protocol-related-routines)
[4.5.1. TCPIP_TCP_OPEN: Open a TCP connection](#451-tcpip_tcp_open-open-a-tcp-connection)
[4.5.2. TCPIP_TCP_CLOSE: Close a TCP connection](#452-tcpip_tcp_close-close-a-tcp-connection)
[4.5.3. TCPIP_TCP_ABORT: Abort a TCP connection](#453-tcpip_tcp_abort-abort-a-tcp-connection)
[4.5.4. TCPIP_TCP_STATE: Get the state of a TCP connection](#454-tcpip_tcp_state-get-the-state-of-a-tcp-connection)
[4.5.5. TCPIP_TCP_SEND: Send data a TCP connection](#455-tcpip_tcp_send-send-data-a-tcp-connection)
[4.5.6. TCPIP_TCP_RCV: Receive data from a TCP connection](#456-tcpip_tcp_rcv-receive-data-from-a-tcp-connection)
[4.5.7. TCPIP_TCP_DISCARD: Discard data in the output buffer of a TCP connection](#457-tcpip_tcp_discard-discard-data-in-the-output-buffer-of-a-tcp-connection)
[4.6. Raw IP connections related routines](#46-raw-ip-connections-related-routines)
[4.6.1. TCPIP_RAW_OPEN: Open a raw IP connection](#461-tcpip_raw_open-open-a-raw-ip-connection)
[4.6.2. TCPIP_RAW_CLOSE: Close a raw IP connection](#462-tcpip_raw_close-close-a-raw-ip-connection)
[4.6.3. TCPIP_RAW_STATE: Get the state of a raw IP connection](#463-tcpip_raw_state-get-the-state-of-a-raw-ip-connection)
[4.6.4. TCPIP_RAW_SEND: Send a raw IP datagram](#464-tcpip_raw_send-send-a-raw-ip-datagram)
[4.6.5. TCPIP_RAW_RCV: Retrieve an incoming raw IP datagram](#465-tcpip_raw_rcv-retrieve-an-incoming-raw-ip-datagram)
[4.7. Configuration related routines](#47-configuration-related-routines)
[4.7.1. TCPIP_CONFIG_AUTOIP: Enable or disable the automatic IP addresses retrieval](#471-tcpip_config_autoip-enable-or-disable-the-automatic-ip-addresses-retrieval)
[4.7.2. TCPIP_CONFIG_IP: Manually configure an IP address](#472-tcpip_config_ip-manually-configure-an-ip-address)
[4.7.3. TCPIP_CONFIG_TTL: Get/set the value of TTL and TOS for outgoing datagrams](#473-tcpip_config_ttl-getset-the-value-of-ttl-and-tos-for-outgoing-datagrams)
[4.7.4. TCPIP_CONFIG_PING: Get/set the automatic PING reply flag](#474-tcpip_config_ping-getset-the-automatic-ping-reply-flag)
[4.8. Miscellaneous routines](#48-miscellaneous-routines)
[4.8.1. TCPIP_WAIT: Wait for a processing step to run](#481-tcpip_wait-wait-for-a-processing-step-to-run)
## 1. Introduction
MSX-UNAPI is a standard procedure for defining, discovering and using new APIs
(Application Program Interfaces) for MSX computers. The MSX-UNAPI specification is
described [in a separate document](MSX%20UNAPI%20specification%201.1.md).
This document describes an UNAPI compliant API intended for software that implements
a TCP/IP stack, that is, software that provides networking capabilities by using the IP
family of protocols. The functionality provided by this API is focused mainly on
communicating with other computers by using the TCP and UDP protocols, but there are
also some additional routines that allow for example performing domain name resolution
by querying DNS servers.
The intended client software applications for this API are networking related applications
such as Telnet, FTP or e-mail clients. Any software willing to transmit or receive data by
using the TCP or UDP protocols can make use of implementations of this specification.
This document is targeted at both developers of TCP/IP UNAPI implementations, and
developers of client applications for these implementations.
### 1.1. Design goals
There were two main goals when designing this specification:
* _Simplicity_. This specification's intent is to provide the simplest API that will allow
to develop useful networking applications for MSX computers.
* _Modularity_. Most of the capabilities provided by this API are optional, and there
are means to get information about which capabilities are supported by a given
implementation. This allows to create from minimal to complete
implementations, as well as providing a clean way to develop an implementation
in an incremental way.
### 1.2. Specification scope
In order to achieve the simplicity goal, this specification deals with the most basic
capabilities required in order to develop client networking applications. These capabilities
are:
* Communicating via TCP connections.
* Communicating via UDP datagrams.
* Converting domain names to IP addresses by querying DNS servers.
* Sending ICMP echo request messages (PINGs) and retrieving their answers.
* Communicating via raw IP datagrams.
Other capabilities that are usually part of TCP/IP stacks, but which are not necessary in
order to develop most client applications, are not covered by this specification. In
particular, this specification does NOT deal with:
* The link layer protocol / physical transport medium used (serial cable, modem,
Ethernet network, wireless network, joystick cable, or whatever medium is
used).
* The procedure for establishing and closing a network connection, if applicable.
* The configuration parameters of the implementation, other than basic
parameters such as the IP addresses to use and wether to set these IP
addresses manually or automatically (for example setting the user name and
password for establishing a network connection is not covered).
* Sending and receiving ICMP messages, other than echo messages (PINGs).
* Configuring routing tables.
* Converting IP addresses into hardware addresses using ARP or an equivalent
protocol, when applicable.
Note that this does not impose any restriction on implementations for actually providing
these features. For example, an implementation may deal internally with ICMP
messages; an Ethernet based implementation will most probably use ARP to convert IP
addresses to hardware addreses; and it is expected that implementations will be
delivered with the appropriate advanced configuration tools, when needed. The key
concept is that these capabilities may exist but are not covered by this specification.
### 1.3. Modularity
In order to achieve the modularity goal, most of the capabilities defined in this
specification are optional; implementations may choose to implement the full
specification, or only a subset of it. Of course, the less capabilities are implemented by a
given implementation, the greater are the chances that a particular client application will
not work with it, especially the most basic capabilities. For example, an implementation
not providing any support for TCP connections will not be very useful; on the other hand,
an implementation that supports TCP and UDP but does not support raw IP connections
will probably still work fine with most client applications.
The modularity feature is implemented in two ways:
1. There is a routine, [TCPIP_GET_CAPAB](#412-tcpip_get_capab-get-information-about-the-tcpip-capabilities-and-features), that returns a
"capabilities vector". This vector holds one bit for each capability that is defined
in this specification; when the bit is set it means that the capability is
implemented.
2. All routines defined in this specification return an error code in register A. One of
these codes is "Not implemented", and is returned whenever a routine related to
an unimplemented capability is invoked (certain routines return this error or not
depending on the input parameters).
For more details on which routines can be invoked (and how) depending on the
supported capabilities, see the routines descriptions themselves.
## 2. API identifier and version
The API identifier for the specification described in this document is: "TCP/IP" (without
the quotes). Remember that per the UNAPI specification, API identifiers are caseinsensitive.
The TCP/IP API version described in this document is 1.1. This is the API specification
version that the mandatory implementation information routine must return in DE (see
[UNAPI_GET_INFO](#411-unapi_get_info-obtain-the-implementation-name-and-version)).
## 3. Error codes
All routines defined in this specification return an error code in register A. This section
lists all the possible error codes; the numeric value, a mnemonic and a short description
is provided for each one. Each routine description has an errors section which explains
with detail which error codes can be returned for that routine, and for which reasons is
each one returned.
| Code | Mnemonic | Description |
|----|---|---|
| 0 | ERR_OK | Operation completed successfully |
| 1 | ERR_NOT_IMP | Capability not implemented |
| 2 | ERR_NO_NETWORK | No network connection available |
| 3 | ERR_NO_DATA | No incoming data available |
| 4 | ERR_INV_PARAM | Invalid input parameter |
| 5 | ERR_QUERY_EXISTS | Another query is already in progress |
| 6 | ERR_INV_IP | Invalid IP address |
| 7 | ERR_NO_DNS | No DNS servers are configured |
| 8 | ERR_DNS | Error returned by DNS server |
| 9 | ERR_NO_FREE_CONN | No free connections available |
| 10 | ERR_CONN_EXISTS | Connection already exists |
| 11 | ERR_NO_CONN | Connection does not exists |
| 12 | ERR_CONN_STATE | Invalid connection state |
| 13 | ERR_BUFFER | Insufficient output buffer space |
| 14 | ERR_LARGE_DGRAM | Datagram is too large |
| 15 | ERR_INV_OPER | Invalid operation |
## 4. API routines
This version of the TCP/IP API consists of 30 mandatory routines, which are described
below. API implementations may define their own additional implementation-specific
routines, as described in the MSX-UNAPI specification.
Routines are grouped in subsections by related behavior. Useful information concerning
all the routines on a given subsection is provided at the beginning of each subsection.
Some routines exchange data with the client application by using a memory buffer. Per
the UNAPI specification, implementations may not allow the destination address to be a
page 1 address (in the range 4000h-7FFFh). Client software should not use this range as
destination address when invoking these routines, in order to correctly interoperate with
such implementations.
### 4.1. Information gathering routines
These routines allow to obtain various information about the implementation capabilities,
working parameters, and current state.
### 4.1.1. UNAPI_GET_INFO: Obtain the implementation name and version
* Input:
* A = 0
* Output:
* A = Error code
* HL = Address of the implementation name string
* DE = API specification version supported. D=primary, E=secondary.
* BC = API implementation version. B=primary, C=secondary.
This routine is mandatory for all implementations of all UNAPI compliant APIs. It returns
basic information about the implementation itself: the implementation version, the
supported API version, and a pointer to the implementation description string.
The implementation name string must be placed in the same slot or segment of the
implementation code (or in page 3), must be zero terminated, must consist of printable
characters, and must be at most 63 characters long (not including the terminating zero).
Refer to the MSX-UNAPI specification for more details.
**ERROR CODES**
This routine never fails. ERR_OK is always returned.
### 4.1.2. TCPIP_GET_CAPAB: Get information about the TCP/IP capabilities and features
* Input:
* A = 1
* B = Index of information block to retrieve:
* 1: Capabilities and features flags, link level protocol
* 2: Connection pool size and status
* 3: Maximum datagram size allowed
* 4: Second set of capabilities and features flags
* Output:
* A = Error code
When information block 1 requested:
* HL = Capabilities flags
* DE = Features flags
* B = Link level protocol used
When information block 2 requested:
* B = Maximum simultaneous TCP connections supported
* C = Maximum simultaneous UDP connections supported
* D = Free TCP connections currently available
* E = Free UDP connections currently available
* H = Maximum simultaneous raw IP connections supported
* L = Free raw IP connections currently available
When information block 3 requested:
* HL = Maximum incoming datagram size supported
* DE = Maximum outgoing datagram size supported
When information block 4 requested:
* HL = Second set of capabilities flags
* DE = Second set of features flags (currently unused, always zero)
As explained in ["Modularity"](#13-modularity), the TCP/IP UNAPI specification is modular, meaning that
implementators may choose to include only a certain funcionality subset in the
developed implementations. This is the routine that gives information about the
capabilities actually available in the implementation in which it is invoked. It also
provides information about other implementation working parameters that may be useful
for client applications.
The **capabilities flags** is the most important piece of information, and should be
retrieved by all client applications at startup time, before trying to actually perform any
TCP/IP related operation. It consists of a bitfield in which each bit is associated to one of
the capabilities provided by the routines described in this specification. When the bit is
one, the capability is available, and client applications can safely invoke the routines that
provide the capability. When the bit is zero, the capability is not implemented, and trying
to invoke any of the associated routines will result in the routine returning a
ERR_NOT_IMP error code. (Some routines depend on a given capability or not depending
on the input parameters; more details are given on each routine description).
The first set of capabilities flags (returned whe information block 1 is requested) is as follows.
Bit 0 is LSB of register L, bit 8 is LSB of register H.
* Bit 0: Send ICMP echo messages (PINGs) and retrieve the answers
* Bit 1: Resolve host names by querying a local hosts file or database
* Bit 2: Resolve host names by querying a DNS server
* Bit 3: Open TCP connections in active mode
* Bit 4: Open TCP connections in passive mode, with specified remote socket
* Bit 5: Open TCP connections in passive mode, with unsepecified remote socket
* Bit 6: Send and receive TCP urgent data
* Bit 7: Explicitly set the PUSH * Bit when sending TCP data
* Bit 8: Send data to a TCP connection before the ESTABLISHED state is reached
* Bit 9: Discard data in the output buffer of a TCP connection
* Bit 10: Open UDP connections
* Bit 11: Open raw IP connections
* Bit 12: Explicitly set the TTL and ToS for outgoing datagrams
* Bit 13: Explicitly set the automatic reply to PINGs on or off
* Bit 14: Automatically obtain the IP addresses, by using DHCP or an equivalent protocol (deprecated)
* Bit 15: Get the TTL and ToS for outgoing datagrams
The second set of capabilities flags (returned whe information block 4 is requested) is as follows.
* Bit 0: Automatically obtain the local IP address, subnet mask and default gateway, by using DHCP or an equivalent protocol
* Bit 1: Automatically obtain the IP addresses of the DNS servers, by using DHCP or an equivalent protocol
* Bit 2: Manually set the local IP address
* Bit 3: Manually set the peer IP address
* Bit 4: Manually set the subnet mask IP address
* Bit 5: Manually set the default gateway IP address
* Bit 6: Manually set the primary DNS server IP address
* Bit 7: Manually set the secondary DNS server IP address
* Bit 8: Use [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) in TCP active connections
* Bit 9: Use [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) in TCP passive connections
* Bits 10-15: Unused
Bit 14 of the primary set is deprecated and kept for compatibility with version 1.0 of the specification.
It must be set if at least one of bits 0 and 1 of the secondary set is set.
The **features flags** provide additional information about the internal working
parameters of the implementation. These parameters have no direct influence on the
specification routines (no ERR_NOT_IMP error will ever be returned as a result of one of
these features being missing), but client applications may indirectly make use of this
information to decide how to behave.
The first (and currently only) set of features flags (returned whe information block 1 is requested) is as follows.
Bit 0 is LSB of register E, bit 8 is LSB of register D.
* Bit 0: Physical link is point to point
* Bit 1: Physical link is wireless
* Bit 2: Connection pool is shared by TCP, UDP and raw IP (see explanation about maximum simultaneus connection support below)
* Bit 3: Checking network state requires sending a packet in looback mode, or other expensive (time consuming) procedure
* Bit 4: The TCP/IP handling code is assisted by external hardware
* Bit 5: The loopback address (127.x.x.x) is supported
* Bit 6: A host name resolution cache is implemented
* Bit 7: IP datagram fragmentation is supported
* Bit 8: User timeout suggested when opening a TCP connection is actually applied
* Bit 9: TTL can be specified in the parameters block of [TCPIP_SEND_ECHO](#421-tcpip_send_echo-send-icmp-echo-message-ping)
* Bit 10: [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query) is a blocking operation
* Bit 11: [TCPIP_TCP_OPEN](#451-tcpip_tcp_open-open-a-tcp-connection) is a blocking operation
* Bit 12: The server certificate can be verified when opening a TCP connection with TLS in [TCPIP_TCP_OPEN](#451-tcpip_tcp_open-open-a-tcp-connection)
* Bits 13-15: Unused
**Note for client application developers:** Bit 15 of the first set of capabilities flags,
the entire second set of capabilities flags, and bits 9-12 of the first set of features flags
were introduced in version 1.1 of the specification. They aren't presend on implementations of version 1.0.
The **link level protocol used** byte may be one of the following. Future versions of this
specification may define additional codes.
* 0: Other/Unespecified
* 1: SLIP
* 2: PPP
* 3: Ethernet
* 4: WiFi
The **connection pool size and status** block informs about how many TCP, UDP and
raw IP connections can be handled simultaneously by the implementation, as well as
how many free connections are currently available. If the TCP, UDP or raw IP protocols
are not supported at all (as indicated in the capabilities flags), then the maximum and
free connection count for that protocol should be returned as zero.
When the _"Connection pool is shared by TCP, UDP and raw IP"_ feature bit is set, it
means that there is one single group of free connections for both TCP, UDP and raw IP,
rather than one separate group for each protocol. This implies that the "maximum
simultaneuos connections" and "current free connections" values always will be the same
for all three protocols, and opening a new connection for any of the protocols will cause
all three free connection counters to decrease.
The **maximum datagram size allowed** block informs about the maximum size of IP
datagrams (including IP and higher level protocol headers, but not including any link
level header) the implementation can handle. The implementation may silently discard
any incoming datagrams larger than the maximum incoming datagram size, but client
applications may usually ignore this fact. More important is the maximum outgoing
datagram size, since client applications need to take in account this value when
performing an operation that involves directly sending datagrams (such as sending UDP
data or raw IP datagrams).
All implementations are required to support a minimum datagram size of 576 bytes, as
per the IP protocol specification.
**ERROR CODES**
* ERR_OK
The requested information block has been returned.
* ERR_INV_PAR
Invalid information block index specified.
### 4.1.3. TCPIP_GET_IPINFO: Get IP address
* Input:
* A = 2
* B = Index of address to obtain:
* 1: Local IP address
* 2: Peer IP address
* 3: Subnet mask
* 4: Default gateway
* 5: Primary DNS server IP address
* 6: Secondary DNS server IP address
* Output:
* A = Error code
* L.H.E.D = Requested address
This routine returns one of the IP address parameters used by the implementation, as
currently configured. If an address is not configured, then it is returned as 0.0.0.0.
The addresses are returned in the format L.H.E.D. For example, 1.2.3.4 is returned as
HL=0201h, DE=0403h. This makes easier to store and retrieve addresses in memory
using simple `ld (IP),hl : ld(IP+2),de` or equivalent instructions.
**ERROR CODES**
* ERR_OK
The requested IP address has been returned.
* ERR_INV_PAR
An invalid value for B has been specified at input, or the specified address type does not
make sense for the implementation (for example the subnet mask or the default
gateway when the link layer protocol is PPP, or the peer address on an Ethernet
network).
### 4.1.4. TCPIP_NET_STATE: Get network state
* Input:
* A = 3
* Output:
* A = Error code
* B = Current network state:
* 0: Closed
* 1: Opening
* 2: Open
* 3: Closing
* 255: Unknown
This routine returns the current state of the network availability. It is only possible to
send and receive data when the network state is "Open"; it may or may not be possible
as well when the returned state is "Unknown".
The "Closed" state may refer to a logical close (for example, no connection has been
established in case of serial communications using the PPP protocol) or to a physical
medium unavailability (for example, no cable is connected in case of an Ethernet
network).
The "Opening" state means that the implementation is actively trying to reach the
"Open" state, but the actions that are actually performed for this depend on each
implementation. For example, it may mean "connecting to the ISP" in case of modem
communications, or "obtaining addresses via DHCP" in case of an Ethernet network.
There are no restrictions on the possible transitions from any of these states to any
other. For example, an implementation could pass from "Opening" to "Closed" again if an
error is detected during the opening process. Or, it could toggle between "Open" and
"Closed" directly if no special setup or shutdown process is required.
Implementations should return the "Checking network state requires an expensive
procedure" feature flag set if calling this routine implies performing a time consuming
procedure (such as sending a loopback packet), in order to inform client that it should
not be called too often.
**ERROR CODES**
This routine never fails. ERR_OK is always returned.
### 4.2. ICMP echo request (PING) routines
These routines allow to send ICMP echo request messages (known as PINGs) and to
retrieve the received responses.
### 4.2.1. TCPIP_SEND_ECHO: Send ICMP echo message (PING)
* Input:
* A = 4
* HL = Address of echo parameters block
* Output:
* A = Error code
This routine sends an ICMP echo request (a PING) with the specified parameters. A
parameters block with the following format must be supplied:
* +0 (4): IP address of the destination machine
* +4 (1): TTL for the datagram
* +5 (2): ICMP identifier
* +7 (2): ICMP sequence number
* +9 (2): Data length, 0 to maximum datagram size - 28
The datagram will be send with the value specified if the _"TTL can be specified in the parameters block of
TCPIP_SEND_ECHO"_ feature flag is set. If it isn't, the implementation will choose by itself the value to use.
It is possible to choose the size of the data area of the ICMP message, but not its
contents; these must be always the byte sequence 0 1 2 ... 253 254 255 0 1 2...
appropriately truncated to match the specified size.
The identifier and the data number can help on matching requests and replies (an echo
reply will always have these values identical to the ones of its associated echo request),
they can be any 16 bit number. The TTL value should normally be set to 255, in order to
maximize the probability of the packet arriving to its destination.
Replies to ICMP echo messages (in the form of ICMP echo response messages) can be
obtained by using the [TCPIP_RCV_ECHO](#422-tcpip_rcv_echo-retrieve-icmp-echo-response-message) routine.
**ERROR CODES**
* ERR_OK
The ICMP echo message packet has been sent.
* ERR_NOT_IMP
The _"Send ICMP echo messages"_ capability flag is not set. The implementation does not
support sending ICMP echo messages.
* ERR_NO_NETWORK
There is no network connection available.
* ERR_LARGE_DGRAM
Invalid data length specified. The maximum data length allowed is equal to the
maximum outgoing datagram size minus 28 (the size of the IP and ICMP headers
combined).
### 4.2.2. TCPIP_RCV_ECHO: Retrieve ICMP echo response message
* Input:
* A = 5
* HL = Address for the echo parameters block
* Output:
* A = Error code
This routine retrieves the parameters associated to the oldest received ICMP echo
response message (usually received as a reply of an echo message sent via
[TCPIP_SEND_ECHO](#421-tcpip_send_echo-send-icmp-echo-message-ping)), and copies them to the address supplied in HL. It also removes the
message information from the implementation internal buffers, so that the next call to
this routine will either return information for the next message received, or a
ERR_NO_DATA error if no more messages are available. Implementations are required to
have internal buffer space to hold data for only one echo response message, but may
choose to provide space for more than one; echo response messages received when the
buffer space is full are silently discarded.
The parameters block has the same format as the one used by [TCPIP_SEND_ECHO](#421-tcpip_send_echo-send-icmp-echo-message-ping), only
that now the parameters refer to the received echo response message, not to a message
to be sent. It is not possible to retrieve the data part of the echo response messages
received.
**ERROR CODES**
* ERR_OK
The ICMP echo response message parameters have been copied to the specified address.
* ERR_NOT_IMP
The _"Send ICMP echo messages"_ capability flag is not set. The implementation does not
support receiving ICMP echo response messages.
* ERR_NO_DATA
No new ICMP echo response messages have been received and the implementation's
buffer for incoming messages is empty.
### 4.3. Host name resolution routines
These routines allow to resolve a host name, that is, to convert host names to the
appropriate IP addresses. Depending on the supported capabilities, host names may be
resolved by using a local hosts file or equivalent mechanism, by querying a DNS server,
or both.
### 4.3.1. TCPIP_DNS_Q: Start a host name resolution query
* Input:
* A = 6
* HL = Address of the host name to be resolved, zero terminated
* B = Flags, when set to 1 they instruct the resolver to:
* bit 0: Only abort the query currently in progress, if there is any (other flags and registers are then ignored)
* bit 1: Assume that the passed name is an IP address, and return an error if this is not true
* bit 2: If there is a query in progress already, do NOT abort it and return an error instead
* Output:
* A = Error code
* B = status after the routine returns:
* 0: a query to a DNS server is in progress
* 1: the name represented an IP address
* 2: the name could be resolved locally
* L.H.E.D = Resolved IP address (only if no error occurred and B=1 or 2 is returned)
This routine, together with its counterpart [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result)
explained later, allows to obtain
the IP address associated to a given host name (for example "smtp.mailserver.com"),
which may be up to 255 characters long. To achieve this, the DNS servers whose IP
addresses are currenly configured (see [TCPIP_GET_IPINFO](#413-tcpip_get_ipinfo-get-ip-address) routine) are queried. If the
implementation supports a local hosts file or an equivalent mechanism (as indicated by
the homonym capability flag), then it is queried first, and only when no match is found is
the DNS server queried.
Strings that directly represent an IP address (for example "120.200.0.34") must also be
accepted by this routine, making then easy to develop programs that accept both host
names and IP addresses as a user supplied parameter. This functionality is mandatory
even if the implementation does not support host name resolution by local hosts file nor
by querying DNS servers (that is, even if the _"Resolve host names by querying a local
hosts file"_ and _"Resolve host names by querying a DNS server"_ capability flags are both
not set).
After the host name is examined, there are three possibilities regarding how the host
name can be resolved:
1. _The name represents an IP address._ In that case, the result is directly returned
in registers HL and DE, and B=1 is returned.
2. _The name can be resolved locally_, by using a local hosts file or the resolver
cache. In that case, the result is directly returned in registers HL and DE, and
B=2 is returned.
3. _A query to a DNS server is needed to resolve the name._ In that case, the query
is started and B=0 is immediately returned; the query processing will continue in
background. TCP_DNS_S must be invoked in order to know when the query has
finished, and to get the result.
The implementation can use the _"TCPIP_DNS_Q is a blocking operation"_ feature flag to announce that
this routine may query DNS servers and that in this case it won't return to the caller until
such process is completed or fails (thus never returning the "a query to a DNS server is in progress" state).
Client applications may use this flag to be aware that the routine may take a long time to return.
In the first two cases, the result must be cached so that a later call to [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result) will
return it as well. That way, client applications may ignore the fact that some names will
be resolved locally (that is, they can ignore the returned values in B, HL and DE), and
always invoke TCP_DNS_S to get the result of the name resolution process.
As stated above, the only mandatory capability of this routine is to parse strings
representing IP addresses. Resolution of host names via local hosts file, and resolution
via queries to DNS servers, are both optional capabilities. Depending of which of these
capabilities are supported, implementations should behave as follows when a host name
that does not represent an IP address is requested to be resolved:
* _None of the capabilities is supported:_ An ERR_NOT_IMP error must be returned.
* _Only local hosts file is supported:_ The host name must be searched in the local
hosts file. If not found, a "Host name not found" error must be cached so a later
call to [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result) will return it. (See the description of [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result) for
details on this error)
* _Only queries to DNS servers are supported:_ A query to the configured DNS
server must be started.
* _Both capabilities are supported:_ The host name must be searched in the local
hosts file. If not found, a query to the configured DNS server must be started.
If there is already a query in progress when [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query) is executed, normally this
query will be aborted in order to initiate the new one (only one query can be handled at
a time). However, if B:2 is set at input and there is a query in progress, then this query
will not be aborted and a ERR_QUERY_EXSITS will be returned instead.
How the implementation performs queries to DNS servers is outside this specification,
however it is expected that all implementations will follow some basic procedures:
* The primary DNS server will be queried, and in case of failure, the secondary
server will be queried.
* The "recursive query" flag in the packets send to the DNS servers will be set, but
if the server does not support recursive queries and the address of another DNS
server is obtained instead of the requested IP address, then this server will in
turn be queried.
* A total timeout for the entire process will be implemented so that a client
application invoking [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result) in a loop will not hang forever waiting for a
result.
However the implementation behaves, the process must be transparent for client
applications, which will rely exclusively on the results returned by [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query) and
[TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result) routines.
**Note for implementors:** The following algorithm should be followed when
implementing this routine, to ensure that it behaves properly and returns the
appropriate error codes depending on the input parameters and the supported
capabilities.
```
Is B:0 set?
Yes: Abort the current query, if any
Return ERR_OK, B=0
Is there a query in progress?
Yes: Is B:2 set?
Yes: Return ERR_QUERY_EXISTS
No: Abort the current query
Try to parse host name as an IP address
Success?
Yes: Cache the result so that TCPIP_DNS_S will return it
Return ERR_OK, B=1, and the address in HL,DE
B:1 was set?
Yes: Return ERR_INV_IP
Are the local hosts file mechanism capability, and the querying DNS servers capability, both NOT supported?
Yes: Return ERR_NOT_IMP
Is the local hosts file mechanism supported?
Yes: Is the host name in the local hosts file?
Yes: Cache the result so that TCPIP_DNS_S will return it
Return ERR_OK, B=2, and the address in HL,DE
Is DNS querying supported?
No: Cache a "Host name not found error" so that TCPIP_DNS_S will return it (see description of TCPIP_DNS_S)
Return ERR_OK, B=0
Is DNS cache supported?
Yes: Is the host name in the DNS cache?
Yes: Cache the result so that TCPIP_DNS_S will return it
Return ERR_OK, B=2, and the address in HL,DE
Is network available?
No: Return ERR_NO_NETWORK
Is there any DNS server configured?
No: return ERR_NO_DNS
Start querying the primary DNS server, or the secondary, if primary is not configured
Return ERR_OK, B=0
```
Please note that the result is cached only if ERR_OK is returned. If any other error code
is returned, then [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result) must still return the same result as before [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query)
was invoked.
**Note for client application developers:** Below is an example of a simple way of using
the [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query)/S routines pair. For simplicity it is assumed that the implementation
routines can be called directly, without need for slot or segment switching.
```
;* Start the query
ld hl,HOST_NAME
xor a
call TCPIP_DNS_Q
or a
jp nz,ERROR_Q ;Jump to error management code
;* Wait until either a result or an error is returned
WAIT:
xor a
call TCPIP_DNS_S
cp 1 ;Query is still in progress
jr z,WAIT
cp 3 ;Query finished with error
jp z,ERROR_S ;Jump to error management code
;From here, A can only be equal to 2
ld (IP_ADD),hl ;Store the result
ld (IP_ADD+2),de
...
HOST_NAME: db "name.host.com",0
IP_ADD: ds 4
```
Note that in this example, we don't care about HOST_NAME representing an IP address
or being resolved locally. We just invoke [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result) to get the resolved IP address,
without checking how it was obtained. This will be enough in most cases.
**ERROR CODES**
* ERR_OK
A DNS query is in progress, or the name resolution process has finished and the result
has been cached for [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result).
* ERR_INV_PARAM
An unused flag was set in B.
* ERR_INV_IP
The host name does not represent an IP address and the routine was invoked with B:1
set.
* ERR_NOT_IMP
The host name does not represent an IP address, and neither the "Resolve host names
by querying a local hosts file" nor the "Resolve host names by querying a DNS server"
capabilities are supported.
* ERR_QUERY_EXISTS
The routine was invoked with B:0 set and there is another query in progress.
* ERR_NO_NETWORK
A query to a DNS server must start, but there is no network connectivity available.
* ERR_NO_DNS
A query to a DNS server must start, but there are no DNS server addresses configured.
### 4.3.2. TCPIP_DNS_S: Obtains the host name resolution process state and result
* Input:
* A = 7
* B = Flags, when set to 1 they instruct the resolver to:
* bit 0: Clear any existing result or error condition after the execution (except if there is a query in progress)
* Output:
* A = Error code
* B = DNS error code (when error is ERR_DNS)
* B = Current query status (when error is ERR_OK):
* 0: There is no query in progress, nor any result nor error code available
* 1: There is a query in progress
* 2: Query is complete
* C = Current query substatus (when error is ERR_OK and B=1):
* 0: Unknown
* 1: Querying the primary DNS server
* 2: Querying the secondary DNS server
* 3: Querying another DNS server
* C = Resolution proces type (when error is ERR_OK and B=2):
* 0: The name was obtained by querying a DNS server
* 1: The name was a direct representation of an IP address
* 2: The name was resolved locally
* L.H.E.D = Resolved IP address (when error is ERR_OK and B=2)
This routine is the complementary of [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query). It allow to obtain the status of the
current host name resolution process (which was initiated via an invocation to
[TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query)); and if the query process has finished, it returns either the resulting IP
addres or an appropriate error code.
As explained in the description of [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query), in certain circumstances the host name
can be resolved locally, without having to actually query any DNS server. In that case,
the result is cached so that [TCPIP_DNS_S](#432-tcpip_dns_s-obtains-the-host-name-resolution-process-state-and-result) returns it as well; that way, client applications
do not need to worry about a DNS query being actually performed or not (see the
sample code in the description of [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query)).
If B:0 is set at input, the current result is cleared after the routine returns, so that a
later invocation of the routine will return B=0 (no query is in progress and no result is
available). If B:0 is not set at input, successive invocations of the routine will always
return the same result, until an invocation of [TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query) that returns ERR_OK is
performed. Note that B:0 is ignored if there is a query in progress.
If ERR_DNS is returned, then B returns an error code with more detailed error
information. Below are the possible error codes that B can return; codes 1 to 15 are
directly returned by a DNS server (as defined in RFC1035), other codes are generated by
the implementation itself. Errors 1 and 4 should never be obtained if the implementation
is working properly.
* 0: Unknown error
* 1: Invalid query packet format
* 2: DNS server failure
* 3: The specified host name does not exist
* 4: The DNS server does not support this kind of query
* 5: Query refused
* 6-15: Undefined error codes
* 16: One of the queried DNS servers did not reply
* 17: Total process timeout expired
* 18: Query cancelled by the user ([TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query) was executed with B:0 set)
* 19: Network connectivity was lost during the process
* 20: The obtained reply did not contain REPLY nor AUTHORITATIVE
* 21: The obtained reply is truncated
Note that this routine does never return ERR_NOT_IMP, since it is required that
[TCPIP_DNS_Q](#431-tcpip_dns_q-start-a-host-name-resolution-query) is implemented to at least parse strings representing IP addresses.
**ERROR CODES**
* ERR_OK
A DNS query is in progress, or a DNS query has finished without errors, or no query is in
progress and results from a past query are not available.
* ERR_DNS
A DNS query has finished with errors, see register B for more details.
### 4.4. UDP protocol related routines
These routines allow to send and receive data by using the UDP protocol. Even if UDP is
a datagram based, connectionless protocol, a connections-like mechanism is used; here
an "UDP connection" is simply a pair formed by the local IP address + a local port
number. When sending UDP data, the connection number and the remote IP address and
port must be specified; when a UDP datagram is received on a given connection, the
remote IP address and port are retrieved as well.
UDP connections are identified by connection numbers, which may be any number in the
range 1 to 254. The numbers actually used depend on the implementation; client
applications should handle these numbers as opaque values.
There is a "intended connection lifetime" parameter that is to be specified when opening
the connection: _transient_, which means that the connection is intended to be closed
when the client application finishes; and _resident_, which means that the connection is
intended to be used by a resident program. The only behavioral difference between
these two modes as far as this specification is concerned, is that all open transient
connections are closed when [TCPIP_UDP_CLOSE](#442-tcpip_udp_close-close-a-udp-connection) is invoked and zero is specified as the
connection number, being the resident connections unaffected.
This specification does not define how implementations should handle incoming UDP
datagrams whose destination port number is not associated with any open UDP
connection. These datagrams can be silently discarded, or implementation specific
routines can be defined to handle them.
### 4.4.1. TCPIP_UDP_OPEN: Open a UDP connection
* Input:
* A = 8
* HL = Local port number (FFFFh: random port)
* B = Intended connection lifetime:
* 0: Transient
* 1: Resident
* Output:
* A = Error code
* B = Connection number
This routine opens a new UDP connection. This process does not imply any type of
negotiation or data exchange with any remote host; all that happens is that a connection
number is associated with a local port number.
The port number should not be zero, as this means "unespecified port" in the UDP
protocol, and this is not supported by this specification. Also, it should not be in the
range FFF0h-FFFEh, these port numbers are reserved for internal use of the
implementations.
When FFFFh is specified as the port number, the implementation must use a randomly
chosen port number. This port will be in the range 16384-32767, and will never be a
port number used by another open UDP connection.
Once the connection is open, UDP datagrams data can be sent and received by using the
[TCPIP_UDP_SEND](#444-tcpip_udp_send-send-an-udp-datagram) and [TCPIP_UDP_RCV](#445-tcpip_udp_rcv-retrieve-an-incoming-udp-datagram) routines. The connection can be closed by using
[TCPIP_UDP_CLOSE](#442-tcpip_udp_close-close-a-udp-connection). These routines expect the connection number returned by
[TCPIP_UDP_OPEN](#441-tcpip_udp_open-open-a-udp-connection) as an input parameter.
**ERROR CODES**
* ERR_OK
The connection has been created successfully. The returned connection number is valid.
* ERR_NOT_IMP
The _"Open UDP connections"_ capability flag is not set. The implementation does not
support sending and receiving UDP datagrams.
* ERR_INV_PARAM
- The "intended connection lifetime" parameter has an invalid value.
- Zero has been specified as the local port.
- The local port is in the range FFF0h-FFFEh.
* ERR_CONN_EXISTS
Other UDP connection exists which has the same local port assigned.
* ERR_NO_FREE_CONN
There are no free UDP connections available.
### 4.4.2. TCPIP_UDP_CLOSE: Close a UDP connection
* Input:
* A = 9
* B = Connection number, 0 to close all open transient UDP connections
* Output:
* A = Error code
This routine closes the specified UDP connection. This process does not imply any type of
negotiation or data exchange with any remote host; all that happens is that the
connection number is freed and all the pending incoming datagrams for the connection
are discarded.
All the existing connections that were open in "transient" lifetime mode are closed if zero
is specified as the connection number.
**ERROR CODES**
* ERR_OK
The connection(s) has (have) been closed successfully.
* ERR_NOT_IMP
The "Open UDP connections" capability flag is not set. The implementation does not
support sending and receiving UDP datagrams.
* ERR_NO_CONN
There is no connection open with the specified number.
### 4.4.3. TCPIP_UDP_STATE: Get the state of a UDP connection
* Input:
* A = 10
* B = Connection number
* Output:
* A = Error code
* HL = Local port number
* B = Number of pending incoming datagrams
* DE = Size of oldest pending incoming datagram (data part only)
This routine retrieves information about the UDP connection with the specified number.
_"Number of pending incoming datagrams"_ indicates how many UDP datagrams whose
destination port matches the connection's associated port have been received and
cached by the implementation; these datagrams can be retrieved by using the
[TCPIP_UDP_RCV](#445-tcpip_udp_rcv-retrieve-an-incoming-udp-datagram) routine. Implementations are required to have buffer space for only one
incoming UDP datagram per connection, but may optionally have space for more.
Datagrams received when this buffer is full are silently discarded.
_"Number of pending incoming datagrams"_ may actually be smaller than the actual
number of pending datagrams, if the implementation knows than there are received
datagrams but has no means to know how many. The following rules apply: if no
pending datagrams are available, then B=0; if at least one pending datagram is
available, then B>0 but less than or equal to the number of pending datagrams.
Applications willing to retrieve all the pending datagrams for a UDP connection should
not rely on this number; instead, they should invoke [TCPIP_UDP_RCV](#445-tcpip_udp_rcv-retrieve-an-incoming-udp-datagram) repeatedly until
ERR_NO_DATA is returned.
_"Size of oldest pending datagram"_ indicates the size of the data part of the datagram
that will be retrieved by the next call to [TCPIP_UDP_RCV](#445-tcpip_udp_rcv-retrieve-an-incoming-udp-datagram). It is zero if the datagram
contains no data apa