SIP API spec

Bob Gilligan <> Tue, 26 January 1993 02:30 UTC

Received: from by IETF.CNRI.Reston.VA.US id aa20405; 25 Jan 93 21:30 EST
Received: from CNRI.RESTON.VA.US by IETF.CNRI.Reston.VA.US id aa20401; 25 Jan 93 21:30 EST
Received: from Sun.COM by CNRI.Reston.VA.US id aa06897; 25 Jan 93 21:32 EST
Received: from Eng.Sun.COM (zigzag-bb.Corp.Sun.COM) by Sun.COM (4.1/SMI-4.1) id AA21025; Mon, 25 Jan 93 18:30:18 PST
Received: from sunroof.Eng.Sun.COM by Eng.Sun.COM (4.1/SMI-4.1) id AA17731; Mon, 25 Jan 93 18:31:05 PST
Received: from bigriver.Eng.Sun.COM (bigriver-248) by sunroof.Eng.Sun.COM (4.1/SMI-4.1) id AA15867; Mon, 25 Jan 93 18:29:52 PST
Received: from kandinsky.Eng.Sun.COM by bigriver.Eng.Sun.COM (4.1/SMI-4.1) id AA06471; Mon, 25 Jan 93 18:23:37 PST
Date: Mon, 25 Jan 93 18:23:37 PST
Sender: ietf-archive-request@IETF.CNRI.Reston.VA.US
From: Bob Gilligan <>
Message-Id: <9301260223.AA06471@bigriver.Eng.Sun.COM>
Subject: SIP API spec
Content-Length: 13373

Here's a first draft of a spec for changes to BSD APIs to support SIP
and IPAE.  Send comments and suggestions to me.

Internet Engineering Task Force				Robert E. Gilligan
INTERNET-DRAFT						Sun Microsystems, Inc.
							January 25, 1992

		SIP Program Interfaces for BSD Systems


In order to implement the Simple Internet Protocol (SIP) in a 4.x BSD
based operating system, changes must be made to some of the application
program interfaces (APIs).  The API changes need to be specified
concretely so that SIP implementations in all BSD-based systems can
provide the same API and thus provide portability for application
software that makes use of SIP.  This memo proposes a set of changes to
the BSD networking APIs.  This changes include a new data structure to
carry 64-bit SIP addresses, a new name to address translation library
function, and some new setsockopt() options.

Status of this Memo

This a draft internet-draft.  Since this memo specifies APIs only, and
not protocols, it is not intended to ever get onto the Internet
standards track.

1. Introduction.

The most visible feature of SIP is its extension of the length of an IP
address from 32 bits to 64 bits.  The APIs that the BSD system provide
make the length of an IP address quite visible to an application.
Virtually all TCP/IP applications for BSD-based systems have the length
of an IP address hard-coded throughout.  Thus it is not possible to
implement SIP in a BSD-based system without some changes to the APIs.

Some of the API changes presented here are based loosely on those
implemented in the Sun IPAE/SIP prototype.  These APIs are expected to
change 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.  The API
changes for SIP 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 SIP

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 inet_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
and thus can be extended to hold a SIP 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 SIP addresses, must be defined.

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

2.2 Implementation experience

The Sun IPAE/SIP prototype exposed some of the issues in designing a
compatible interface.  The Sun prototype passed SIP addresses between
the kernel and applications using the sockaddr_in structure with the
sin_family field set to AF_INET.  The kernel distinguished between
8-byte SIP addresses and 4-byte IPv4 addresses passed in passed in by
checking at 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 SIP address was being
passed in.  It would determine what form of addresses to pass out to the
application based on the form of address used in the bind() or connect()
call.  If a SIP address was used in the bind(), the kernel would pass
SIP address out in the socket system calls that return addresses.

While this technique works for most existing applications, we concluded
that it would be unworkable in the general case when we discovered that
some applications do not set the sin_zero field of the sockaddr_in
structure to zero.

3. Interface specification

3.1. New address family

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

	#define AF_SIP		23	/* Simple Internet Protocol */

3.2 Sockaddr_in structure

We change the definition of the sockaddr_in structure in <netinet/in.h>:

	struct sockaddr_in {
		short sin_family;
		u_short sin_port;
		union {
			in_addr sin_sin_addr;
			u_long sin_sip_zero;
		} sin_un1;
		union {
			u_long sin_sip_addr[2];
			char sin_sin_zero[8];
		} sin_un2;
#define sin_addr sin_un1.sin_sin_addr
#define sin_zero sin_un2.sin_sin_zero
#define sip_addr sin_un2.sin_sip_addr
#define sip_zero sin_un1.sin_sip_zero

The sin_family field can have two values: AF_INET or AF_SIP.  If the
sin_family is AF_SIP, then the sip_addr field contains a 8-byte SIP
address and the sip_zero field is zero.  If the sin_family field is
AF_INET, then the sin_addr field contains a 4-byte IPv4 address and
the sin_zero field is zero.

A 4-byte IPv4 address can be represented in a sockaddr_in structure with
sin_family set to AF_SIP.  To do this, the low-order four bytes of the
sip_addr field should be set to the the 4-byte IPv4 address, and the
high-order 4 bytes of the sip_addr field should be set to zero.

The two 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                          +
        |                                                               |

And this is the layout of the AF_SIP form of the sockaddr_in

	|            AF_SIP             |        port number            |
        |                         all zero bits                         |
        |                                                               |
	+                          SIP address                          +
        |                                                               |

We considered an alternative form that overlays the high-order four
bytes of the SIP addr with sin_addr.  The form presented has a few

  -	The SIP address is aligned on a 64-bit boundary within the

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

  -	The union declaration is simpler than the alternative.

3.3 The socket functions

AF_SIP can be used interchangeably with AF_INET in the "domain" argument
(the first argument) of the socket() function, e.g:

	s = socket (AF_SIP, SOCK_STREAM, 0);

Using AF_SIP informs the kernel that the application would like to
receive SIP addresses rather than IPv4 addresses in all system calls
that return addresses.  The functions that return internet addresses in
arguments are:


In all other ways, sockets obtained using a domain argument of AF_SIP
behave the same as those obtained using AF_INET in the domain argument.
In particular, addresses in either the SIP form or the IPv4 form can be
passed in to either type of socket in the system calls that pass in
addresses as arguments.  The socket functions that pass in addresses


This interchangeability is necessary because Unix allows sockets to be
passed to child processes across an exec() call.  Thus it is possible
for a pre-SIP application to obtain a socket using AF_INET, and then
pass this socket to a SIP knowledgeable child process which then might
do a system call (e.g. connect(), sendto()) that passes in an address.

Note that there is still a problem with SIP knowledgeable applications
passing AF_SIP sockets to an non-SIP knowledgeable application that then
does a system call that returns an address.  We are proposing the
SIP_ADDRFORM option to remedy this problem: SIP knowledgeable
applications can use the SIP_ADDRFORM option to "downgrade" an AF_SIP
socket to AF_INET before it is passed via exec to an unknown process.
And a SIP knowledgeable application that is passed in a socket from an
unknown process, can use the SIP_ADDRFORM option to "upgrade" the socket
to AF_SIP before doing any system calls that return addresses.

3.4 Setsockopt options

We define two options at the IPPROTO_IP level that can be used with
AF_INET or AF_SIP sockets.  They have the following definitions in

#define SIP_FLOWID	0x15		/* get/set SIP flow ID */
#define SIP_ADDRFORM	0x16		/* get/set form of returned addrs */

Using the SIP_FLOWID option via setsockopt() sets the value of the flow
ID (a.k.a the SIP reserved field) used in all outgoing SIP packets sent
via that socket.  Using SIP_FLOWID via getsockopt() returns the flow ID
value given in the last setsockopt() call, not the flow ID in received
packets.  The value of the argument to the SIP_FLOWID option is a u_long

Using the SIP_ADDRFORM option via setsockopt() tells the kernel the form
of addresses (SIP or IPv4) that are to be returned in the system calls
that return addresses.  Using the SIP_ADDRFORM option via the
getsockopt() call informs the application in what form the kernel will
be returning addresses.  The value of the argument to the SIP_ADDRFORM
option is a u_long type.  The only valid arguments that may be passed or
returned by the SIP_ADDRFORM option are AF_INET and AF_SIP.

3.5  Name-to-address translation functions

We create a new function call with the form:

     struct hostent *gethostbyname2(const char *name, int type);

This interface looks the given host name up in the naming service and
returns a list of addresses.  The type argument is used to determine
what form of address -- 4-byte IPv4 or 8-byte SIP address -- to return
to the caller in the h_addr_list field of the hostent structure.

If the type argument is AF_INET, gethostbyname2() behaves to the
application exactly like gethostbyname().  That is, it returns an array
of 4-byte IPv4 addresses.  If AA records are found, then the low-order 4
bytes of each SIP address are returned.  If only A records are found,
then the associated 4-byte IP address is returned.

If the type argument is AF_SIP, then the h_addr_list contains an array
of 8-byte SIP addresses.  If AA records are found, then the full SIP
address of each record is returned.  If only A records are found, then
each 8-byte address returned is composed by copying the 4-byte IP
address in the A record into the low-order 4 bytes, and setting the
high-order 4-bytes to zero.

This interface is adapted from one proposed by Christian Huitema in an
email message to the SIP mailing list.  Christian's proposal had the
application determine the form of the returned address (4-byte IPv4 or
8-byte SIP) based on the return value of the function.  This proposal
allows the application to be simpler, since it can always
unconditionally bcopy() an 8-byte address returned by gethostbyname2()
into a sockaddr_in.  Also, the semantics of the gethostbyname2() with
type set to 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

If type is AF_INET, then len must be 4 and addr points to a 4-byte IPv4
address.  If type is AF_SIP, then len must be 8 and addr points to an
8-byte SIP address.

3.6 Open Issues

The API changes described here are just the beginning.  Among the
other changes we might want to consider 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 SIP

  -	There are a number of functions (inet_addr(), inet_ntoa()) for
	translating IPv4 addresses to and from printable form.  Should
	we define similar functions for 64-bit SIP addresses?

  -	The format of the "/etc/hosts" file currently supports only
	IPv4 addresses.  Should we extend the format of the existing
	file to handle SIP addresses?  Or should we invent a file with
	a new name for storing SIP host addresses.

  -	The name of the function gethostbyname2() might confuse
	people.  Should we pick a different name?