RISC OS TCP/IP libraries version 5.44
-------------------------------------

These libraries are an update to the libraries described in chapter 123 of
the PRM (supplied in this distribution and as part of PRM 5a). They support
all the new features of the Internet 5 module supplied with RISC OS 3.7 and
later, add a few new support calls, and generally tidy up the interfaces (in
particular with regard to "const correctness"). The libraries should now
function fully with the compiler in ANSI mode; some files in the previous
version would only compile in PCC mode.


Library versions
----------------
This distribution comprises the following library versions :

    inetlib 0.10 (TCPIPLibs:o.inetlib*)
    socklib 0.06 (TCPIPLibs:o.socklib*)
    unixlib 0.05 (TCPIPLibs:o.unixlib*)
    headers 1.09 (TCPIPLibs:h.*)


Suggested setup for using the libraries
---------------------------------------

   1) In a boot file (eg !SetPaths.!Boot/!Run, or within <Boot$ToBeTasks>)
      set a system variable TCPIPLibs$Path to point to the top directory of
      the libraries.
   2) Set the include path for CC to "C:,TCPIPLibs:".
   3) Put "p" in the "Suppress warnings" submenu of !CC (or add -Wp to the
      command line) to stop the compiler issuing warnings about the use of
      constructs like #include <sys/types.h>.
   4) If necessary, define COMPAT_INET4 (see below).
   5) Use ANSI mode, rather than Unix PCC mode. Previous releases of the
      library were not fully ANSI-compatible; this release should be.
   6) Link with TCPIPLibs:o.Socklib[5][zm][-32], and if necessary
      TCPIPLibs:o.Inetlib[zm][-32] and TCPIPLibs:o.Unixlib[zm][-32], in that
order.

   
Notes about these libraries
---------------------------
The Internet 5 module, and these libraries, are based on a 4.4BSD Unix
derivative, rather than the 4.3BSD Unix of Internet 4 and earlier. As a
result a few structures have changed. Notably a struct sockaddr now has a
length field, and the msghdr structure has changed. The potential
compatibility problems arising from this are solved as follows:

          1) All previously existing Internet SWIs will accept both old and
             new style structures as parameters.
          2) All previously existing Internet SWIs will return only
             old-style structures.
          3) There are a set of new SWIs providing alternate forms of calls
             that return new-style structures.

Now, if you define COMPAT_INET4 (using the -D option of the compiler), the
header files will define struct sockaddr etc. in the old way, and your code
will continue to function on old Internet modules. However, new calls (eg
the PF_ROUTE socket calls) that were not provided in Internet 4 will only
accept the new-style structures. Therefore the library provides structures
"nsockaddr" etc and functions "naccept" allowing access to the new calls
where necessary.

If you don't define COMPAT_INET4, then calls such as accept() will call the
new SWIs in the Internet 5 module, and the sockaddr etc structures will have
the new form. Your program will not function on Internet 4 modules. To
access the old structures and calls, use oaccept and osockaddr etc.

To clarify the relationship between the old and new ("_1" suffixed) SWIs and
the Socklib functions:

                                    COMPAT_INET4?
                                 Yes             No
            Socket_Accept      accept()        oaccept()
        SWI
            Socket_Accept_1    naccept()       accept()


Typically, most programs will be compiled with COMPAT_INET4 enabled, and use
socketversion() to check whether Internet 5 is loaded; they can then use the
new-style structures to access the new facilities, while using the old
structures throughout the rest of the program.

When compiling with COMPAT_INET4, you should link your program with Socklib
or Socklibzm. Otherwise, link with Socklib5 or Socklib5zm.

The text below consists of annotations, replacement sections and new
sections to be inserted into chapter 123 of the PRM (as supplied in this
distribution as 'Internet/htm').

                                  *************
                                  * PROTOCOLS *
                                  *************

ROUTE
=====

Name
----
route - kernel packet forwarding database

Synopsis
--------
#include <sys/socket.h>
#include <net/if.h>
#include <net/route.h>

int socket(PF_ROUTE, SOCK_RAW, int family)

Description
-----------
The Internet module provides some packet routing facilities.  The module
maintains a routing information database, which is used in selecting the
appropriate network interface when transmitting packets.

From Internet 5, a user process (or possibly multiple co-operating pro-
cesses) maintains this database by sending messages over a special kind
of socket.  This supplants fixed size socketioctl's used in earlier
releases.

The operating system may spontaneously emit routing messages in response
to external events, such as receipt of a re-direct, or failure to locate
a suitable route for a request.  The message types are described in
greater detail below.

Routing database entries come in two flavors: for a specific host, or for
all hosts on a generic subnetwork (as specified by a bit mask and value
under the mask.  The effect of wildcard or default route may be achieved
by using a mask of all zeros, and there may be hierarchical routes.

When the system is booted and addresses are assigned to the network in-
terfaces, each protocol family installs a routing table entry for each
interface when it is ready for traffic.  Normally the protocol specifies
the route through each interface as a 'direct' connection to the desti-
nation host or network.  If the route is direct, the transport layer of a
protocol family usually requests the packet be sent to the same host
specified in the packet.  Otherwise, the interface is requested to ad-
dress the packet to the gateway listed in the routing entry (i.e. the
packet is forwarded).

When routing a packet, the kernel will attempt to find the most specific
route matching the destination.  (If there are two different mask and
value-under-the-mask pairs that match, the more specific is the one with
more bits in the mask.  A route to a host is regarded as being supplied
with a mask of as many ones as there are bits in the destination).  If no
entry is found, the destination is declared to be unreachable, and a
routing-miss message is generated if there are any listers on the routing
control socket described below.

A wildcard routing entry is specified with a zero destination address
value, and a mask of all zeroes.  Wildcard routes will be used when the
system fails to find other routes matching the destination.  The combina-
tion of wildcard routes and routing redirects can provide an economical
mechanism for routing traffic.

One opens the channel for passing routing control messages by using the
socket call shown in the synopsis above:

The family parameter may be AF_UNSPEC which will provide routing informa-
tion for all address families, or can be restricted to a specific address
family by specifying which one is desired.  There can be more than one
routing socket open per system.

Messages are formed by a header followed by a small number of sockaddrs
(now variable length particularly in the ISO case), interpreted by posi-
tion, and delimited by the new length entry in the sockaddr.  An example
of a message with four addresses might be an ISO redirect: Destination,
Netmask, Gateway, and Author of the redirect.  The interpretation of
which address are present is given by a bit mask within the header, and
the sequence is least significant to most significant bit within the vec-
tor.

Any messages sent to the kernel are returned, and copies are sent to all
interested listeners.  The sender may use the sequence field to distin-
guish between outstanding messages.  However, message replies may be lost
when kernel buffers are exhausted.

The kernel may reject certain messages, and will indicate this by filling
in the rtm_errno field.  The routing code returns EEXIST if requested to
duplicate an existing entry, ESRCH if requested to delete a non-existent
entry, or ENOBUFS if insufficient resources were available to install a
new route.  In the current implementation, all routing process run local-
ly, and the values for rtm_errno are available through the normal errno
mechanism, even if the routing reply message is lost.

A process may avoid the expense of reading replies to its own messages by
issuing a setsockopt call indicating that the SO_USELOOPBACK option at
the SOL_SOCKET level is to be turned off.  A process may ignore all mes-
sages from the routing socket by doing a shutdown system call for fur-
ther input.

If a route is in use when it is deleted, the routing entry will be marked
down and removed from the routing table, but the resources associated
with it will not be reclaimed until all references to it are released.
User processes can obtain information about the routing entry to a spe-
cific destination by using a RTM_GET message, or by reading the /dev/kmem
device, or by issuing a getkerninfo system call.

Messages include:

#define RTM_ADD         0x1    /* Add Route */
#define RTM_DELETE      0x2    /* Delete Route */
#define RTM_CHANGE      0x3    /* Change Metrics, Flags, or Gateway */
#define RTM_GET         0x4    /* Report Information */
#define RTM_LOOSING     0x5    /* Kernel Suspects Partitioning */
#define RTM_REDIRECT    0x6    /* Told to use different route */
#define RTM_MISS        0x7    /* Lookup failed on this address */
#define RTM_RESOLVE     0xb    /* request to resolve dst to LL addr */

A message header consists of:

struct rt_msghdr {
    u_short rmt_msglen;  /* to skip over non-understood messages */
    u_char  rtm_version; /* future binary compatibility */
    u_char  rtm_type;    /* message type */
    u_short rmt_index;   /* index for associated ifp */
    pid_t   rmt_pid;     /* identify sender */
    int     rtm_addrs;   /* bitmask identifying sockaddrs in msg */
    int     rtm_seq;     /* for sender to identify action */
    int     rtm_errno;   /* why failed */
    int     rtm_flags;   /* flags, incl kern & message, e.g. DONE */
    int     rtm_use;     /* from rtentry */
    u_long  rtm_inits;   /* which values we are initializing */
    struct  rt_metrics rtm_rmx; /* metrics themselves */
};


where

struct rt_metrics {
    u_long rmx_locks;     /* Kernel must leave these values alone */
    u_long rmx_mtu;       /* MTU for this path */
    u_long rmx_hopcount;  /* max hops expected */
    u_long rmx_expire;    /* lifetime for route, e.g. redirect */
    u_long rmx_recvpipe;  /* inbound delay-bandwith product */
    u_long rmx_sendpipe;  /* outbound delay-bandwith product */
    u_long rmx_ssthresh;  /* outbound gateway buffer limit */
    u_long rmx_rtt;       /* estimated round trip time */
    u_long rmx_rttvar;    /* estimated rtt variance */
};

Flags include the values:

#define RTF_UP        0x1       /* route usable */
#define RTF_GATEWAY   0x2       /* destination is a gateway */
#define RTF_HOST      0x4       /* host entry (net otherwise) */
#define RTF_REJECT    0x8       /* host or net unreachable */
#define RTF_DYNAMIC   0x10      /* created dynamically (by redirect) */
#define RTF_MODIFIED  0x20      /* modified dynamically (by redirect) */
#define RTF_DONE      0x40      /* message confirmed */
#define RTF_MASK      0x80      /* subnet mask present */
#define RTF_CLONING   0x100     /* generate new routes on use */
#define RTF_XRESOLVE  0x200     /* external daemon resolves name */
#define RTF_LLINFO    0x400     /* generated by ARP or ESIS */
#define RTF_STATIC    0x800     /* manually added */
#define RTF_BLACKHOLE 0x1000    /* just discard pkts (during updates) */
#define RTF_PROTO2    0x4000    /* protocol specific routing flag #1 */
#define RTF_PROTO1    0x8000    /* protocol specific routing flag #2 */

Specifiers for metric values in rmx_locks and rtm_inits are:

#define RTV_SSTHRESH  0x1    /* init or lock _ssthresh */
#define RTV_RPIPE     0x2    /* init or lock _recvpipe */
#define RTV_SPIPE     0x4    /* init or lock _sendpipe */
#define RTV_HOPCOUNT  0x8    /* init or lock _hopcount */
#define RTV_RTT       0x10   /* init or lock _rtt */
#define RTV_RTTVAR    0x20   /* init or lock _rttvar */
#define RTV_MTU       0x40   /* init or lock _mtu */

Specifiers for which addresses are present in the messages are:

#define RTA_DST       0x1    /* destination sockaddr present */
#define RTA_GATEWAY   0x2    /* gateway sockaddr present */
#define RTA_NETMASK   0x4    /* netmask sockaddr present */
#define RTA_GENMASK   0x8    /* cloning mask sockaddr present */
#define RTA_IFP       0x10   /* interface name sockaddr present */
#define RTA_IFA       0x20   /* interface addr sockaddr present */
#define RTA_AUTHOR    0x40   /* sockaddr for author of redirect */


IP
==

Name
----
IP - Internet Protocol

Synopsis
--------

#include "sys/socket.h"
#include "netinet/in.h"

int socket(AF_INET, SOCK_RAW, proto);

Description
-----------
IP is the transport layer protocol used by the Internet protocol family.
Options may be set at the IP level when using higher-level protocols that
are based on IP (such as TCP and UDP).  It may also be accessed through a
'raw socket' when developing new protocols, or special-purpose
applications.

There are several IP-level setsockopt/getsockopt options.
IP_OPTIONS may be used to provide IP options to be transmitted in the IP
header of each outgoing packet or to examine the header options on incom-
ing packets.  IP options may be used with any socket type in the Internet
family.  The format of IP options to be sent is that specified by the IP
protocol specification (RFC-791), with one exception: the list of
addresses for Source Route options must include the first-hop gateway at
the beginning of the list of gateways. The first-hop gateway address will
be extracted from the option list and the size adjusted accordingly
before use.  To disable previously specified options, use a zero-length
buffer:

     setsockopt(s, IPPROTO_IP, IP_OPTIONS, NULL, 0);
 
IP_TOS and IP_TTL may be used to set the type-of-service and time-to-live
fields in the IP header for SOCK_STREAM and SOCK_DGRAM sockets. For
example,

     int tos = IPTOS_LOWDELAY;       /* see <netinet/in.h> */
     setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));

     int ttl = 60;                   /* max = 255 */
     setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));

If the IP_RECVDSTADDR option is enabled on a SOCK_DGRAM socket, the
recvmsg call will return the destination IP address for a UDP datagram. 
The msg_control field in the msghdr structure points to a buffer that
contains a cmsghdr structure followed by the IP address.  The cmsghdr
fields have the following values:

     cmsg_len = sizeof(struct in_addr)
     cmsg_level = IPPROTO_IP
     cmsg_type = IP_RECVDSTADDR

Multicast Options:

IP multicasting is supported only on AF_INET sockets of type SOCK_DGRAM
and SOCK_RAW, and only on networks where the interface driver supports
multicasting.

The IP_MULTICAST_TTL option changes the time-to-live (TTL) for outgoing
multicast datagrams in order to control the scope of the multicasts:

     u_char ttl;        /* range: 0 to 255, default = 1 */
     setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

Datagrams with a TTL of 1 are not forwarded beyond the local network.
Multicast datagrams with a TTL of 0 will not be transmitted on any
network, but may be delivered locally if the sending host belongs to the
destination group and if multicast loopback has not been disabled on the
sending socket (see below).  Multicast datagrams with TTL greater than 1
may be forwarded to other networks if a multicast router is attached to
the local network.

For hosts with multiple interfaces, each multicast transmission is sent
from the primary network interface.  The IP_MULTICAST_IF option overrides
the default for subsequent transmissions from a given socket:

     struct in_addr addr;
     setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr));

where "addr" is the local IP address of the desired interface or 
INADDR_ANY to specify the default interface.  An interface's local IP
address and multicast capability can be obtained via the SIOCGIFCONF and
SIOCGIFFLAGS ioctls.  Normal applications should not need to use this
option.

If a multicast datagram is sent to a group to which the sending host
itself belongs (on the outgoing interface), a copy of the datagram is,
by default, looped back by the IP layer for local delivery.  The 
IP_MULTICAST_LOOP option gives the sender explicit control over whether
or not subsequent datagrams are looped back:

     u_char loop;       /* 0 = disable, 1 = enable (default) */
     setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));

This option improves performance for applications that may have no more
than one instance on a single host (such as a router demon), by eliminat-
ing the overhead of receiving their own transmissions.  It should
generally not be used by applications for which there may be more than
one instance on a single host (such as a conferencing program) or for
which the sender does not belong to the destination group (such as a
time querying program).

A multicast datagram sent with an initial TTL greater than 1 may be
delivered to the sending host on a different interface from that on which
it was sent, if the host belongs to the destination group on that other
interface.  The loopback control option has no effect on such delivery.

A host must become a member of a multicast group before it can receive 
datagrams sent to the group.  To join a multicast group, use the
IP_ADD_MEMBERSHIP option:

     struct ip_mreq mreq;
     setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

where mreq is the following structure:

     struct ip_mreq {
         struct in_addr imr_multiaddr; /* multicast group to join */
         struct in_addr imr_interface; /* interface to join on */
     }

imr_interface should be INADDR_ANY to choose the default multicast inter-
face, or the IP address of a particular multicast-capable interface if
the host is multihomed.  Membership is associated with a single
interface; programs running on multihomed hosts may need to join the same
group on more than one interface.  Up to IP_MAX_MEMBERSHIPS (currently
20) memberships may be added on a single socket.

To drop a membership, use:

     struct ip_mreq mreq;
     setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));

where mreq contains the same values as used to add the membership.
Memberships are dropped when the socket is closed or the process exits.  

Raw IP Sockets:

Raw IP sockets are connectionless, and are normally used with the sendto
and recvfrom calls, though the connect call may also be used to fix
the destination for future packets (in which case the socketread or recv
and socketwrite or send socket calls may be used).

If proto is 0, the default protocol IPPROTO_RAW is used for outgoing
packets, and only incoming packets destined for that protocol are
received.  If proto is non-zero, that protocol number will be used on
outgoing packets and to filter incoming packets.

Outgoing packets automatically have an IP header prepended to them (based
on the destination address and the protocol number the socket is created
with), unless the IP_HDRINCL option has been set.  Incoming packets are
received with IP header and options intact.

IP_HDRINCL indicates the complete IP header is included with the data and
may be used only with the SOCK_RAW type.

     #include <netinet/ip.h>
     
     int hincl = 1;                  /* 1 = on, 0 = off */
     setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl));

Unlike previous BSD releases, the program must set all the fields of the
IP header, including the following:

     ip->ip_v = IPVERSION;
     ip->ip_hl = hlen >> 2;
     ip->ip_id = 0;  /* 0 means kernel set appropriate value */
     ip->ip_off = offset;

If the header source address is set to INADDR_ANY, the kernel will choose
an appropriate address. 

Diagnostics
-----------
A socket operation may fail with one of the following errors returned:

[EISCONN]        when trying to establish a connection on a socket which
                 already has one, or when trying to send a datagram with
                 the destination address specified and the socket is
                 already connected;

[ENOTCONN]       when trying to send a datagram, but no destination
                 address is specified, and the socket hasn't been
                 connected;

[ENOBUFS]        when the system runs out of memory for an internal data
                 structure;

[EADDRNOTAVAIL]  when an attempt is made to create a socket with a
                 network address for which no network interface exists.

[EACESS]         when an attempt is made to create a raw IP socket by a
                 non-privileged process.

The following errors specific to IP may occur when setting or getting IP
options:

[EINVAL]         An unknown socket option name was given.

[EINVAL]         The IP option field was improperly formed; an option
                 field was shorter than the minimum value or longer than
                 the option buffer provided.


TCP
===

Name
----
TCP - Internet Transmission Control Protocol

Synopsis
--------
#include <sys/socket.h>
#include <netinet/in.h>

int socket(AF_INET, SOCK_STREAM, 0)

Description
-----------
The TCP protocol provides reliable, flow-controlled, two-way transmission
of data.  It is a byte-stream protocol used to support the SOCK_STREAM
abstraction.  TCP uses the standard Internet address format and, in
addition, provides a per-host collection of 'port addresses'.  Thus,
each address is composed of an Internet address specifying the host and
network, with a specific TCP port on the host identifying the peer
entity.

Sockets utilizing the tcp protocol are either 'active' or 'passive'.
Active sockets initiate connections to passive sockets.  By default TCP
sockets are created active; to create a passive socket the listen
socket call must be used after binding the socket with the bind system
call.  Only passive sockets may use the accept call to accept incoming
connections.  Only active sockets may use the connect call to initiate
connections.  TCP also supports a more datagram-like mode, called
Transaction TCP, which is described in TTCP.

Passive sockets may 'underspecify' their location to match incoming
connection requests from multiple networks.  This technique, termed
'wildcard addressing', allows a single server to provide service to
clients on multiple networks.  To create a socket which listens on all
networks, the Internet address INADDR_ANY must be bound.  The TCP port
may still be specified at this time; if the port is not specified the
system will assign one.  Once a connection has been established the
socket's address is fixed by the peer entity's location.  The address
assigned the socket is the address associated with the network interface
through which packets are being transmitted and received.  Normally this
address corresponds to the peer entity's network.

TCP supports a number of socket options which can be set with
setsockopt and tested with getsockopt:

TCP_NODELAY  Under most circumstances, TCP sends data when it is
             presented; when outstanding data has not yet been
             acknowledged, it gathers small amounts of output to be sent
             in a single packet once an acknowledgement is received. For
             a small number of clients, such as window systems that send
             a stream of mouse events which receive no replies, this
             packetization may cause significant delays.  The boolean
             option TCP_NODELAY defeats this algorithm.

TCP_MAXSEG   By default, a sender- and receiver-TCP will negotiate among
             themselves to determine the maximum segment size to be used
             for each connection.  The TCP_MAXSEG option allows the user
             to determine the result of this negotiation, and to reduce
             it if desired.

TCP_NOOPT    TCP usually sends a number of options in each packet,
             corresponding to various TCP extensions which are provided
             in this implementation.  The boolean option TCP_NOOPT is
             provided to disable TCP option use on a per-connection
             basis.

TCP_NOPUSH   By convention, the sender-TCP will set the 'push' bit and
             begin transmission immediately (if permitted) at the end of
             every user call to socketwrite or socketwritev.  The TCP_NOPUSH
             option is provided to allow servers to easily make use of
             Transaction TCP (see TTCP).  When the option is set to a
             non-zero value, TCP will delay sending any data at all until
             either the socket is closed, or the internal send buffer is
             filled.

The option level for the setsockopt call is the protocol number for
TCP, available from getprotobyname, or IPPROTO_TCP.  All options are
declared in "netinet/tcp.h".

Options at the IP transport level may be used with TCP; see IP.  
Incoming connection requests that are source-routed are noted, and the
reverse source route is used in responding.

MIB variables
-------------

The TCP protocol implements three variables in the net.inet branch of the
sysctl MIB.

TCPCTL_DO_RFC1323  (tcp.rfc1323) Implement the window scaling and time-
                   stamp options of RFC 1323 (default true).

TCPCTL_DO_RFC1644  (tcp.rfc1644) Implement Transaction TCP, as described
                   in RFC 1644.

TCPCTL_MSSDFLT     (tcp.mssdflt) The default value used for the maximum
                   segment size ('MSS') when no advice to the contrary
                   is received from MSS negotiation.

Diagnostics
-----------
A socket operation may fail with one of the following errors returned:

[EISCONN]        when trying to establish a connection on a socket which
                 already has one;

[ENOBUFS]        when the system runs out of memory for an internal data
                 structure;

[ETIMEDOUT]      when a connection was dropped due to excessive
                 retransmissions;

[ECONNRESET]     when the remote peer forces the connection to be closed;

[ECONNREFUSED]   when the remote peer actively refuses connection
                 establishment (usually because no process is listening
                 to the port);

[EADDRINUSE]     when an attempt is made to create a socket with a port
                 which has already been allocated;

[EADDRNOTAVAIL]  when an attempt is made to create a socket with a
                 network address for which no network interface exists.

[EAFNOSUPPORT]   when an attempt is made to bind or connect a socket to a
                 multicast address.

See also
--------
"TCP Extensions for High Performance", RFC 1323, V. Jacobson, R. Braden,
and D. Borman

"T/TCP - TCP Extensions for Transactions", RFC 1644, R. Braden


TTCP
====

Name
----
     TTCP - Transmission Control Protocol Extensions for Transactions

Synopsis
--------
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

int setsockopt(sock, IPPROTO_TCP, TCP_NOPUSH, &One, sizeof One)

int sendto(sock, msg, len, MSG_EOF, &sin, sizeof sin)

int sendto(sock, msg, len, MSG_EOF, 0, 0)

Description
-----------
T/TCP refers to a set of extensions to the TCP protocol (see TCP)
which permit hosts to reliably exchange a small amount of data in a two-
packet exchange, thus eliminating the extra round-trip delays inherent in
a standard TCP connection.  The socket interface includes modifications
to support T/TCP, detailed here for the specific case, and in the
socket and send manual pages for the protocol-independent support.
T/TCP is defined in RFC 1644.

The T/TCP extensions work by including certain options in all segments of
a particular connection, which enable the implementation to avoid the
three-way handshake for all but the first connection between a pair of
hosts.  These same options also make it possible to more reliably
recognize old, duplicate packets, which in turn reduces the amount of
time the TCP protocol must maintain state after a connection closes.  The
net.inet.tcp.rfc1644 MIB variable can be used to disable T/TCP
negotiation at run time; however, the protocol has been designed to
ensure that attempts by non-T/TCP systems to communicate with T/TCP-
enhanced ones automatically degenerate into standard TCP.

Transaction model
-----------------
The expected model of a "transaction" as used by T/TCP is a fairly simple
one:

1)  A client program generates a request to be sent to the server, which
    is small enough to fit in a single TCP segment, and sends a SYN PUSH
    FIN segment with options and data to the server.
    
2)  The server program accepts the request in the same manner as for
    regular TCP connections, interprets it, and generates a reply which
    may be small enough to fit in a single segment.  If it is, the reply
    is sent in a single SYN PUSH FIN ACK segment with (different) options
    and data back to the client.  If not, then the connection degenerates
    into (almost) the usual case for TCP.

Client support
--------------
Support on the client side is provided by extending the semantics of the
sendto and sendmsg system calls to understand the notion of implied
connect and send and shutdown.  To send the request in a transaction, the
sendto system call is typically used, as in the following example:

     char request[REQ_LEN];
     struct sockaddr_in sin;
     int sock, req_len;

     sock = socket(PF_INET, SOCK_STREAM, 0);

     /* prepare request[] and sin */

     err = sendto(sock, request, req_len, MSG_EOF, 
             (struct sockaddr *)&sin, sin.sin_len);

     /* do something if error */

     req_len = socketread(sock, request, sizeof request);
     socketclose(sock);

     /* do something with the reply */


Note that, after the call to sendto, the socket is now in the same state
as if the connect and shutdown system calls had been used.  That is
to say, the only reasonable operations to perform on this socket are
socketread and socketclose.  (Because the client's TCP sender is already shut
down, it is not possible to connect this socket to another destination.)

Server support
--------------
There are two different options available for servers using T/TCP:

1)  Set the TCP_NOPUSH socket option, and use normal socketwrite calls when
    formulating the response.

2)  Use sendto with the MSG_EOF flag, as in the client, but with the
    destination unspecified.

The first option is generally the appropriate choice when converting
existing servers to use T/TCP extensions; simply add a call to
setsockopt(sock, IPPROTO_TCP, TCP_NOPUSH, &One, sizeof One) (where One is
an integer variable with a non-zero value).  The server socket must be
closed before any data is sent (unless the socket buffers fill up).

The second option is preferable for new servers, and is sometimes easy
enough to retrofit into older servers.  In this case, where the reply
phase would ordinarily have included a call to socketwrite, one substitutes
sendto(sock, reply_buf, reply_len, MSG_EOF, (struct sockaddr *)0, 0).  In
this case, the reply is sent immediately, but as in the client case, the
socket is no lnoger useful for anything and should be immediately closed.

MIB variables
-------------
The T/TCP extensions require the net.inet.tcp.rfc1323 and
net.inet.tcp.rfc1644 MIB variables to both be true in order for the
appropriate TCP options to be sent.  See tcp(4) for more information.


See also
--------
R. Braden, "T/TCP - TCP Extensions for Transactions", RFC 1644

History
-------
Support for T/TCP first appeared in Internet 5.00.
                              

                                *****************
                                * LIBRARY CALLS *
                                *****************


ACCEPT
======
New variants: naccept and oaccept

ACCESS
======
New prototype: int access(const char *path, int mode);

BIND
====
New prototype: int bind(int s, const struct sockaddr *name, int namelen);

BSTRING
=======
New prototypes: int bcmp(const void *s1, const void *s2, unsigned int length);
                void bcopy(const void *src, void *dst, unsigned int length);
                void bzero(void *s, unsigned int length);

CHDIR
=====
New prototype: int chdir(const char *dir);

CHMOD
=====
New prototype: int chmod(const char *path, unsigned short mode);

CONNECT
=======
New prototype: int connect(int s, const struct sockaddr *name, int namelen);

_COPYERROR
==========

Name
----
_copyerror - fill in errno and _inet_error.

Synopsis
--------
#include "kernel.h"
int _copyerror(_kernel_oserror *e);

Description
-----------
_Copyerror is used by Socklib for all Socket_... SWI calls it makes. If a SWI
returns an error, then _copyerror is called. Copyerror takes the following
actions:

_Copyerror copies the supplied error block into the global error structure
_inet_error. It then sets errno from the SWI's returned error number, converting
standard Internet errors (ie those returned by the SWI in the range &20E00 -
&20E7F) to the values used in C by subtracting &20E00. If - after that - the value
of errno is still greater than EREMOTE, makecall then sets errno to ESRCH.
Finally, _copyerror returns a value of -1.

Exported by
-----------
Socklib


ERR
===

Name
----
err, verr, errx, verrx, warn, vwarn, warnx, vwarnx, err_set_file,
err_set_exit - formatted error messages

Synopsis
--------

#include "err.h"

extern char *__progname;

void err(int eval, const char *fmt, ...);
void verr(int eval, const char *fmt, va_list args);
void errx(int eval, const char *fmt, ...);
void verrx(int eval, const char *fmt, va_list args);
void warn(const char *fmt, ...);
void vwarn(const char *fmt, va_list args);
void warnx(const char *fmt, ...);
void vwarnx(const char *fmt, va_list args);

void err_set_file(void *fp);
void err_set_exit(void (*exitf)(int));

The err family of functions display a formatted error message on the standard
error output, or on another file specified using the err_set_file function.
In all cases, the last component of the program name, a colon character,
and a space are output. 

Under RISC OS, to use these functions, you need to define a global variable
__progname containing the name of the program.

If the fmt argument is not NULL, the formatted error message, a colon
character, and a space are output. In the case of the err, verr, warn, and
vwarn functions, the error message string affiliated with the last error from
socklib (as obtained by the _inet_err function) is output. In all cases, the
output is followed by a newline character.

The err, verr, errx, and verrx functions do not return, but exit with the value
of the argument eval. The err_set_exit function can be used to specify a
function which is called before exit(), to perform any necessary cleanup;
passing a null function pointer for exitf resets the hook to do nothing.

Examples
--------
Display the current errno information string and exit:

        if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
                err(1, NULL);

Display an error message and exit:

        if (tm.tm_hour < START_TIME)
                errx(1, "too early, wait until %s", start_time_string);

Warn of an error:

        if (socketioctl(s, FIONBIO, &on) < 0)
                warn(1, "socketioctl(FIONBIO) failed");

Exported by
-----------
UnixLib

ERRNO
=====

Unixlib no longer exports an "errno" variable - instead it uses the
"__errno" defined in <errno.h>, stored in the shared C library stubs. (errno
is #defined to __errno in <errno.h>). This prevents potential problems where
source files that included <errno.h> used to "see" the wrong errno variable.

FSTAT
=====

New prototype: int fstat(int s, struct stat *buf);

GETEGID
=======

New prototype: unsigned long getegid(void);

GETGROUPS
=========

New prototype: int getgroups(int ngrps, unsigned long grparray[]);

GETHOSTBYNAME
=============
New prototypes: struct hostent *gethostbyname(const char *name);
                struct hostent *gethostbyaddr(const char *addr, int len, int type);

gethostbyaddr will now attempt to do its reverse name lookup using a DNS resolver
module, if present.

GETNETENT
=========
New prototypes: struct netent *getnetbyname(const char *name);
                struct netent *getnetbyaddr(long net, int type);

GETOPT
======

Name
----
getopt - get option character from command line argument list

Synopsis
--------
#include <stdlib.h>

extern char *optarg;
extern int   optind;
extern int   optopt;
extern int   opterr;
extern int   optreset;

int getopt(int argc, char *const *argv, const char *optstring);

Description
-----------
The getopt function incrementally parses a command line argument list argv
and returns the next known option character. An option character is known if
it has been specified in the string of accepted option characters, optstring.

The option string optstring may contain the following elements: individual
characters, and characters followed by a colon to indicate an option argument
is to follow. For example, an option string "x" recognizes an option "-x",
and an option string "x:" recognizes an option and argument "-x argument".
It does not matter to getopt if a following argument has leading white space.

On return from getopt, optarg points to an option argument, if it is
anticipated, and the variable optind contains the index to the next argv
argument for a subsequent call to getopt. The variable optopt saves the last
_known_ option character returned by getopt.

The variables opterr and optind are both initialized to 1. The optind variable
may be set to another value before a set of calls to getopt in order to skip
over more or less argv entries.

In order to use getopt to evaluate multiple sets of arguments, or to evaluate
a single set of arguments multiple times, the variable optreset must be set
to 1 before the second and each additional set of calls to getopt, and the
variable optind must be reinitialized.

The getopt function returns an EOF when the argument list is exhausted, or a
non-recognized option is encountered. The interpretation of options in the
argument list may be canceled by the option -- (double dash) which causes
getopt to signal the end of argument processing and return an EOF. When all
options have been processed (i.e., up to the first non-option argument),
getopt returns EOF.

Diagnostics
-----------
If the getopt function encounters a character not found in the string optarg
or detects a missing option argument it writes an error message to the stderr
and returns '?'. Setting opterr to a zero will disable these error messages.
If optstring has a leading ":" then a missing option argument causes a
':' to be returned in addition to suppressing any error messages.

Option arguments are allowed to begin with "-"; this is reasonable but
reduces the amount of error checking possible.

Extensions
----------
The optreset variable was added to make it possible to call the getopt
function multiple times. This is an extension to the IEEE 1003.2
specification.

Example
-------             
        extern char *optarg;
        extern int optind;
        int bflag, ch, fd;
        
        bflag = 0;
        while ((ch = getopt(argc, argv, "bf:")) != EOF)
                switch(ch) {
                case 'b':
                        bflag = 1;
                        break;
                case 'f':
                        if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
                                (void)fprintf(stderr,
                            "myname: %s: %s\en", optarg, strerror(errno));
                        exit(1);
                }
                        break;
                case '?':
                default:
                        usage();
        }
        argc -= optind;
        argv += optind;

Notes
-----
A single dash "-" may be specified as an character in optstring, however it
should never have an argument associated with it. This allows getopt to be
used with programs that expect "-" as an option flag. This practice is wrong,
and should not be used in any current development. It is provided for
backward compatibility _only_. By default, a single dash causes getopt to
return EOF. This is, we believe, compatible with System V.

It is also possible to handle digits as option letters. This allows getopt
to be used with programs that expect a number ("-3") as an option. This
practice is wrong, and should not be used in any current development. It is
provided for backward compatibility _only_. The following code fragment works
in most cases.

        int length;
        char *p;
        
        while ((c = getopt(argc, argv, "0123456789")) != EOF)
                switch (c) {
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                        p = argv[optind - 1];
                        if (p[0] == '-' && p[1] == ch && !p[2])
                                length = atoi(++p);
                        else
                                length = atoi(argv[optind] + 1);
                        break;
                }
        }

Exported by
-----------
UnixLib


GETPASS
=======
New prototype: char *getpass(const char *prompt);

GETPEERNAME
===========
New variants: ngetpeername and ogetpeername

GETPID
======
New prototype: long getpid(void);

GETPROTOENT
===========
New prototype: struct protoent *getprotobyname(const char *name);

GETPWENT
========

New prototypes: int setpwent(void);
                struct passwd *getpwnam(const char *name);
                struct passwd *getpwuid(unsigned long uid);

GETSERVENT
==========
New prototypes: struct servent *getservbyname(const char *name, const char *proto);
                struct servent *getservbyport(int port, const char *proto);

GETSOCKNAME
===========
New variants: ngetsockname and ogetsockname

GETSOCKOPT
==========
New prototype: int setsockopt(int s, int level, int optname, const void *optval,
                              int optlen);

New options:
          SO_REUSEPORT   enables duplicate address and port bindings
          SO_SNDLOWAT    set minimum count for output
          SO_RCVLOWAT    set minimum count for input
          SO_SNDTIMEO    set timeout value for output
          SO_RCVTIMEO    set timeout value for input

SO_REUSEPORT allows completely
duplicate bindings by multiple processes if they all set SO_REUSEPORT before
binding the port.  This option permits multiple instances of a program to
each receive UDP/IP multicast or broadcast datagrams destined for the bound
port.

SO_SNDLOWAT is an option to set the minimum count for output operations. Most
output operations process all of the data supplied by the call, delivering
data to the protocol for transmission and blocking as necessary for flow
control.  Nonblocking output operations will process as much data as
permitted subject to flow control without blocking, but will process no data
if flow control does not allow the smaller of the low water mark value or the
entire request to be processed.  A select operation testing the ability to
write to a socket will return true only if the low water mark amount could be
processed.  The default value for SO_SNDLOWAT is set to a convenient size for
network efficiency, often 1024.  SO_RCVLOWAT is an option to set the minimum
count for input operations.  In general, receive calls will block until any
(non-zero) amount of data is received, then return with the smaller of the
amount available or the amount requested.  The default value for SO_RCVLOWAT
is 1.  If SO_RCVLOWAT is set to a larger value, blocking receive calls
normally wait until they have received the smaller of the low water mark
value or the requested amount.  Receive calls may still return less than the
low water mark if an error occurs, a signal is caught, or the type of data
next in the receive queue is different than that returned.

SO_SNDTIMEO is an option to set a timeout value for output operations.  It
accepts a struct timeval parameter with the number of seconds and micro-
seconds used to limit waits for output operations to complete.  If a send
operation has blocked for this much time, it returns with a partial count or
with the error EWOULDBLOCK if no data were sent.  In the current
implementation, this timer is restarted each time additional data are
delivered to the protocol, implying that the limit applies to output portion
ranging in size from the low water mark to the high water mark for output.
SO_RCVTIMEO is an option to set a timeout value for input operations.  It
accepts a struct timeval parameter with the number of seconds and micro-
seconds used to limit waits for input operations to complete.  In the
current implementation, this timer is restarted each time additional data are
received by the protocol, and thus the limit is in effect an inactivity
timer.  If a receive operation has been blocked for this much time without
receiving additional data, it returns with a short count or with the error
EWOULDBLOCK if no data were received.

GETUID
======
New prototypes: unsigned long getuid(void);
                unsigned long geteuid(void);



INET_ADDR
=========
New prototypes: u_long inet_addr(const char *cp);
                u_long inet_network(const char *cp);
                struct in_addr inet_makeaddr(u_long net, u_long host);

_INET_ERROR
===========

A new function has been defined:

    char *_inet_err(void);

This returns the errmess field from _inet_error. It is provided as a simpler
way of obtaining the previous error message than accessing _inet_error->errmess
directly.

IOCTL
=====
New prototype: int ioctl(int s, unsigned long cmd, ...);

ISO_ADDR
========

Name
----
iso_addr, iso_ntoa - elementary network address conversion routines for
Open System Interconnection

Synopsis
--------
#include <sys/types.h>
#include <netiso/iso.h>

struct iso_addr *iso_addr(char *cp);
char *ison_ntoa(struct iso_addr *isoa);

Description
-----------
The routine iso_addr interprets character strings representing OSI addresses,
returning binary information suitable for use in system calls. The routine
iso_ntoa takes OSI addresses and returns ASCII strings representing NSAPs
(network service access points) in a notation inverse to that accepted by 
iso_addr.

Unfortunately, no universal standard exists for representing OSI network
addresses.

The format employed by iso_addr is a sequence of hexadecimal digits (optionally
separated by periods), of the form:

        <hex digits>.<hex digits>.<hex digits>

Each pair of hexadecimal digits represents a byte with the leading digit
indicating the higher-ordered bits. A period following an even number of bytes
has no effect (but may be used to increase legibility). A period following an
odd number of bytes has the effect of causing the byte of address being
translated to have its higher order bits filled with zeros.

Return values
-------------
iso_ntoa always returns a null terminated string. iso_addr always returns a
pointer to a struct iso_addr.

Notes
-----
The returned values reside in a static memory area. The RISC OS Internet module
does not support OSI networking, so these functions are not of immediate use.

Exported by
-----------
Inetlib

KILLFILE
========
New prototype: void killfile(const char *name);

KVM
===

Name
----
KVM - kernel memory interface

Synopsis
--------
#include "kvm.h"

kvm_t *kvm_open(const char *uf, const char *mf, const char *sf,
                int flag, const char *errout);

kvm_t *kvm_openfiles(const char *uf, const char *mf, const char *sf,
                     int flag, char *errout);

int kvm_close(kvm_t *kd);
int kvm_read(kvm_t *kd, unsigned long kva, void *buf, size_t len);
char *kvm_geterr(kvm_t *kd);

Description
-----------
The KVM library in Unix provides a uniform interface for accessing kernel
virtual memory images, including live systems and crash dumps. Under RISC OS
the KVM functions are used by support utilities such as InetStat to access
internal variables in the Internet module. The Internet module provides
a restricted implementation of the kvm_nlist function, and Unixlib provides
the dummy functions above to aid Unix compatibility. kvm_open, kvm_openfiles,
kvm_close and kvm_err do nothing, while kvm_read simply treats kva as a pointer
and does memcpy(buf, (void *) kva, len).

These functions should not be used by normal programs; they are documented here
for completeness only.

Exported by
-----------
Unixlib


KVM_NLIST
=========

Name
----
kvm_nlist - retrieve symbol table from the internet module

Synopsis
--------
#include "kvm.h"
#include "nlist.h"

int kvm_nlist(kvm_t *kd, struct nlist *nl);

Description
-----------
This function is for the internal use of support utilities such as InetStat;
it permits access to named variables inside the Internet module. Any program
that uses this function is liable to break on future versions of the
Internet module. It is documented here for completeness only.

kvm_nlist retrieves the symbol table entries indicated by the name list
argument nl. This argument points to an array of nlist structures,
terminated by an entry whose n_name field is NULL. Each symbol is looked up
using the n_name field, and if found, the corresponding n_type and n_value
fields are filled in.  These fields are set to 0 if the symbol is not found.

Under RISC OS, the kd parameter does not signify anything; it should be
NULL. All available symbols under RISC OS are of type N_ABS, and can the
n_value field is an absolute pointer to the relevant data.

Return values
-------------
The kvm_nlist function returns the number of invalid entries found. If the kernel
symbol table was unreadable, -1 is returned.

See also
--------
KVM

Exported by
-----------
Socklib


LINK_ADDR
=========

Name
----
link_addr, link_ntoa - elementary address specification routines for link level
access

Synopsis
--------
#include "sys/types.h"
#include "sys/socket.h"
#include "net/if_dl.h"

void link_addr(const char *addr, struct sockaddr_dl *sdl);
char *link_ntoa(const struct sockaddr_dl *sdl);

Description
-----------
The routine link_addr interprets character strings representing link-level
addresses, returning binary information suitable for use in system calls.
The routine link_ntoa takes a link-level address and returns an ASCII string
representing some of the information present, including the link level address
itself, and the interface name or number, if present. This facility is
experimental and is still subject to change.

For link_addr, the string addr may contain an optional network interface
identifier of the form "name unit-number", suitable for the first argument to
IfConfig, followed in all cases by a colon and an interface address in the form
of groups of hexadecimal digits separated by periods. Each group represents a
byte of address; address bytes are filled left to right from low order bytes
through high order bytes.

Thus "ea0:8.0.9.13.d.30" represents an ethernet address to be transmitted on
the first Ethernet III interface.

Notes
-----
The returned values for link_ntoa reside in a static memory area.

If the sdl_len field of the link socket address sdl is 0, link_ntoa will not
insert a colon before the interface address bytes. If this translated address
is given to link_addr without inserting an initial colon, the latter will not
interpret it correctly.

Exported by
-----------
Inetlib


LISTEN
======
The backlog is no longer limited to 5 in Internet 5.


_MAKECALL
=========
Makecall is no longer used by Socklib, but is still exported for backwards
compatibility. See _COPYERROR.


NAMISIPADR
==========
New prototype: struct hostent *namisipadr(const char *name);


NS
==

Name
----
ns_addr, ns_ntoa - Xerox NS (tm) address conversion routines

Synopsis
--------
#include "sys/types.h"
#include "netns/ns.h"

struct ns_addr ns_addr(char *cp);
char *ns_ntoa(struct ns_addr ns);

Description
-----------
The routine ns_addr interprets character strings representing XNS addresses,
returning binary information suitable for use in system calls. The routine
ns_ntoa takes XNS addresses and returns ASCII strings representing the address
in a notation in common use in the Xerox Development Environment:

        <network number>.<host number>.<port number>

Trailing zero fields are suppressed, and each number is printed in hexadecimal,
in a format suitable for input to ns_addr. Any fields lacking super-decimal
digits will have a trailing "H" appended.

Unfortunately, no universal standard exists for representing XNS addresses.
An effort has been made to insure that ns_addr be compatible with most formats
in common use. It will first separate an address into 1 to 3 fields using a
single delimiter chosen from period ".", colon ":" or hash "#".

Each field is then examined for byte separators (colon or period). If there are
byte separators, each subfield separated is taken to be a small hexadecimal
number, and the entirety is taken as a network-byte-ordered quantity to be zero
extended in the high-network-order bytes. Next, the field is inspected for
hyphens, in which case the field is assumed to be a number in decimal notation
with hyphens separating the millenia. Next, the field is assumed to be a number:
It is interpreted as hexadecimal if there is a leading "0x" (as in C), a
trailing "H" (as in Mesa), or there are any super-decimal digits present. It is
interpreted as octal is there is a leading "0" and there are no super-octal
digits. Otherwise, it is converted as a decimal number.

Notes
-----
The string returned by ns_ntoa resides in a static memory area. The RISC OS
Internet module does not support XNS networking, so these functions are not of
immediate use.

Exported by
-----------
Inetlib


READ
====

New prototype: int read(int d, void *buf, unsigned int nbytes);
               int readv(int d, const struct iovec *iov, int iovcnt);

READDIR
=======
New prototype: int readdir(const char *path, char *buf, int len,
                           const char *name, int offset);

RECV
====
New prototypes: int recv(int s, void *buf, size_t len, int flags);
                int recvfrom(int s, void *buf, size_t len, int flags,
                             struct sockaddr *from, int *fromlenaddr);
                int recvmsg(int s, struct msghdr *msg, int flags);
New variants: nrecvfrom, nrecvmsg, orecvfrom, orecvmsg

SEND
====
New prototypes: int send(int s, const void *msg, size_t len, int flags);
                int sendmsg(int s, const struct msghdr *msg, int flags);
                int sendto(int s, const void *msg, size_t len, int flags,
                           const struct sockaddr *to, int tolen);

SOCKETIOCTL
===========
New prototype: int socketioctl(int s, unsigned long cmd, ...);

Some ioctls that return sockaddr structures now have old and new forms (in
the same way as the functions naccept, oaccept, etc) that return old and
new-style sockaddrs. In particular, beware of SIOCGIFCONF, which in its new
form no longer returns an evenly spaced array of sockaddrs - each entry is
now of variable length, determined by the sa_len field.

There is a new RISC OS-specific ioctl FIOSLEEPTW. If this is enabled (in the
same way as FIONBIO), a blocking socket call in a program running in a task
window will cause the TaskWindow to sleep. In Internet 5.18 and later,
mixing sockets using FIOSLEEPTW and those which do not as parameters to
select will now cause TaskWindow to sleep - earlier versions would act
differently based on the socket numbers in use.

Internet module versions after 5.42 provide a new RISC OS-specific
FIOPOLLWORD. This takes a pointer to two 32bit values :

struct {
  unsigned long *pollword;
  unsigned int bit;
} pollword_parameter;

The pollword pointer must be word aligned and must reference globally accessible
memory, such as the RMA or a Dynamic Area. The bit number must be in the range
0-31. When an event occurs for socket that would raise an asynchronous signal
(the Internet event), the specified bit within the pollword will be set.
Such pollwords can be disabled by setting the pollword pointer to 0.



SOCKETREAD
==========
New prototypes: int socketread(int s, void *buf, unsigned int len);
                int socketreadv(int s, const struct iovec *iov, int iovcnt);

SOCKETWRITE
===========
New prototypes: int socketwrite(int s, const void *buf, unsigned int len);
                int socketwritev(int s, const struct iovec *iov, int iovcnt);

SOCKETVERSION
=============

Name
----
socketversion - return version of loaded internet module

Synopsis
--------
int socketversion(void);

Description
-----------
The socketversion function returns the version number of the Internet module
currently loaded, times 100. For example, Internet 5.02 will return 502.
As this SWI only appeared in Internet 5.00, older versions of the Internet
module will return an error. Therefore the following code is suggested:

        inet_version = socketversion();
        if (inet_version < 0)
            inet_version = 407; /* Assume 4.07 if socketversion() fails */

Exported by
-----------
Socklib


STRING
======

New prototypes: char *index(const char *s, int c);
                char *rindex(const char *s, int c);
                int strcasecmp(const char *s1, const char *s2);
                int strncasecmp(const char *s1, const char *s2, unsigned int n);

STRSEP
======

Name
----
strsep - separate strings

Synopsis
--------
char *strsep(char **stringp, char *delim);

Description
-----------
The strsep function locates, in the string referenced by *stringp, the first
occurrence of any character in the string delim (or the terminating '\0'
character) and replaces it with a '\0'. The location of the next character
after the delimiter character (or NULL, if the end of the string was reached)
is stored in *stringp. The original value of *stringp is returned.

An "empty" field, i.e. one caused by two adjacent delimiter characters, can
be detected by comparing the location referenced by the pointer returned in
*stringp to '\0'.

If *stringp is initially NULL, strsep returns NULL.

Examples
--------
The following uses strsep to parse a string, containing tokens delimited by
white space, into an argument vector:

        char **ap, *argv[10], *inputstring;
        
        for (ap = argv; (*ap = strsep(&inputstring, " \t")) != NULL;)
                if (**ap != '\0')
                        ++ap;

History
-------
The strsep function is intended as a replacement for the strtok function.
While the strtok function should be preferred for portability reasons (it
conforms to ANSI C) it is unable to handle empty fields, i.e. detect fields
delimited by two adjacent delimiter characters, or to be used for more than
a single string at a time.

Exported by
-----------
UnixLib

SYSCTL
======

Name
----
sysctl - get or set system information

Synopsis
--------
#include "sys/sysctl.h"

int sysctl(int *name, u_int namelen, void *oldp, size_t oldlenp, void *newp,
           size_t newlen);

Description
-----------
The sysctl function retrieves system information and allows processes with
appropriate privileges to set system information. The information available
from sysctl consists of integers, strings, and tables. Information may be
retrieved and set from the command interface using the SysCtl utility. Normal
applications should not alter any variables using sysctl, as these variables
affect the whole system and you could cause problems in other programs.

The state is described using a 'Management Information Base' (MIB) style
name, listed in name, which is a namelen length array of integers.

The information is copied into the buffer specified by oldp. The size of the
buffer is given by the location specified by oldlenp before the call, and
that location gives the amount of data copied after a successful call and
after a call that returns with the error code ENOMEM. If the amount of data
available is greater than the size of the buffer supplied, the call supplies
as much data as fits in the buffer provided and returns with the error code
ENOMEM. If the old value is not desired, oldp and oldlenp should be set to
NULL.

The size of the available data can be determined by calling sysctl with a
NULL parameter for oldp. The size of the available data will be returned in
the location pointed to by oldlenp. For some operations, the amount of space
may change often. For these operations, the system attempts to round up so
that the returned size is large enough for a call to return the data shortly
thereafter.

To set a new value, newp is set to point to a buffer of length newlen from
which the requested value is to be taken. If a new value is not to be set,
newp should be set to NULL and newlen set to 0.

The top level names are defined with a CTL_ prefix in "sys/sysctl.h", and are
as follows. The next and subsequent levels down are found in the include
files listed here, and described in separate sections below. However, only
CTL_NET is provided by the Internet module.

        Name            Next level names        Description
        CTL_DEBUG       sys/sysctl.h            Debugging
        CTL_VFS         sys/sysctl.h            File system
        CTL_HW          sys/sysctl.h            Generic CPU, I/O
        CTL_KERN        sys/sysctl.h            High kernel limits
        CTL_MACHDEP     sys/sysctl.h            Machine dependent
        CTL_NET         sys/socket.h            Networking
        CTL_USER        sys/sysctl.h            User-level
        CTL_VM          vm/vm_param.h           Virtual memory

For example, the following retrieves the default TTL for outgoing network
packets:

        int mib[4], maxproc;
        size_t len;

        mib[0] = CTL_NET;
        mib[1] = PF_INET;
        mib[2] = IPPROTO_IP;
        mib[3] = IPCTL_DEFTTL;
        len = sizeof(maxproc);
        sysctl(mib, 4, &maxproc, &len, NULL, 0);

CTL_NET
-------
The string and integer information available for the CTL_NET level is
detailed below. The changeable column shows whether a process with
appropriate privilege may change the value.
                Second level name  Type                 Changeable
                PF_ROUTE           routing messages     no
                PF_INET            internet values      yes

PF_ROUTE Return the entire routing table or a subset of it. The data is
         returned as a sequence of routing messages (see route for the header
         file, format and meaning). The length of each message is contained in
         the message header.

         The third level name is a protocol number, which is currently always 0.
         The fourth level name is an address family, which may be set to 0
         to select all address families. The fifth and sixth level names are
         as follows:

              Fifth level name  Sixth level is:
              NET_RT_FLAGS      rtflags
              NET_RT_DUMP       None
              NET_RT_IFLIST     None

PF_INET  Get or set various global information about the internet protocols.
         The third level name is the protocol. The fourth level name is the
         variable name. The currently defined protocols and names are:

             Protocol name         Variable name      Type       Changeable
             ip                    forwarding         integer    yes
             ip                    redirect           integer    yes
             ip                    ttl                integer    yes
             ip                    rtexpire           integer    yes
             ip                    rtminexpire        integer    yes
             ip                    rtmaxcache         integer    yes
             ip                    sourceroute        integer    yes
             icmp                  maskrepl           integer    yes
             icmp                  stats              structure  no
             igmp                  stats              structure  no
             tcp                   rfc1323            integer    yes
             tcp                   rfc1644            integer    yes
             tcp                   mssdflt            integer    yes
             tcp                   stats              structure  no
             tcp                   rttdflt            integer    yes
             tcp                   keepidle           integer    yes
             tcp                   keepintvl          integer    yes
             tcp                   sendspace          integer    yes
             tcp                   recvspace          integer    yes
             udp                   checksum           integer    yes
             udp                   stats              structure  no
             udp                   maxdgram           integer    yes
             udp                   recvspace          integer    yes

         The variables are as follows:

         [protocol].stats  Returns a structure giving internal statistics for
                        the specified protocol. This is for the use
                        of the InetStat only.
                           
         ip.forwarding  Returns 1 when IP forwarding is enabled for the host,
                        meaning that the host is acting as a router.

         ip.redirect    Returns 1 when ICMP redirects may be sent by the
                        host. This option is ignored unless the host is
                        routing IP packets, and should normally be enabled
                        on all systems.

         ip.ttl         The default time-to-live (hop count) value for an IP
                        packet sourced by the system. This value applies to
                        normal transport protocols, not to ICMP.

         tcp.keepidle   The default number of 'slow timeouts' (1/2 second
                        intervals) that should pass before a TCP connection
                        is probed to keep it alive.

         tcp.keepintvl  The default number of 'slow timeouts' (1/2 second
                        intervals) that should pass after the tcp.keepidle
                        period has elapsed to repeat probes.

         icmp.maskrepl  Returns 1 if ICMP network mask requests are to be
                        answered.

         udp.checksum   Returns 1 when UDP checksums are being computed and
                        checked. Disabling UDP checksums is strongly
                        discouraged.

Files
-----
"sys/sysctl.h"       definitions for top level identifiers, second level
                     kernel and hardware identifiers, and user level
                     identifiers
"sys/socket.h"       definitions for second level network identifiers
"netinet/in.h"       definitions for third level Internet identifiers and
                     fourth level IP identifiers
"netinet/icmp_var.h" definitions for fourth level ICMP identifiers
"netinet/udp_var.h"  definitions for fourth level UDP identifiers

History
-------
The sysctl function first appeared in Internet 5.00.


UNLINK
======
New prototype: int unlink(const char *path);

WRITE
=====
New prototypes: int write(int d, const void *buf, unsigned int nbytes);
                int writev(int d, const struct iovec *iov, int iovcnt);

XPERROR
=======
New prototypes: void xperror(const char *s);
                const char *const sys_errlist[];
                const int sys_nerr;

Note that it is recommended that you do not use these functions, as this
will link into your program a large table of error messages, and the error
messages will not be internationalised. Use _inet_err() in preference.

XSTRERROR
=========

Name
----
strerror - get error message string

Synopsis
--------
char *xstrerror(int errnum);

Description
-----------
xstrerror maps the error number in errnum to an error message string, and
returns a pointer to that string. xstrerror uses the same set of error
messages as xperror. The returned string should not be overwritten.

Notes
-----
This function will _not_ return localised errors - use _inet_err() in
preference.

Exported by
-----------
Unixlib


                                *****************
                                * SERVICE CALLS *
                                *****************

Service_InternetStatus 0 (Service Call &B0)
========================

Issued by the Internet module when the address of an interface has changed

On entry
--------
R0 = 0 (subreason code)
R1 = &B0 (reason code)
R2 -> interface name (eg "ea0")
R3 -> Driver Information Block for interface

On exit
-------
R0-R3 preserved

Use
---
This service call is issued by the Internet module upon successful
completion of an SIOCSIFADDR, SIOCAIFADDR or SIOCDIFADDR socketioctl() call;
ie when an interface address has been changed. Versions of Internet prior
to 5.08 do not supply R2 or R3.

Versions of internet prior to 5.43 do not issue this service when the
address is deleted.

You must not claim this service call.


Service_InternetStatus 1 (Service Call &B0)
========================

Issued by the Net module when the net map has changed

On entry
--------
R0 = 1 (subreason code)
R1 = &B0 (reason code)

On exit
-------
R0,R1 preserved

Use
---
This service call is issued by the Net or NetI modules when it receives new
information about the net map.

You must not claim this service call.


Service_InternetStatus 2 (Service Call &B0)
========================

Issued by the Internet module when an interface goes up or down.

On entry
--------
R0 = 2 (subreason code)
R1 = &B0 (reason code)
R2 = new state (0 = down, 1 = up)
R3 -> interface name (eg "ea0")
R4 -> Driver Information Block for interface

On exit
-------
R0-R4 preserved

Use
---
This service call is issued by the Internet module (version 5.03 or later)
when an interface goes up or down (eg due to an SIOCSIFFLAGS socketioctl()
call).

Versions of Internet prior to 5.43 do not issue this service if the
interface is implicitly brought up or down by the configuration or removal
of addresses.

You must not claim this service call.

  
Service_InternetStatus 3 (Service Call &B0)
========================

Reserved for internal use.

  
Service_InternetStatus 4 (Service Call &B0)
========================

Issued by the Internet module when a BOOTP/DHCP reply has been received.

On entry
--------
R0 = 4 (subreason code)
R1 = &B0 (reason code)
R2 -> interface name (eg "ea0")
R3 -> Driver Information Block for interface
R4 -> DHCP reply message buffer
R5 = size of buffer pointed to by R4

On exit
-------
R0,R2-R5 preserved.
R1 = 0 to claim service call, else preserved.

Use
---
This service call is issued by the Internet module (version 5.28 or later)
when a BOOTP/DHCP reply is received.  You may inspect the contents of the
buffer to extract any configuration information.

If you want to alter information in the buffer you may do so, but you must
then claim the service call by setting R1 to zero on exit.  If the service
call is claimed, the Internet module will reprocess the buffer as if it had
just arrived from the network. Another Service_InternetStatus 4 will arrive
in due course.

You should not normally claim this service call.


Service_InternetStatus 5 (Service Call &B0)
========================

Issued by the DHCP module when it receives a DHCPOFFER message.

On entry
--------
R0 = 5 (subreason code)
R1 = &B0 (reason code)
R2 -> interface name (eg "ea0")
R3 -> Driver Information Block for interface
R4 -> DHCPOFFER message buffer
R5 = size of buffer pointed to by R4

On exit
-------
R0,R2-R5 preserved.
R1 = 0 to claim service call, else preserved.

Use
---

This service call is issued by the DHCPClient module whenever it receives an
offer of an IP address lease which is better than its current best choice
(or if it is the first acceptable offer). You may inspect the buffer, but it
must not be modified.

If clients choose to retain information about offers, they MUST
use the value of OPTION_SERVERIDENTIFIER as an opaque key to identify which
offer has been chosen.

If you claim this service, the DHCPClient module will not accept the offer, but
will wait for another offer to be made.

You should not normally claim this service call.

  
Service_InternetStatus 6 (Service Call &B0)
========================

Reserved for internal use.

  
Service_InternetStatus 7 (Service Call &B0)
========================

Reserved for internal use.


Service_InternetStatus 8 (Service Call &B0)
========================

Issued by the Internet module when a machine is seen to be using the
same IP address as us.

On entry
--------
R0 = 8 (subreason code)
R1 = &B0 (reason code)
R2 -> interface name (eg "ea0")
R3 -> Driver Information Block for interface
R4 = IP address duplicated (network byte order)
R5 -> hardware address of machine with duplicate IP address

On exit
-------
R0,R2-R5 preserved.
R1 = 0 to claim service call, else preserved.

Use
---
This service call is issued by the Internet module (version 5.08 or later)
when it detects a machine using a duplicate IP address. This is normally
detected when an incoming ARP packet is received with our IP address but a
different hardware address.

As a probe, whenever an interface is reconfigured, the Internet module sends
out an ARP requst for our IP address to make any such machines reply. That
will then trigger this service call.

Normally, the Internet module will shut down outright as a safety measure if
this happens. However, if this service call is claimed, it will continue
operation. It is expected that anyone claiming this service call should take
appropriate action; for example the DHCP module might remove our IP address,
send a DHCPDECLINE message and go back into the DHCP INIT state.

  
                                     ********
                                     * SWIS *
                                     ********

In Volume 5a of the PRMs, the calling conditions of the Socket SWIs are not
specified. They are:

SWI Socket_??? (SWI &41200-&4123F)
==================================

On entry
     R0-R9 = parameters passed to corresponding Unix system call

On exit
     R0 = return value (if any), else 0. (Note that Internet 2.11 and earlier
          preserved R0 for calls with no return value).
     R1-R9 preserved

Interrupts
     Interrupts are enabled
     Fast interrupts are not altered

Processor mode
     Processor is in SVC mode, except that blocking I/O operations
     will switch in and out of USR mode.
     
Re-entrancy
     SWIs are not re-entrant


The following new SWIs are provided in Internet 5.00:

SWI name               SWI no   Socklib call
Socket_Accept_1        &4121B   naccept        
Socket_Getpeername_1   &4121F   ngetpeername
Socket_Getsockname_1   &41220   ngetsockname
Socket_InternalLookup  &41221   kvm_nlist
Socket_Recvfrom_1      &4121C   nrecvfrom
Socket_Recvmsg_1       &4121D   nrecvmsg
Socket_Sendmsg_1       &4121E   nsendmsg
Socket_Sysctl          &4121A   sysctl
Socket_Version         &41222   socketversion


In Internet 5.10 and later, addresses passed to the socket SWIs will be
passed through simple checks for their validity to prevent system memory
(below &8000) being overwritten).


                             **********************
                             * THE INTERNET EVENT *
                             **********************

In Volume 5a of the PRMs (and the supplied 'Internet/html' file), the
calling conditions of the Internet event are not specified. They are:

Internet Event
--------------

On entry
     R0 = 19 (Internet event)
     R1 = event subcode (see PRM 5-341)
     R2 = socket descriptor
     NEW in Internet 5.00: for events 1-3 on a PF_INET socket, R3 = local port
     number of socket, for other types of socket (currently only PF_ROUTE),
     R3 is undefined.
     
Interrupts
     Interrupts are disabled
     Fast interrupts are enabled
     
Processor mode
     Processor is in SVC mode
     
Most of the normal restrictions to events _do not_ apply to the internet event.
It is always called from a callback, not from an interrupt, so you are free
to call non-reentrant SWIs, including those of the Internet module itself.

If you are to do any processing on this event, you should enable interrupts.
Interrupts are only disabled on entry because it is an unavoidable feature of
OS_GenerateEvent. You should, however, disable interrupts again before
returning, as other EventV claimants may expect interrupts to be disabled.
If you are writing a module in C, then the following will suffice :

          int event_handler(_kernel_swi_regs *r)
          {
                int claim_event = 0;
                if (r->r[0] != Internet_Event || r->r[1] != Socket_Async_Event) 
                        return 1;
                        
                _kernel_irqs_on();
                
                if (r->r[2] == sock_data)
                {
                        ...
                        claim_event = 1;
                }
                else if (r->r[2] == sock_listen)
                {
                        ...
                        claim_event = 1;
                }
                
                _kernel_irqs_off();
                
                return !claim_event;
          }

Note that the Internet module does not care whether or not the event is
claimed, but if the event is for one of your sockets you should generally
claim the event so that other EventV claimants are not called unnecessarily.

Note that it is quite easy to get yourself into an infinite recursion using
events - calling a Socket SWI can often cause an event to go off, so be
careful when calling them from Internet event handlers. Keep an eye on your
state.

If you are reading data using the Internet event, then you should read all
available data (ie read until you get EWOULDBLOCK) on every event - otherwise
data may get "stuck", as any you will get no more events for any data still
sitting in the buffer.

                             **********************
                             * ALIASED INTERFACES *
                             **********************

From Internet 5.37, support for interface aliasing has been enhanced to
allow for named aliased interfaces. The new interface naming scheme is
compatible with that of earlier versions of the Internet module and
it is unlikely that applications will fail to function with aliased
names. Interface names are now given in the form :

  <interface><unit>[:<alias>]

Where <interface> is given by the device driver (such as 'ea'),
      <unit> is numbered from 0, describing the units provided by the
        device driver (most devices only supply a single unit).
      <alias> is a number from 0, describing the alias for an
        interface.

The primary address of an interface is described without an alias
identifier. Reading non-Internet based information (such as hardware
addresses) will ignore the alias number.

Internet 5.37 to 5.43 allocate alias numbers dynamically, resulting
in non-deterministic behaviour for clients wishing to create aliases
for interfaces. That is, deleting the address associated with 'eh0:0' would
cause eh0:1' to be renumbered to 'eh0:0'. From Internet 5.44 onward, alias
numbers are fixed at their creation and can be referred to directly -
'eh0:1' would remain as 'eh0:1' in the above example.

Aliased interfaces cannot be used for DHCP or BootP (only the primary
address may be obtained through DHCP or BootP). The ioctl call to obtain
interface details, SIOCGIFCONF, will return aliased interfaces as named
above.

Aliased interfaces will not be matched within firewalling rules. Only the
primary interface ('<interface><unit>') will be matched for these rules.

Clients should treat aliased interfaces as separated interfaces where this
is appropriate. For example, where clients wish to broadcast to all
connected networks, all interfaces including those which are aliased should
be considered.
