Internet DRAFT - draft-ietf-sip-bsd-api

draft-ietf-sip-bsd-api




Internet Engineering Task Force                 Robert E. Gilligan
INTERNET-DRAFT                                  Sun Microsystems, Inc.
                                                December 20, 1993


                SIPP Program Interfaces for BSD Systems


Abstract

In order to implement the Simple Internet Protocol (SIPP) [1] in an
operating system based on 4.x BSD, changes must be made to some of the
application program interfaces (APIs).  TCP/IP applications written for
BSD-based operating systems have in the past enjoyed a high degree of
portability because most of the systems derived from BSD provide the
same API, known informally as "the socket interface".  We would like the
same portability to be possible with SIPP applications.  This memo
presents a set of changes to the BSD socket API to support SIPP.  The
changes include a new data structure to carry 64-bit SIPP addresses, a
new name to address translation library function, new address conversion
functions, and some new setsockopt() options.  The changes are designed
to be minimal and to provide source and binary compatibility for
existing applications.


Status of this Memo

This document is an Internet Draft.  Internet Drafts are working
documents of the Internet Engineering Task Force (IETF), its Areas, and
its Working Groups.  Note that other groups may also distribute working
documents as Internet Drafts.

Internet Drafts are draft documents valid for a maximum of six months.
This Internet Draft expires on June 20, 1994.  Internet Drafts may be
updated, replaced, or obsoleted by other documents at any time. It is
not appropriate to use Internet Drafts as reference material or to cite
them other than as a "working draft" or "work in progress."

Please check the I-D abstract listing contained in each Internet Draft
directory to learn the current status of this or any other Internet
Draft.

Distribution of this memo is unlimited.










draft-ietf-sip-bsd-api-01.txt                                   [Page 1]

INTERNET-DRAFT           SIPP API Specification            December 1993


1. Introduction.

The most visible feature of SIPP is its extension of the length of an IP
address from 32 bits to 64 bits.  The APIs that the BSD system provides
make the size of an IP address quite visible to an application.
Virtually all TCP/IP applications for BSD-based systems have knowledge
of the size of an IP address.  Generally speaking, those parts of the
API that make addresses visible need to be changed.  This paper presents
a first attempt to define the API changes needed to support SIPP in BSD
systems. These APIs are expected to evolve as we gain more
implementation experience.


2. Design considerations

There are two important considerations in designing changes to these
well-worn APIs.  First, the modified API should provide both source and
binary compatibility for programs written to the existing API.  That is,
exiting program binaries should continue to operate when run on or
re-compiled and run a system supporting the new APIs.  The API changes
for SIPP should not cause existing program binaries to break, nor should
they cause programs written to the existing APIs to fail to compile or
break when re-compiled.

Second, the changes should be as minimal as possible and should make it
as easy as possible to change an existing application to be SIPP
knowledgeable.


2.1 What needs to be changed

Since their address arguments are all opaque pointers, none of the
socket system calls need to changed directly.

The in_addr structure is 4-bytes long and can not be changed without
breaking applications.  The sockaddr_in structure, which is passed into
and returned by the socket functions, contains 8 bytes of unused space
which can be used to hold a SIPP address without incompatibility.

The gethostbyaddr() function includes an address type argument, so this
function does not need to be changed.  However, the gethostbyname()
function does not include a type argument, and most applications that
use it assume that the address array that it returns consists of 4-byte
IP addresses.  Thus a new function similar to gethostbyname(), but
knowledgeable of SIPP addresses, must be defined.

Finally, a new interface is needed in order to set the SIPP flow ID.  The
most straightforward way to do this is to define new setsockopt()
options at the IPPROTO_IP level.





draft-ietf-sip-bsd-api-01.txt                                   [Page 2]

INTERNET-DRAFT           SIPP API Specification            December 1993


2.2 Implementation experience

The Sun IPAE/SIPP prototype exposed some of the issues in designing a
compatible interface.  The initial prototype passed SIPP addresses
between the kernel and applications using the sockaddr_in structure with
the sin_family field set to AF_INET.  The 8-byte SIPP address occupied
the 4 bytes of the "sin_addr" field plus the first 4 bytes of the
"sin_zero" field.  The kernel distinguished between 8-byte SIPP
addresses and 4-byte IPv4 addresses passed in by checking the sin_zero
field.  If sin_zero was zero, the kernel would assume that the sin_addr
field held a 4-byte IPv4 address.  If sin_zero was non-zero, it would
assume that an 8-byte SIPP address was being passed in.

While this technique works for most existing applications, we discovered
that some applications do not set the sin_zero field of the sockaddr_in
structure to zero.  Thus we concluded that it would be unworkable in the
general case and that some specific indication was needed to distinguish
a 8-byte SIPP address from a 4-byte IPv4 address in a sockaddr_in
structure.

Another useful lesson learned from the initial Sun implementation was
that the form of addresses (IPv4 or SIPP) passed in and out of the
socket functions did not always need to constrain the form of packets
(IPv4, IPAE or SIPP) transmitted or received.  For example, a
pre-existing TCP server application that knows nothing of SIPP could
accept a connection that was transmitting and receiving TCP segments
encapsulated within SIPP packets.  Because SIPP and IPv4 addresses are
mappable, the accept() system call can return to the application the
client's address as a 4-byte IPv4 address.

What does matter, however, is that pre-existing applications never be
given address structures that they don't understand.  We found that the
most convenient way for the kernel to decide what form of address to
pass back to applications was to look at the form of addresses passed
in.  That is, if an application passes in IPv4 form addresses, then it
should always be given IPv4 form addresses.  If the application passes
in SIPP form addresses, the kernel can return SIPP form addresses to the
application.


3. Interface specification


3.1. New address family

We define a address family macro in <sys/socket.h>:

        #define AF_SIPP         24      /* Simple Internet Protocol */

The AF_SIPP definition is used only to distinguish between the original
AF_INET form of the sockaddr_in structure, and a new form that we have



draft-ietf-sip-bsd-api-01.txt                                   [Page 3]

INTERNET-DRAFT           SIPP API Specification            December 1993


defined.  Thus there is no corresponding PF_SIPP definition.


3.2 Sockaddr_in structure

The sockaddr_in structure is used in the socket system calls to pass
addresses between the application and the kernel.  Keeping the
sockaddr_in structure the same size is necessary to provide binary
compatibility for existing IPv4 applications.  We can avoid changing the
size of the sockaddr_in structure by appropriating the currently unused
sin_zero field to hold the 64 bit SIPP address.

We can add a structure element for the SIPP address without changing the
original structure definition by just adding two new macros.  The
resulting definition in the <netinet/in.h> header file is:


        struct sockaddr_in {
                short sin_family;
                u_short sin_port;
                in_addr sin_addr;
                char sin_zero[8];
        }
#define sipp_addr sin_zero
#define sipp_zero sin_addr


The value of the sin_family field determines whether the sockaddr_in
structure is holding a 32 bit IPv4 address or a 64 bit SIPP address.
The sin_family field may have one of two values: AF_INET or AF_SIPP.  If
sin_family is AF_SIPP, then the sipp_addr field contains a 8-byte SIPP
address and the sipp_zero field must be set to zero.  If the sin_family
field is AF_INET, then the sockaddr_in keeps its original semantics: The
sin_addr field contains a 4-byte IPv4 address and the sin_zero field
must be set to zero.

We refer to the the two variants as the "AF_INET form" or the "AF_SIPP
form" of the sockaddr_in structure.

The two structure layouts can be understood better when viewed
graphically.  This is the AF_INET form of the sockaddr_in structure:

        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |           AF_INET             |       port number             |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                         IPv4 address                          |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        +                        all zero bits                          +
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



draft-ietf-sip-bsd-api-01.txt                                   [Page 4]

INTERNET-DRAFT           SIPP API Specification            December 1993


And this is the layout of the AF_SIPP form of the sockaddr_in structure:

        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |           AF_SIPP             |        port number            |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                         all zero bits                         |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        +                          SIPP address                          +
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

We considered an alternative form that overlays the high-order four
bytes of the SIPP address with sin_addr.  The form presented has a few
advantages:

  -     The SIPP address is aligned on a 64-bit boundary within the
        structure.

  -     The kernel can do some consistency checking on AF_SIPP addresses
        passed in. Because the sipp_zero field, which overlays the
        sin_addr field, must always zero, the kernel can detect cases
        where the application incorrectly treats an AF_SIPP form
        sockaddr_in as an AF_INET form.

  -     The structure declaration is simpler than the alternative.

3.3 The socket functions

Even though we define a new address family for SIPP, there is no change
to the way that applications get sockets.  There is not a new "type" of
socket for SIPP.  SIPP applications continue use AF_INET in the "domain"
argument (the first argument) of the socket() call.  For example, to get
a TCP socket, a SIPP application would call:

        s = socket (AF_INET, SOCK_STREAM, 0);

and to get a UDP socket, a SIPP application would call:

        s = socket (AF_INET, SOCK_DGRAM, 0);

Once the application has a socket, it may use either the AF_SIPP or the
AF_INET form of the sockaddr_in structure in the system calls that pass
addresses in to the kernel.

The form of sockaddr_in structure returned to the application by the
socket functions is determined by the form of addresses passed in most
recently.  For example, if an application uses an AF_SIPP form address
in its bind() call, then a subsequent accept() call would return a
sockaddr_in structure in the AF_SIPP form.  If the application calls no
socket function that passes in an address before calling one that



draft-ietf-sip-bsd-api-01.txt                                   [Page 5]

INTERNET-DRAFT           SIPP API Specification            December 1993


returns an address, then that function returns an AF_INET form address.

The socket functions to which an application passes in an address
argument are:

        bind()
        connect()
        sendto()

The socket functions that return an address to the application are:

        accept()
        recvfrom()
        getpeername()
        getsockname()


3.4 Sockets passed across exec()

Having two forms of sockaddr_in address that may be used interchageably
with all AF_INET sockets means that existing applications are supported
straightforwardly, and that new applications simply need to be written
to use the AF_SIPP form of sockaddr_in.  However, Unix allows open
sockets to be passed across an exec() call.  Thus a newly written
application may find itself holding an open socket that was passed to it
via exec(), but not knowing what form of addresses that will be
returned.  Similarly, a newly written SIPP knowledgeable application may
wish to use AF_SIPP form addresses in its bind() or connect() calls, and
then pass the socket to a pre-existing application.  To remedy these
problems, we defined a new setsockopt() option that allows an
application to explicitly set the form of sockaddr_in addresses returned
by the socket functions.  A SIPP knowledgeable application that is
passed an open socket from an unknown process may do use the
SIPP_ADDRFORM setsockopt() option to "convert" the socket to return
AF_SIPP form addresses.  Similarly, a SIPP knowledgeable application
that is about to pass an open socket to a program that may not be SIPP
knowledgeable may "downgrade" the socket to return AF_INET form
addresses using the same setsockopt option.

The macro definition for this new option in <netinet/in.h> is:

#define SIPP_ADDRFORM   0x16        /* get/set form of returned addrs */

The SIPP_ADDRFORM option is at the IPPROTO_IP level.  The only valid
option values are AF_SIPP and AF_INET.  For example, to convert a socket
to return AF_INET form addresses, a program would call:

        int addrform = AF_SIPP;

        if (setsockopt(s, IPPROTO_IP, SIPP_ADDRFORM, (char *) &addrform,
                       sizeof(addrform)) == -1)



draft-ietf-sip-bsd-api-01.txt                                   [Page 6]

INTERNET-DRAFT           SIPP API Specification            December 1993


                perror("setsockopt SIPP_ADDRFORM");

An application may use SIPP_ADDRFORM in the getsockopt() function to
learn the form of addresses that will be returned by an open socket.


3.5 IPv4 addresses in AF_SIPP form sockaddr_in structures

An application may need to pass 32 bit IPv4 address in a sockaddr_in
structure, but want to set the sin_family field to AF_SIPP in order to
set the form of addresses to be returned.  To allow for this, we have
defined a convention for storing 32 bit IPv4 addresses in 64 bit SIPP
addresses.  The 32-bit IPv4 address is stored in the low-order 32 bits
of the SIPP address and the high-order 32 bits (i.e. the prefix part)
are set to zero.  For example, the following structure:

        struct sockaddr_in sin1;

        sin1.sin_family = AF_SIPP;
        sin1.sipp_zero = 0;
        *((long *) sin1.sipp_addr) = 0;
        *((long *) &sin1.sipp_addr[4]) = inet_addr("192.9.9.1");

And this structure:

        struct sockaddr_in sin2;

        sin2.sin_family = AF_INET;
        sin2.sin_addr.s_addr = inet_addr("192.9.9.1");
        bzero(sin2.sin_zero, sizeof(sin_zero);

are alternative ways to represent the same IPv4 address.

All of the socket functions that accept sockaddr_in addresses passed in
as arguments accept IPv4 addresses in the AF_SIPP form.


3.6 Flow IDs

The SIPP header has a 28 bit field reserved to hold a "flow ID".  The
usage of this field has not yet been specified.  But in order to allow
application programmers to experiment with SIPP flows, we have defined a
setsockopt() option that can be used to set the value to be assigned to
the flow ID field of transmitted SIPP packets.  So far, we have not
defined any interface for an application to learn the flow ID set in
received SIPP packets.

The macro definition for this new option in <netinet/in.h> is:

#define SIPP_FLOWID              0x15    /* SIPP flow identifier */




draft-ietf-sip-bsd-api-01.txt                                   [Page 7]

INTERNET-DRAFT           SIPP API Specification            December 1993


The SIPP_FLOWID option is at the IPPROTO_IP level.  An example of how an
application might use this option is:

        int flowid = 0x0f3c91ab;        /* made up for this example */

        if (setsockopt(s, IPPROTO_IP, SIPP_FLOWID, (char *) &flowid,
                       sizeof(flowid)) == -1)
                perror("setsockopt SIPP_ADDRFORM");

The SIPP_FLOWID option can also be used with the getsockopt() option to
retrieve the flow ID value given in the last setsockopt() call.

Since the definition of SIPP flows may change as the protocol develops,
this option may also change in the future.  Thus application developers
should consider this option "experimental."


3.7  Name-to-address translation functions

We have defined a new function call with the form:

     struct hostent *hostname2addr(const char *name, int af,
                                   char *buf, int buflen);

This interface looks the given host name up in the naming service and
returns a list of addresses.  The name argument is the name of the host
to look up.  The af argument specifies what form of address -- 4-byte
IPv4 or 8-byte SIPP address -- to return to the caller in the
h_addr_list field of the hostent structure.  The buf argument points to
a buffer that the function can use to store the hostent structure that
is returned.  The buflen argument is the size of the buffer.  If buf is
a null pointer, the function uses its own static buffer.

If the af argument is AF_INET, hostname2addr() behaves like
gethostbyname().  That is, it returns a hostent structure which includes
an array of 4-byte IPv4 addresses.  If AA (SIPP address) records are
found, then the low-order 4 bytes of each SIPP address are returned.  If
only A records are found, then the associated 4-byte IP address is
returned.

If the type argument is AF_SIPP, then the h_addr_list field of the
hostent structure contains an array of 8-byte SIPP addresses.  If AA
records are found, then the full SIPP address of each record is
returned.  If only A records are found, then each 8-byte address
returned holds the IPv4 address in the low-order 4 bytes and the
high-order 4 bytes are set to zero.  (i.e. it uses the convention for
storing IPv4 addresses in SIPP addresses defined above).

There was some discussion on the SIPP mailing list of some other ways to
cast this function.  This proposal allows the application to be simple.
Since it passes in the address family, the application knows the size of



draft-ietf-sip-bsd-api-01.txt                                   [Page 8]

INTERNET-DRAFT           SIPP API Specification            December 1993


the returned addresses and can unconditionally bcopy() them into
sockaddr_in structures.  Also, the semantics of the hostname2addr() when
af is AF_INET lets us implement the existing gethostbyname() function in
terms of the new function.

The gethostbyaddr() function remains unchanged:

     struct hostent *gethostbyaddr(const char *addr, int len, int af);

If the af argument is AF_INET, then len must be 4 and addr points to a
4-byte IPv4 address.  If af is AF_SIPP, then len must be 8 and addr
points to an 8-byte SIPP address.


3.8 Address input/output functions

BSD Unix provides two functions -- inet_addr() and inet_ntoa() -- to
convert IPv4 address between binary and printable form.  SIPP
applications need similar functions.  We have defined the following two
functions to convert SIPP and IPv4 addresses:

        int ascii2addr(long af, char *cp, char *ap);

and

        char *addr2ascii(long af, char *ap, char *buf, int buflen)


The first function is used to transform an ascii string into an address
data structure.  The af argument specifies that address family of the
address.  Currently AF_INET and AF_SIPP are supported.  The cp argument
points to the ascii string being passed in.  The ap argument points to
the 4-byte or 8-byte buffer that the address will be converted into.

If the af argument is AF_INET, the function accepts a string in the
standard IPv4 dotted decimal form:

        ddd.ddd.ddd.ddd

Where ddd is a one to three digit decimal number between 0 and 255.

If the af argument is AF_SIPP, then the function accepts a string in the
standard IPv4 dotted decimal form given above, or a string in one of the
two standard SIPP printing forms:

        xxxx:xxxx:ddd.ddd.ddd.ddd
or
        xxxx:xxxx:xxxx:xxxx

where xxxx is a 1 to 4 digit hex value and ddd is a 1 to 3 digit decimal
number between 0 and 255.  If the string is in the IPv4 dotted decimal



draft-ietf-sip-bsd-api-01.txt                                   [Page 9]

INTERNET-DRAFT           SIPP API Specification            December 1993


form, the high order 4 bytes of the address buffer pointed to by ap are
set to zero and the low-order 4 bytes are set to the IPv4 address.

Having the AF_SIPP variant of the ascii2addr() function accept either
IPv4 addresses or SIPP addresses allows an application to easily accept
either form of address from the user.

The second function transforms an address buffer into a printable
string.  The af argument specifies the form of the address.  This can be
AF_INET or AF_SIPP.  The ap argument points to a buffer holding a 4-byte
IPv4 address or an 8-byte SIPP address.  The buf argument points to a
buffer that the function can convert into, and the buflen argument gives
the size of this buffer.  If the buf argument is zero, then the function
will convert the address unto a private static buffer of its own.  In
either case, the function returns a pointer to the buffer that the
address has been converted into.

The ascii2addr() function returns 0 if the conversion succeeded, and -1
if it failed.  The function does not modify the storage pointed to by ap
if the conversion fails.  The addr2ascii() function returns a pointer to
the buffer if the conversion succeeded, and -1 if the conversion failed.

These two functions are derived from suggestions by Craig Partridge on
the SIPP mailing list.  There was some discussion about whether the
buffer that addr2ascii() converts into should be static within the
function() or passed in by the application.  In the interface presented
here, we try to provide the best of both worlds.

4. Open Issues

The API changes described here are likely to change as we get experience
writing SIPP applications.  There are also some issues left unresolved.
Some of the things we need to think about are:

  -     There is a type defined (in_addr) to represent a 32-bit IPv4
        address.  Should we define a structure to hold the 64-bit SIPP
        address?  There was some discussion of this on the SIPP mailing
        list with opinions on both sides.

  -     The format of the "/etc/hosts" file currently supports only IPv4
        addresses.  Should we extend the format of the existing file to
        handle SIPP addresses?  Or should we invent a file with a new
        name for storing SIPP host addresses?  Andrew Cherenson suggests
        a clever, but ugly, hack to re-use the same file and allow old
        and new versions of gethostb* to co-exist: precede SIPP lines
        with "#SIPP", which acts as comment for old versions.

  -     How do datagram applications participate in path MTU discovery?

  -     What about the SIOC* ioctl() commands that get and set interface
        parameters and manipulate the IP routing table?



draft-ietf-sip-bsd-api-01.txt                                  [Page 10]

INTERNET-DRAFT           SIPP API Specification            December 1993



  -     Posix is changing and standardizing the socket interface.
        Should we track the posix changes?  In particular, 4.3-Reno has
        split the 16-bit address family field of the sockaddr struct
        into two 8-bit fields: a length field and an address family
        field.  Should we adopt this here?

  -     This spec has concentrated on the BSD socket interface.  What
        about the System V Transport Library Interface (TLI)?  Does
        anyone really care about TLI?

  -     The BSD "net-2" release includes setsockopt options to set the
        IP TTL.  Should we specify that this option sets the SIPP hop
        limit, or is this just obvious?


5. Security Considerations

Security issues are not discussed in this document.


6. Acknowledgements

Thanks to all who provided feedback to the first revision of this
document, including Christian Huitema, Craig Partridge, Steve Deering,
Andrew Cherenson, Charles Lynn, Ran Atkinson, Erik Nordmark, Glenn
Trewitt, Fred Baker, Robert Elz, and Dean D. Throop.


7. References

[1]     Deering, S., "Simple Internet Protocol (SIP) Specification",
        Internet Draft November 1992



8. Authors' Address

        Robert E. Gilligan
        Sun Microsystems, Inc.
        2550 Garcia Avenue
        Mailstop UMTV05-44
        Mountain View, California 94043-1100

        415-336-1012

        bob.gilligan@eng.sun.com







draft-ietf-sip-bsd-api-01.txt                                  [Page 11]