Internet Engineering Task Force R. E. Gilligan (Sun) draft-ietf-sipp-bsd-api-02.txt R. Govindan (Bellcore) S. Thomson (Bellcore) J. Bound (Digital) April 1994 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 writ- ten 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 applica- tions. This memo presents a set of changes to the BSD socket API to support SIPP. The changes include a new data structure to carry SIPP address sequences, new name to address translation library functions, 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 October 27, 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." To learn the current status of any Internet-Draft, please check the 1id-abstracts.txt listing contained in the Internet-Drafts Shadow Directories on ds.internic.net, nic.nordu.net, ftp.isi.edu, or Expires: October 1994 [Page 1] INTERNET DRAFT SIPP BSD API April 1994 munnari.oz.au. Distribution of this memo is unlimited. 1. Introduction. While IP destination addresses are 32 bits long, a SIPP destination may, in general, be represented by a sequence of 64-bit addresses [2]. The APIs that the BSD system provides make the size of an IP address quite visible to an application; virtually all TCP/IP appli- cations 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 sys- tems. These APIs are expected to evolve as we gain more implementa- tion experience. 2. Design considerations There are a number of important considerations in designing changes to these well-worn APIs. - The modified API should provide both source and binary compati- bility for programs written to the existing API. That is, existing 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. - 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. - Applications should be able to use the new API to interoperate both with SIPP and IPv4 hosts. Applications need not know whether they are communicating with an IPv4 host or a SIPP host (i.e. they should be "C-bit ignorant", [3]). - SIPP addresses passed in the API should be 64-bit aligned. Expires: October 1994 [Page 2] INTERNET DRAFT SIPP BSD API April 1994 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. We define a new address family type for SIPP applications. The socket address structure for this address family is larger than the sockaddr_in structure, to accommodate SIPP address sequences. We define a socket option to change the form of addresses communicated between the kernel and applications. Two new name-to-address translation functions are introduced which have similar functionality to gethostbyname() and gethostbyaddr(), but return a new hostent structure, and support addresses in both the IPv4 and SIPP address families. Since SIPP address sequences may have different lengths in general, a new hostent structure is needed because the existing one does not support addresses of different lengths. Also, gethostbyname() does not include an address type argument, and most applications that use it assume that the address array that it returns consists of 4-byte IP addresses. The new func- tion replacing gethostbyname() allows an application to specify the type of address to be returned. Finally, a new interface is needed in order to set the SIPP flow label. The most straightforward way to do this is to define new set- sockopt() options at the IPPROTO_IP level. 3. Implementation experience The Sun IPAE [3]/SIPP implementation exposed some issues in designing a compatible application interface. 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 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. It is important, however, 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 applica- tion passes in SIPP form addresses, the kernel can return SIPP form Expires: October 1994 [Page 3] INTERNET DRAFT SIPP BSD API April 1994 addresses to the application. 4. Interface specification 4.1. New address family We define a address family macro in : #define AF_SIPP 24 /* Simple Internet Protocol */ The AF_SIPP definition is used only to distinguish between the origi- nal AF_INET form of the sockaddr_in structure, and a new form that we have defined. Thus there is no corresponding PF_SIPP definition. 4.2. Socket address structure The sockaddr_in structure is used in the socket system calls to pass IPv4 addresses between the application and the kernel. This structure is insufficient for conveying SIPP address sequences, so we define a new sockaddr_sipp structure: struct sockaddr_sipp { short ss_family; /* AF_SIPP */ u_short ss_port; u_short ss_reserved; u_short ss_len; /* Number of SIPP addresses */ struct sipp_addr ss_addr[7]; /* SIPP Addr Seq */ }; The value of the ss_family field must be AF_SIPP. "Struct sipp_addr" defines a single 64-bit SIPP address. The ss_addr field contains the SIPP address sequence in ascending order of addresses: that is, ss_addr[0] contains the identifying address (see [2]), ss_addr[1] contains the next higher-order address and so on. It is unlikely that more than seven addresses will be required to represent source and destination address sequences. For compatibility with existing IPv4 applications, however, BSD implementations must continue to support the sockaddr_in form of socket addresses. We describe in Section 4.4 how applications can convert from one form of socket address to another. Expires: October 1994 [Page 4] INTERNET DRAFT SIPP BSD API April 1994 4.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 sockaddr_sipp address structure (with address family AF_SIPP) or the sockaddr_in address structure (with address family AF_INET) in the system calls that pass addresses in to the kernel. None of the socket functions themselves need to be changed, since the socket interface accepts addresses of different lengths. 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_sipp structure in the AF_SIPP form. If the appli- cation calls no socket function that passes in an address before cal- ling one that returns an address, then that function returns the sockaddr_in address structure. 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() Expires: October 1994 [Page 5] INTERNET DRAFT SIPP BSD API April 1994 4.4. Sockets passed across exec() While existing, unmodified IPv4 applications use the sockaddr_in socket address structure, new SIPP-capable applications should be written to use the sockaddr_sipp socket address structure. Unix allows open sockets to be passed across an exec() call; so, 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 applica- tion. To remedy these problems, we define 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 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 IPv4 address returned on a call to a "downgraded" socket is the lower 32- bits of the identifying address of the SIPP address sequence that would have been returned had the socket not been "downgraded". The macro definition for this new option in 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) 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. Expires: October 1994 [Page 6] INTERNET DRAFT SIPP BSD API April 1994 4.5. Flow Label The SIPP header has a 28 bit field reserved to hold a "flow label". 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 label field of transmitted SIPP packets. So far, we have not defined any interface for an application to learn the flow label set in received SIPP packets. The macro definition for this new option in is: #define SIPP_FLOWLABEL 0x15 /* SIPP flow label */ The SIPP_FLOWLABEL option is at the IPPROTO_IP level. An example of how an application might use this option is: int flowlbl = 0x0f3c91ab; /* made up for this example */ if (setsockopt(s, IPPROTO_IP, SIPP_FLOWLABEL, (char *) &flowlbl, sizeof(flowlbl)) == -1) perror("setsockopt SIPP_FLOWLABEL"); The SIPP_FLOWLABEL option can also be used with the getsockopt() option to retrieve the flow label value given in the last set- sockopt() call. An application may wish the kernel to select the SIPP flow label; to do so, it invokes the SIPP_FLOWLABEL setsockopt() with a zero-valued flow label. Since the definition of SIPP flows may change as the protocol develops [1], this option may also change in the future. Thus appli- cation developers should consider this option "experimental." 4.6. Name-to-address translation functions New functions similar to gethostbyname() and gethostbyaddr() are defined which support addresses in different address families, and which return a new hostent structure. The new hostent structure called struct hostent_sipp is defined as follows in : Expires: October 1994 [Page 7] INTERNET DRAFT SIPP BSD API April 1994 struct hostent_sipp { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address family */ u_long *h_len_list; /* list of lengths of addresses */ char **h_addr_list; /* list of pointers to addresses */ }; This structure contains the same information as struct hostent except that the single integer length field, h_length, is replaced by a pointer to a list of lengths, to enable the length of each address to be specified. Each element i of the array h_len_list is the length of the corresponding address referred to in h_addr_list[i]. A new function similar to gethostbyname(), called hostname2addr(), is defined to enable applications to specify the type of address to be looked up: struct hostent_sipp *hostname2addr(const char *name, int af); This new function looks up the given name in the name service and returns the completed hostent_sipp structure if the lookup succeeds, and NULL otherwise. The name argument is the domain name of the host to look up. The af argument specifies the type of the address -- IPv4 (AF_INET) or SIPP (AF_SIPP) -- to return to the caller in the h_addr_list field of the hostent_sipp structure. If the af argument is AF_INET, hostname2addr() queries the name ser- vice for IPv4 addresses and, if any are found, returns a hostent_sipp structure that includes an array of IPv4 addresses and a correspond- ing array of address lengths. The end of the address array is indi- cated by a NULL pointer, while the end of the length array is indi- cated by a zero length. Each IPv4 address is encoded in network byte order. If the af argument is AF_SIPP, the hostent_sipp structure returned by hostname2addr() contains a null-terminated array of SIPP address sequences and a corresponding zero-terminated array of address sequence lengths. As in the sockaddr_sipp structure, an address sequence returned in struct hostent_sipp is encoded in ascending order of addresses. Each address is in network byte order. In the case of the AF_SIPP address family, the hostname2addr() function first queries the name service for SIPP address sequences. If address sequences are found, they are returned in the hostent_sipp structure. If no address sequences are found, the function queries the name Expires: October 1994 [Page 8] INTERNET DRAFT SIPP BSD API April 1994 service for IPv4 addresses. If an IPv4 address is found, it is returned as a 64-bit SIPP address by storing its value in the low- order 32 bits of the SIPP address and setting the high-order bit (the "C-bit") to one, and the rest of the high-order prefix to zero. A new function, called addr2hostname(), is defined with a similar interface to the gethostbyaddr() function, but which returns a hostent_sipp structure: struct hostent_sipp *addr2hostname(const char *addr, int len, int af); Addr2hostname() performs an inverse lookup in the name service, returning a completed hostent_sipp structure if the lookup succeeds, or NULL, if the lookup fails. Addr2hostname() supports both the AF_INET and AF_SIPP address families. If the af argument is AF_INET, then len must be 4 and addr points to an IPv4 address. If af is AF_SIPP, then len must be in multiples of 8 and addr points to a SIPP address sequence. When passing a SIPP address sequence as an argu- ment, it is encoded as it is returned in struct hostent_sipp by hostname2addr(). If the addr argument is an IPv4 address in SIPP form (the high-order bit is set to one, the rest of the high-order 32-bit prefix is set to zero), hostname2addr() performs an inverse lookup on the low-order 32 bits of the address only. In both cases, struct hostent_sipp returns the domain name of the host that has the address specified. Note that the existing BSD gethostbyname() and gethostbyaddr() func- tions must be retained to provide compatibility with existing appli- cations. 4.7. Address input/output functions BSD Unix provides two functions, inet_addr() and inet_ntoa(), to con- vert an IPv4 address between binary and printable form. SIPP appli- cations need similar functions. We have defined the following two functions to convert both SIPP and IPv4 addresses: int ascii2addr(long af, char *cp, char *ap); and char *addr2ascii(long af, char *ap, long n, char *buf); The first function converts an ascii string to an address in the Expires: October 1994 [Page 9] INTERNET DRAFT SIPP BSD API April 1994 address family specified by the af argument. Currently AF_INET and AF_SIPP address families are supported. The cp argument points to the ascii string being passed in. The ap argument points to a buffer that is to be used by the function to return the address. Ascii2addr() returns the length of the address in octets if the conversion succeeds, and -1 otherwise. The function does not modify the storage pointed to by ap if the conversion fails. The application must ensure that the buffer referred to by ap is large enough to hold the converted address. 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 one of the two standard SIPP printing forms[2]: xxxx:xxxx:ddd.ddd.ddd.ddd or xxxx:xxxx:xxxx:xxxx (possibly extended) where xxxx is a 1 to 4 digit hex value and ddd is a 1 to 3 digit decimal number between 0 and 255. The The second function converts an address 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 an IPv4 address, if the af argument is AF_INET, and a SIPP address sequence, if the af argument is AF_SIPP. The argument n contains the length in octets of the address referred to by the ap argument. The buf argu- ment points to a buffer that the function can use to store the ascii string. If the buf argument is NULL, the function uses its own private static buffer. The length of the address that can be con- verted in this case is implementation-dependent. If the application specifies a buf argument, it must be large enough to hold the ascii conversion of the address specified as an argument. The addr2ascii() function returns a pointer to the buffer containing the ascii string if the conversion succeeds, and NULL otherwise. The function does not modify the storage pointed to by buf if the conver- sion fails. Expires: October 1994 [Page 10] INTERNET DRAFT SIPP BSD API April 1994 5. Security Considerations Security issues are not discussed in this document. Acknowledgements Thanks to all who provided feedback to the first revision of this document, including Christian Huitema, Craig Partridge, Steve Deer- ing, Andrew Cherenson, Charles Lynn, Ran Atkinson, Erik Nordmark, Glenn Trewitt, Fred Baker, Robert Elz, and Dean D. Throop. References [1] S. Deering, "Simple Internet Protocol Plus (SIPP) Specifica- tion", Internet Draft, February 1994, . [2] S. Deering, P. Francis and R. Govindan, "Simple Internet Proto- col Plus Routing and Addressing Overview", Internet Draft, . [3] R.Gilligan, E. Nordmark, R. Hinden, "IPAE: The SIPP Interopera- bility and Transition Mechanism", Internet Draft, March 1994, . Expires: October 1994 [Page 11] INTERNET DRAFT SIPP BSD API April 1994 Authors' Address Jim Bound Robert E. Gilligan Digital Equipment Corporation Sun Microsystems, Inc. 110 Spitbrook Road ZK3-3/U14 2550 Garcia Avenue Nashua, NH 03062-2698 Mailstop UMTV05-44 Mountain View, California 94043-1100 Telephone: +1 603 881 0400 Phone: +1 415 336 1012 EMail: bound@zk3.dec.com Email: bob.gilligan@eng.sun.com Ramesh Govindan Susan Thomson Bell Communications Research Bell Communications Research MRE 2P-341, 445 South Street MRE 2P-343, 445 South Street Morristown, NJ 07960 Morristown, NJ 07960 Telephone: +1 201 829 4406 Telephone: +1 201 829 4514 Email: rxg@thumper.bellcore.com Email: set@thumper.bellcore.com Expires: October 1994 [Page 12]