Acorn TCP/IP libraries version 5.71
-----------------------------------

These libraries are an update to the libraries described in chapter 123 of the PRM
(in volume 5a). They support all the new features of the Internet 5 module supplied
with RISC OS 3.7, 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.

The text below consists of annotations, replacement sections and new sections
to be inserted into chapter 123 of the PRM.

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

   1) In a boot file (eg !SetPaths.!Boot/!Run, or Choices:Boot.PreDesktop) 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) Use ANSI mode, rather than Unix PCC mode. Previous releases of the
      library were not fully ANSI-compatible; this release should be.
   5) Link with TCPIPLibs:o.Socklib5[zm] and, if necessary,
      TCPIPLibs:o.Inetlib[zm] and TCPIPLibs:o.Unixlib[zm], in that order.

Internet 4 migration
--------------------

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.

With this came some changes/extensions to the structure layouts used to
communicate with functions in the Internet module. These additions aimed to:

   * Make the functions extensible for larger (eg IPv6) addresses in future
   * Add fields to allow the expected layout to be deduced for forwards
     compatibility
   * Make the functions safer to call by avoid copying out results into an
     undersize buffer

The socket library functions are ultimately implemented via SWIs. Where the
structure layouts changed, the Internet 5 module added six new SWIs (all
suffixed "_1") to use:

   SWI under Internet 4     SWI under Internet 5
   Socket_Accept            Socket_Accept_1
   Socket_Getpeername       Socket_Getpeername_1
   Socket_Getsockname       Socket_Getsockname_1
   Socket_Recvfrom          Socket_Recvfrom_1
   Socket_Recvmsg           Socket_Recvmsg_1
   Socket_Sendmsg           Socket_Sendmsg_1

   (Those SWIs without a suffixed equivalent are compatible with both)

These SWIs are specific to RISC OS, which makes it difficult to build on top
of software aimed at other operating systems, which is where the socket library
comes in. It provides an interface which uses all the familiar BSD sockets names and
parameters and maps these to RISC OS SWIs.

Currently four versions of the TCP/IP libraries are provided, Socklib[zm] and
Socklib5[zm] from making two selections:

   * The "zm" suffix denotes it is suitable for use with a RISC OS module
   * Whether to provide Internet 4 compatibility or not

Exactly which SWI the library calls (old or new) is based on an opt-in compiler switch COMPAT_INET4.

If you define COMPAT_INET4 (using the -D option of the compiler), the
header files adapt to define struct sockaddr etc. in the old way, and the
library functions will call the old SWIs.

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.

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.

Note that when using COMPAT_INET4 none of the new functionality (eg the PF_ROUTE
socket calls) will be available, and provision for larger addresses in IPv6
is impossible using the old structure layouts. Therefore it is recommended to
update your code to use Internet 5 structure layouts throughout and not rely
on COMPAT_INET4, which is due to be removed.

Even though the library will stop supporting Internet 4, the six old SWIs
will continue to be supported to the extent noted:

   SWI name             Emulation
   Socket_Accept        Socket address limited to IPv4
   Socket_Recvfrom      Socket address limited to IPv4
   Socket_Recvmsg       Access rights field ignored on entry
   Socket_Sendmsg       Access rights field ignored on entry
   Socket_Getpeername   Socket address limited to IPv4
   Socket_Getsockname   Socket address limited to IPv4

Potential for error number inequality
-------------------------------------

Take care if source code you are adopting from another system makes reference
to <errno.h> or "errno.h" as one of its include files.

For compatibility with FreeBSD the TCPIPLibs headers redirect 'errno.h' to
the more common 'sys/errno.h'. This leads to an ambiguity whether the TCPIPLibs
error numbers or ANSI error numbers were expected, depending on the order of
include paths specified to the compiler.

Often this issue is self apparent because the ANSI header file only defines
six error numbers, while the TCPIPLibs copy defines over ninety, so it's
unlikely that the source code would compile if it uses any outside the ANSI
range. However, if it did use only EDOM/ERANGE/ESIGNUM/EILSEQ/EOVERFLOW/EFBIG
and was then linked with TCPIPLibs the functions placing values into errno
would not match within your program leading to undefined behaviour.


                                  *************
                                  * 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.

[EACCES]         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.

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.  When this
             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 thirteen variables in the net.inet branch of the
sysctl MIB.

tcp.rfc1323      Implement the window scaling and time-
                 stamp options of RFC 1323 (default true).
                 
tcp.mssdflt      The default value used for the maximum
                 segment size ('MSS') when no advice to the contrary
                 is received from MSS negotiation.

tcp.minmss       The smallest acceptable maximum segment size ('MSS')
                 that will be used. Set to 0 to disable.
                 
tcp.rttdflt      The value of the default maximum TCP Round Trip Time.

tcp.sendspace    The default maximum send and receive window sizes,
tcp.recvspace    respectively

tcp.keepidle     Amount of time, in milliseconds, that the connection must
                 be idle before keepalive probes (if enabled) are sent.

tcp.keepintvl    The interval, in milliseconds, between keepalive probes sent
                 to remove machines, when no response is received on a keepidle
                 probe. After TCPTV_KEEPCNT (default 8) probes are sent, with
                 no response, the connection is dropped.

tcp.keepinit     Timeout, in milliseconds, for new, non-established TCP
                 connections.

tcp.always_keepalive Assume that SO_KEEPALIVE is set on all TCP connections,
                 the kernel will periodically send a packet to the remote
                 host to verify the connection is still up.

tcp.pcbcount     The number of active process control blocks (read-only).

tcp.path_mtu_discovery Enable Path MTU Discovery when non-zero.

tcp.delayed_ack  Delay ACK to try and piggyback it onto a data packet.

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


                                *****************
                                * 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);

BITSTRING
=========

Name
----
bit_alloc, bit_clear, bit_decl, bit_ffs, bit_nclear, bit_nset, bit_set,
bitstr_size, bit_test - bit-string manipulation macros

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

bitstr_t *bit_alloc(int nbits)
void      bit_decl(bitstr_t *name, int nbits)
void      bit_clear(bitstr_t *name, int bit)
void      bit_ffc(bitstr_t *name, int nbits, int *value)
void      bit_ffs(bitstr_t *name, int nbits, int *value)
void      bit_nclear(bitstr_t *name, int start, int stop)
void      bit_nset(bitstr_t *name, int start, int stop)
void      bit_set(bitstr_t *name, int bit)
int       bitstr_size(int nbits)
int       bit_test(bitstr_t *name, int bit)

DESCRIPTION
These macros operate on strings of bits.

The macro bit_alloc() returns a pointer of type ``bitstr_t *'' to sufficient
space to store nbits bits, or NULL if no space is available.

The macro bit_decl() allocates sufficient space to store nbits bits on the
stack.

The macro bitstr_size() returns the number of elements of type bitstr_t
necessary to store nbits bits.  This is useful for copying bit strings.

The macros bit_clear() and bit_set() clear or set the zero-based numbered bit
bit, in the bit string name.

The bit_nset() and bit_nclear() macros set or clear the zero-based numbered
bits from start to stop in the bit string name.

The bit_test() macro evaluates to non-zero if the zero-based numbered bit
of bit string name is set, and zero otherwise.

The bit_ffs() macro stores in the location referenced by value the zero-
based number of the first bit set in the array of nbits bits referenced by
name. If no bits are set, the location referenced by value is set to -1.

The macro bit_ffc() stores in the location referenced by value the zero-
based number of the first bit not set in the array of nbits bits referenced
by name. If all bits are set, the location referenced by value is set to -1.

The arguments to these macros are evaluated only once and may safely have
side effects.

Example
-------
      #include <limits.h>
      #include <bitstring.h>

      #define LPR_BUSY_BIT            0
      #define LPR_FORMAT_BIT          1
      #define LPR_DOWNLOAD_BIT        2
      #define LPR_AVAILABLE_BIT       9
      #define LPR_MAX_BITS            10

      make_lpr_available()
      {
              bitstr_t bit_decl(bitlist, LPR_MAX_BITS);
              ...
              bit_nclear(bitlist, 0, LPR_MAX_BITS - 1);
              ...
              if (!bit_test(bitlist, LPR_BUSY_BIT)) {
                      bit_clear(bitlist, LPR_FORMAT_BIT);
                      bit_clear(bitlist, LPR_DOWNLOAD_BIT);
                      bit_set(bitlist, LPR_AVAILABLE_BIT);
              }
      }

See also
--------
malloc


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
-----------
This function is used by Socklib for all Socket_... SWI calls it makes. If a
SWI returns an error, then _copyerror is called which takes the following
actions:

* copies the supplied error block into the global error structure _inet_error.
* 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 ENEEDAUTH, then errno is changed to
  ESRCH.
* finally the function 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));
void err_set_silent(int silent);

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.

For "silent" operation, call err_set_silent() with a non-zero parameter. Then
the warn functions will do nothing, and the err functions will set the system
variable Inet$Error, instead of printing to stderr.

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.


FFS
===

Name
----
ffs - find first bit set in a bit string

Synopsis
--------
int ffs(int value)

Description
-----------
The ffs() function finds the first bit set in value and returns the index of
that bit.  Bits are numbered starting from 1, starting at the right- most
bit.  A return value of 0 means that the argument was zero.

See also
--------
bitstring

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


FSTAT
=====

Name
----
fstat - get file status

Synopsis
--------
int fstat(int s, struct stat *buf);

See also
--------
socketstat

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

GETADDRINFO
===========
New prototype: int getaddrinfo(const char *nodename, const char *servname,
                               const struct addrinfo *hints,
                               struct addrinfo **res);
               void freeaddrinfo(struct addrinfo *ai);

The getaddrinfo() function fills an addrinfo structure having looked up the
node and server name given. An optional hints structure can be given to direct
the output result, for example to restrict the return results to ones the
caller supports.

The hints flags can be combinations of AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST:

  AI_PASSIVE - set if the caller plans to use the result with bind(),
               otherwise connect()
  AI_CANONNAME - try to return the canonical name in the first addrinfo
                 structure
  AI_NUMERICHOST - this flag flag prevents any type of name resolution service
               
When finished with the result, it must be freed by the caller by calling
freeaddrinfo().

The return value from the function is 0 upon success or a nonzero error code.
The error code can be turned into a string, for example for use in error logs,
by passing the return value to gai_strerror().

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.

Note that these functions are not thread safe, nor do they handle IPv6
addresses, and as such should be considered deprecated. See getipnodebyname()
and getipnodebyaddr() for suitable replacements.

GETIPNODEBY
===========
New prototypes: struct hostent *getipnodebyname(const char *name, int af,
                                                int flags, int *error_num);
                struct hostent *getipnodebyaddr(const void *src, size_t len,
                                                int af, int *error_num);
                void freehostent(struct hostent *ptr);

Performs nodename-to-address and address-to-nodename translation.

For getipnodebyname() the name argument can be either a node name or a
numeric address string. Using an address family of AF_INET is largely equivalent
to the former gethostbyname().
The flags argument specifies the types of addresses that are searched for, and
the types of addresses that are returned.

For getipnodebyaddr() takes similar arguments to the former gethostbyaddr(),
but adds a error return value rather than relying on the global errno value.

The hostent structure returned by getipnodebyname() and getipnodebyaddr() must
subsequently be freed by the caller by calling freehostent();

GETNAMEINFO
===========
New prototype: int getnameinfo(const struct sockaddr *sa, socklen_t salen,
                               char *host, size_t hostlen,
                               char *serv, size_t servlen,
                               int flags);

This function looks up an IP address and port number provided by the
caller in the DNS and system-specific database, and returns text
strings for both in buffers provided by the caller.  The function
indicates successful completion by a zero return value; a non-zero
return value indicates failure.

GETNETENT
=========
New prototypes: struct netent *getnetbyname(const char *name);
                struct netent *getnetbyaddr(unsigned 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);

New description:

Getpid returns the process ID of the current process.  Most often it is used
to generate uniquely-named temporary files.

Under RISC OS, this call returns the Wimp task handle of the current task. 
If the caller is not an active Wimp task (ie. a command-line application not
running in a TaskWindow), this call returns 9999.


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

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

IF_INDEX
========
New prototypes: char *if_indextoname(unsigned int, char *);
                unsigned int if_nametoindex(const char *);   
                struct if_nameindex *if_nameindex(void);     
                void if_freenameindex(struct if_nameindex *);

This API uses an interface index (a small positive integer) to
identify the local interface on which a multicast group is joined.
Interfaces are normally known by names such as "lo0", "em0", "ppp2",
and the like.

The API defines two functions that map between an interface name and
index, a third function that returns all the interface names and
indexes, and a fourth function to return the dynamic memory allocated
by the previous function.  

IN6_IS...
=========
This family of macros tests an in6_addr structure and returns a boolean result
if the address given is of that type. The tests available are as follows:

        IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *);
        IN6_IS_ADDR_LOOPBACK(const struct in6_addr *);
        IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *);
        IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
        IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
        IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *);
        IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
        IN6_IS_ADDR_MULTICAST(const struct in6_addr *);
        IN6_IS_ADDR_SITELOCAL(const struct in6_addr *);
        IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *);
        IN6_IS_ADDR_V4COMPAT(const struct in6_addr *);
        IN6_IS_ADDR_V4MAPPED(const struct in6_addr *);


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

Four new functions have been defined:

	char *inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size);
	
This function convert network number from network to presentation format.
Generates CIDR style result always.  The return value is pointer to dst, or
NULL if an error occurred (check errno).

	int inet_net_pton(int af, const char *buf, void *, size_t);
	
This function parses a presentation format (ie. textual) address into a
network address (the reverse operation to inet_net_ntop).   af is the address
type (AF_INET or AF_INET6); buf points to the textual representation, buf
points to the output buffer and size is the length of that buffer.  The
return value is the number of bits, either imputed classfully or specified
with /CIDR, or -1 if some failure occurred (check errno). ENOENT means it was
not a valid network specification.

	int inet_pton(int af, const char *src, void *dst);
	
Convert from presentation format (which usually means ASCII printable) to network
format (which is usually some kind of binary format).  Return:
  1 if the address was valid for the specified address family
  0 if the address wasn't valid (`dst' is untouched in this case)
 -1 if some other error occurred (`dst' is untouched in this case, too)

	const char *inet_ntop(int af, const void *src, char *dst, size_t size);

Convert a network format address to presentation format.  Returns a pointer to
presentation format address (`dst'), or NULL (see errno).

_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 virtual 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.


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);

SETSOCKOPT
==========
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.

SLEEP
=====

Name
----
sleep - suspend process execution for an interval measured in seconds

Synopsis
--------
unsigned int sleep(unsigned int seconds);

Description
-----------
The sleep() function suspends execution of the calling process until either
seconds seconds have elapsed or an escape condition occurs. System activity
may lengthen the sleep by an indeterminate amount.

Return values
-------------
If the sleep() function returns because the requested time has elapsed,
the value returned will be zero.  If the sleep() function returns due to
an escape condition, the value returned will be the unslept amount
(the requested time minus the time actually slept) in seconds.

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


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 task window to sleep.

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

SOCKETSTAT
==========

Name
----
socketstat - get socket status

Synopsis
--------
int socketstat(int s, struct stat *buf);

Description
-----------
The only meaningful fields of the status structure filled in when stat() is
applied to a socket are st_mode and st_blksize.

st_mode equals S_IFSOCK if the descriptor given is recognised as a socket
        descriptor.
st_blksize gives the preferred send buffer size to use for the
           protocol (or 0 if unknown) which can improve performance by
           reducing fragmentation.

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


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);

STRDUP
======

Name
----
strdup - save a copy of a string

Synopsis
--------
char *strdup(const char *str);

Description
-----------
The strdup function allocates sufficient memory for a copy of the string str,
does the copy, and returns a pointer to it. The pointer may subsequently be
used as an argument to the function free.

If insufficient memory is available, NULL is returned.

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

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/types.h>
#include <sys/sysctl.h>

int sysctl(int *name, u_int namelen, void *oldp, size_t oldlenp, void *newp,
            size_t newlen);
int sysctlbyname(const char *name, 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.

Unless explicitly noted below, sysctl() returns a consistent snapshot of the
data requested.  Consistency is obtained by locking the destination buffer
into memory so that the data may be copied out without blocking. Calls to
sysctl() are serialized to avoid deadlock.

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

The sysctlbyname() function accepts an ascii representation of the name and
internally looks up the integer name vector.  Apart from that, it behaves the
same as the standard sysctl() function.
 
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
             igmp                  forceleave         integer    yes
             tcp                   rfc1323            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 utility 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.

         icmp.maskrepl     Returns 1 if ICMP network mask requests are to be
                           answered.
         
         igmp.forceleave   Suppresses IGMPv2 'leave' optimisation.

         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.
The sysctlbyname function first appeared in Internet 5.31.

Exported by
-----------
Socklib (sysctl), Inetlib (sysctlbyname)

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 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 module 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).

You must not claim this service call.
  
Service_InternetStatus 3 (Service Call &B0)
========================

Issued by the Internet module or DHCP module when a BOOTP/DHCP request is about to be sent.

On entry
--------
R0 = 3 (subreason code)
R1 = &B0 (reason code)
R2 -> interface name (eg "ea0")
R3 -> Driver Information Block for interface
R4 -> DHCP request message buffer
R5 = size of buffer pointed to by R4
R6 = offset from packet start to current end of options

On exit
-------
R0,R3-R5 preserved, R6 may be updated.
R1 = 0 to claim service call, else preserved.
If claiming the service call, R2 may be updated with a value of errno, else it
must be preserved.

Use
---
This service call is issued by the Internet module (version 5.19 or later) or the
DHCP module (all versions) when a BOOTP/DHCP request is about to be performed on
an interface. (eg due to an SIOCGWHOIAMB socketioctl() call).  The request message
buffer pointed to by R4 is the datagram payload about to be sent.  You may modify
the options field of the request message buffer and update R6 to be the offset to
the first free byte in the options field.

If the DHCP module has issued the service call, the options buffer of the message
buffer will contain OPTION_DHCPMESSAGETYPE.  Clients can base decisions on what to
do on the value of this option.  Clients not wishing to parse the options directly
can attempt a call to SWI DHCP_GetOption to retrieve the single byte message type
value, as defined by RFC2131.  Currently, only DHCPDISCOVER messages are sent on
this service call, DHCPREQUEST messages use subreason code 6.

To prevent the transmission of the BOOTP/DHCP request on the network, claim the
service call.  You should not normally claim this service call unless you are
providing an alternative arrangement for obtaining interface configuration.

If you claim this service call, then you may update R2 with a value between 0 and
255 representing the standard Internet error number which the service call issuer
should return to its caller.  By default, Internet will use EADDRNOTAVAIL.  A
value of zero should be used to indicate that the interface configuration process
has been successfully completed.

  
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.19 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 DHCP 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.

Clients may need to remember various attributes of the message in order to
respond correctly to the subsequent Service_InternetStatus 3 (DHCPREQUEST
message).  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 DHCP 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)
========================

Issued by the DHCP module when it is about to send a DHCPREQUEST message.

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

On exit
-------
All registers preserved.

Use
---
This service call is issued by the DHCP module whenever it wishes to send
a DHCPREQUEST message after electing which IP address lease DHCPOFFER to
accept.  The DHCPOFFER which has been accepted in pointed to by R6.  The
DHCPREQUEST which will be sent is pointed to by R4.  You must not modify
the DHCPOFFER message.  You may modify the DHCPREQUEST message.

You must not claim this service call.  Any objection should have been raised
in response to Service_InternetStatus 5.


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

Issued by the Internet module when a DHCPACK reply to a DHCPINFORM has been received.

On entry
--------
R0 = 7 (subreason code)
R1 = &B0 (reason code)
R2 -> DHCP reply message buffer
R3 = size of buffer pointed to by R2

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

Use
---
This service call is issued by the Internet module (version 5.24 or later)
when a DHCPACK is received in reply to a DHCPINFORM message.  You may inspect
the contents of the buffer to extract any configuration information.

You should not normally claim this service call.


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 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 Vol 5a of the PRMs, the calling conditions of the Socket SWIs are not specified.
Here 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


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

In Vol 5a of the PRMs, the calling conditions of the Internet event are not
specified. Here 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 handle_internet_event(_kernel_swi_regs *r)
          {
          	if (r->r[2] == sock_data)
          	{
          		...
          		return 0;
          	}
          	else if (r->r[2] == sock_listen)
          	{
          		...
          		return 0;
          	}
          	
          	return 1;
          }

          int event_handler(_kernel_swi_regs *r)
          {
                int result = 1;
          	if (r->r[0] == Internet_Event && r->r[1] == Socket_Async_Event)
          	{
          	    _kernel_irqs_on();
          	    result = handle_internet_event(r);
          	    _kernel_irqs_off();
          	}
          	return result;
          }

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.
