TCP/IP for DOS Socket Library Reference
Appendix E. Porting BSD Applications
There are differences between the programming interfaces for sockets as defined for 4. 1BSD and sockets as defined for 4.3BSD. When you convert programs using 4. IBSD sockets to 4.3BSD sockets, you need to account for the differences in order for the converted programs to work properly.
There are also some differences between the 4.3BSD programming interface as implemented for the UNIX operating system and the 4.3BSD interface as implemented in the NetWare Communication Services.
This appendix describes the differences between programming interfaces using 4. IBSD sockets and the programming interface in the toolkit, which uses 4.3BSD sockets. It can help you convert your existing code written for the 4. 1BSD interface to the new 4.3BSD interface used by the NetWare Communication Services.
Differences Between 4.1BSD and 4.3BSD
The changes from the 4. 1BSD socket interface to the 4.3BSD socket interface fall into the following categories:
The major differences between the 4.1BSD interface and the 4.3BSD interface are in how sockets are set up to listen for connection requests, how connections are actually accepted, and howsocket options are set and read.
Another difference is that the 4.3BSD interface requires the length of the socket address structure (usually sackaddr or sockaddr_in) as a parameter wherever the socket address structure is used. The 4. IBSD interface did not require this parameter.
These differences are discussed further in the following sections.
New Include Files
The interface provides a new version of the SOCKET.H include file. This file provides the proper prototypes of the 4.3BSD interface functions for any memory model. SOCKET.H should be included in any program making use of the 4.3BSD interface functions in the DOS or Windows socket libraries. This file is provided as a convenience to you and its use is strongly recommended but not required. However, if you choose not to use it, you must prototype properly any 4.3BSD interface functions used; otherwise the runtime results may be unpredictable.
The SOCKET.H include file in the NetWare Communication Services v4. 1 combines all of the declarations that were formerly provided in the following include files:
| ARPA/NAMESER.H | NETINET/IP.H |
| BREAK.H | NETINET/IP_ICMP.H |
| FILIO.H | RESOLV.H |
| IOCTL.H | SIGNAL.H |
| NETDB.H | SOCKIO.H |
| NETINET/IN.H | UIO.H |
| NETINET/IN_SYSTM.H |
To maintain compatibility, the v4.1 toolkit provides versions of these files that each contain a single #include Statement pointing to SOCKET.H. As a result, programs that include the above files continue to compile correctly. New socket library programs need to include only the SOCKET.H header file to access all function prototypes needed for all socket library functions.
New Functions
The 4.3BSD socket libraries include new services not found in the 4. 1BSD socket model. In addition to the new services, some existing services in the 4.1BSD socket model are provided in new function calls by the 4.3BSD style interface. This section describes the new function calls provided by the socket library, and how they relate to the 4.1BSD socket interface.
bind()
This function binds (assigns) an address to a socket. There is no direct equivalent to this function in the 4. IBSD interface. The 4. 1BSD socket() function automatically bound an address to a new socket.
gethostname()
This function returns the standard hostname for the current host. The 4. IBSD equivalent would be the following:
char *name name = "localhost"; rhost(&name);
getmyipaddr()
This function returns the current IP address of the local host. This function is equivalent to calling the rhost("localhost") function in the 4.1BSD socket interface.
getpeername()
This function returns the socket address of the remote peer connected to a socket. There is no equivalent to this function in the 4. 1BSD interface. The socket address returned from getpeername() is the same as the socket address returned from both connect() and accept().
getsockname()
This function returns a socket address. The 4.1BSD interface function socketaddr() is equivalent to getsockname(). The socket address returned from getsockname() is the same as the address returned from the bind() function.
getsockopt()
This function returns the status of options associated with a socket. This function does not duplicate any 4. 1BSD functions. The functional equivalent for the SIOCGKEEP and SIOCGLINGER options previously accessed with the 4.1BSD soioctl() and ioctl() functions has been moved to the 4.3BSD getsockopt() functions.
listen()
This function prepares a socket for incoming connection requests. The function has two purposes: it establishes a connection request queue length, and it puts the socket in passive mode so that the socket can accept incoming connection requests. The queue allows pending connection requests to be backlogged before being accepted. When the queue is full, incoming connection requests are rejected.
The following code segment shows the steps required using the 4.32BSD interface to set up a socket to listen for incoming connection requests:
s = socket(PF_INET, SOCK_STREAM, 0); bind(s, &listen_addr, sizeof(listen_addr));
The equivalent code using the 4.1BSD interface would be as follows:
s = socket(SOCK_STREAM, (struct sockprot *)0, &listen_addr, SO_ACCEPTCONN);
readv0
This function performs a scattered read. There is no equivalent to this function in the 4. 1BSD interface. The iovec structure (a list of I/O vector buffers) and scattered I/O using the iovec structure are not supported in the 4.1BSD interface.
recvfrom()
This function receives a message from a socket. The function is similar to the 4.1BSD interface receive() function. The order of the parameters is different, and there are two new parameters that deal with receive flags and the length of the socket address.
recvmsg()
This function receives a message from a socket. The recvmsg() call can be used with both connected and unconnected sockets. The 4.1BSD interface has no equivalent function. The msghdr structure and the flags parameter are not supported in the 4.1BSD interface.
sendmsg()
This function sends a message from a socket. The sendmsg() function can be used with both connected and unconnected sockets. The 4.1BSD interface has no equivalent function. The msghdr structure and the flags parameter are not supported in the 4.1BSD interface.
sendto()
This function sends a message from an unconnected socket. This function is very similar to the 4. 1BSD send() function. The order of the parameters differs, and there are two new parameters, flags and len. The flags parameter specifies send flags and len is the length of the message.
setsockopt()
This function manipulates options associated with a socket. The function replaces the setting of options that could occur with the 4.1BSD socket() function and some of the operations performed by the 4.1BSD soioctl() and ioctl() functions.
The functional equivalents for the SIOCSKEEP and SIOCSLINGER options that were set via the 4. 1BSD soioctl() and ioctl() functions have been moved to the setsockopt() function.
shutdown()
This function closes part or all of a connection. The function is equivalent to the 4. 1BSD soioctl() and ioctl() SIOCDONE operation.
writev()
This function performs a gathered write. The 4.1BSD interface has no equivalent function. The iovec structure (a list of I/O vector buffers) and gathered I/O using the iovec structure are not supported in the 4. 1BSD interface.
Changes and Enhancements
Many 4.3BSD interface functions have the same names and purposes as 4. 1BSD interface functions, but have been changed or enhanced.
Transport Database Functions
The interface to the transport database files HOSTS, NETWORKS, PROTOCOL, and SERVICES has been simplified in v4. 1 of the NetWare Communication Services. In previous toolkit versions, and in the 4.3BSD interface, it was necessary to issue specialized function calls to open these files before entries could be extracted, and to close the files after reading. Enhanced function calls are now provided for each file that open the file, find and return an entry matching your search parameters, and close the file, all in one operation. These functions are:
In the 4.1 version of the toolkit, multiple versions of the transport database files can be maintained and searched by the functions discussed above. A path of directories to search for the files is defined in the Protocol TCPIP section of the NET.CFG file. See Appendix B for a complete explanation of this capability.
The following functions are no longer suppo rted in the v4. 1 toolkit. If your program calls any of these functions, a NO_RECOVERY error is returned:
| gethostent() | getnetent() | getprotoent() | getservent() |
| sethostent() | setnetent() | setprotoent() | setservent() |
| endhostent() | endnetent() | endprotoent() | endservent() |
accept()
The 4.3BSD accept() function has three significant differences from the 4.1BSD accept() function.
The first difference is that, unlike the 4.1BSD version of the function, it accepts multiple connection requests to the same socket. Each time a connection is accepted, a new socket is created that is connected to the requesting client and returned to the caller. The original listening socket can still accept additional connections. The 4.1BSD version of the accept() function accepts only one connection to a socket. A new 4.1BSD socket must be created to accept another connection.
The second difference is in how a socket is prepared to accept connections. In 4.3BSD, the socket(), bind(), and listen() functions must be called before the accept() function accepts connections.
The third difference is that the 4.3BSD accept() function has an additional address length parameter. This parameter indicates the size of the address structure passed to accept() and returns the resulting length of the address for the accepted connection.
connect()
The 4.3BSD connect() function has an additional address length parameter not used in the 4.1BSD connect() function.
soioetl() and ioetl()
Some of the operations provided by the 4.1BSD soioctl() and ioctl() functions have been moved to various 4.3BSD interface functions.
NOTE: In earlier TCP/IP 4.1BSD-based programming interfaces, this function was named soioctl(). The function in the NetWare Communication Services v4.1 is named ioctl().
The following soioctl() and ioctl() operations are supported in both the 4.1BSD and 4.3BSD interfaces:
The functional equivalents for the following operations in the 4.1BSD soioctl() and ioctl() functions have been moved to the 4.3BSD getsockopt() and setsockopt() functions:
The functional equivalent for the 4.1BSD soioctl() SIOCDONE operation can be found in the 4.3BSD interface shutdown() function.
The toolkit does not support out-of-band data handling. The 4. 1BSD soioctl() and ioctl() operations SIOCATMARK, SIOCSENDOOB, and SIOCRCVOOB are not supported.
The 4.1BSD soioctl() and ioctl() routing-table operations SIOCADDRT, SIOCHGRT, and SIOCDELRT are not supported in the 4.3BSD interface. Refer to the information concerning the NETUTIL utility in the TCP/IP for DOS Administrator's Guide.
recv()
The 4.3BSD recv() function is nearly equivalent to the 4.1BSD receive() function. Besides being spelled differently, the major differences are that the parameter list is different, and that recv() is used only with connected sockets, while the receive() function can be used with both connected and nonconnected sockets.
The recv() parameter list does not have a socket address parameter, and has an additional flags
parameter specifying optional receive processing.
select()
The 4.3BSD select() function is similar to the 4. 1BSD version of select(). The major differences are that the 4.3BSD select() has an additional parameter for selection of exception events, the timeout parameter is a pointer to a structure, and an indefinite timeout can be specified by passing a NULL pointer in the timeout parameter.
send()
The 4.3BSD send() function is nearly equivalent to the 4. 1BSD send() function. The major differences are that the parameter list is different, and that the 4.3BSD send() function can only be used with connected sockets, while the 4.1BSD send() can be used with both connected and nonconnected sockets. The 4.3BSD send() parameter list does not have a socket address parameter, and has an additional flags parameter specifying optional send processing.
socket()
The 4.3BSD socket() function has three differences from the 4.1BSD version of socket(). The 4.3BSD socket() function does not have any options or address parameters. Use the 4.3BSD bind() function to bind the socket to an address.
The 4.3BSD socket() function requires a domain family parameter, which in this case is always PF_ INET.
Currently, the only socket types supported are SOCK_STREAM and SOCK_DGRAM. The SOCK_RAW and SOCK_ETH socket types are not supported.
Converting Function Calls from 4.1BSD to 4.3BSD
Some function calls from your 4.1BSD programs are replaced by differently named functions or multiple functions in the 4.3BSD interface. This section lists the 4.1BSD calls for which you must use differently named functions or more than one function in the 4.3BSD interface, and describes the changes to make.
If a 4.1BSD function is not listed here, you can use the function with the same name in the 4.3BSD interface. Functions with the same names, however, may require different types and numbers of parameters. See the previous section for the differences.
receive()
The 4. 1BSD receive() function is replaced by the 4.3BSD recv() function, which is nearly
equivalent. In addition to the spelling difference, the major differences are that recv() is used only
with connected sockets, while the receive() function can be used with both connected and
nonconnected sockets; and the parameter list is different.
socket() and socket_anr()
These functions are both replaced by the synchronous socket() function in the 4.3BSD socket interface. After the socket() function terminates, call the bind() function to bind the port and address to the socket in the 4.3BSD interface. If the options parameter in the 4.1BSD interface is set to SO_ACCEPTCONN, in the 4.3BSD interface you can call the listen() function with the value of the backlog variable set to O. If the options parameter is set to any other value, use the 4.3BSD setsockopt() function.
The 4.3BSD interface does not have an asynchronous function equivalent to the 4. 1BSD socket_anr().
socketaddr()
This 4. 1BSD function is replaced by the getsockname() function in the 4.3BSD interface. The socket address returned from getsockname() is the same as the address returned from the bind() function.
soioctl() and soioetl_anr()
The 4.3BSD functions that you use in place of these functions depend on the command parameter value used. For command parameter values FIONREAD and FIONBIO, use the 4.3BSD ioctl() function. For command parameter values SIOCKEEP and SIOCLINGER, use the 4.3BSD setsockopt() function. For command parameter value SIOCDONE, use the 4.3BSD shutdown() function. The 4.3BSD interface does not have an asynchronous function equivalent tosoioctl_anr().
NOTE: The function named soioctl() in previous versions of the TCP/IP interface is named ioctl() in the UNIX operating system versions.
soreceive() and soreceive_anr()
For a NULL from parameter, use the 4.3BSD functions recv() and recv_anr(), respectively. If the from parameter is not NULL, use the 4.3BSD functions recvfrom() and recvfrom_anr(), respectively .
sosend() and sosend_anr()
For a NULL to parameter, use the 4.3BSD functions send() and send_anr(), respectively. If the to parameter is not NULL, use the 4.3BSD functions sendto() and sendto_anr(), respectively.
Porting 4.3BSD Applications with the Toolkit
The NetWare Communication Services tries to maintain as much compatibility with 4.3BSD sockets as possible. However, faithfully reproducing an exact 4.3BSD interface would have compromised other important design goals. This section explains differences from the 4.3BSD socket model.
Input/Output Functions
The most obvious difference is that the toolkit does not support generic functions for I/O to devices. The toolkit adds the soread(), sowrite(), and soclose() functions, which act only on sockets, to take the place of the 4.3BSD functions read(), write(), and close(), which act on any device including sockets.
If you are porting an existing 4.3BSD socket application to TCP/IP for DOS, be sure to pay particular attention to the use of the read(), write(), and close() functions. The resulting DOS application must use the soread(), sowrite(), and soclose() functions when manipulating sockets, and it must use the read(), write(), and close() functions only for file operations.
Transport Database Functions
Programs that access the database files in \NET\TCP (HOSTS, NETWORKS, PROTOCOL, and SERVICES) must be recoded to use the enhanced functions provided in toolkit v4.1 and eliminate calls to functions that are no longer supported. Use of the enhanced functions should result in a simplified program. See the section "Transport Database Functions" earlier in this chapter for details of the new functions and eliminated functions.
Name Resolution Functions
In various implementations of the 4.3BSD socket model, you may find two different types of database functions. Some implementations have functions, such as gethostbyname(), which retrieve host information from files in the /etc directory. Other implementations have functions that use the Domain Name System (DNS) to retrieve host information.
The toolkit provides both types of functions. The database functions use files in directories specified by the PATH setting in the Protocol TCPIP section of the workstation's NET.CFG file. The resolver functions res_mkquery() and res_send() use DNS.
In addition, the toolkit combines the two approaches in the rhost() and raddr() functions. When the rhost() function tries to resolve a name into a 32-bit IP address, it first checks the string to determine if it contains a valid IP address, in dotted notation, such as 130.57.6. 129. If the string is not a valid IP address, rhost() queries DNS to resolve the name. If the DNS query fails, rhost() then attempts to resolve the name by scanning the HOSTS file. If that attempt also fails, the function returns an error.
Similarly, when raddr() tries to resolve a 32-bit IP address into a name, it first queries DNS to resolve the address. If the DNS query fails, raddr() then attempts to resolve the name by scanning the HOSTS file. If that attempt also fails, the function returns an error.
PROTOCOL Database File
Because of the length and format requirements for filenames under DOS, the 4.3BSD PROTOCOLS database file has the name PROTOCOL (no terminal letter`S') in the TCP/IP implementation.
Porting Server Applications
Porting 4.3BSD server applications to DOS poses a general problem: the 4.3BSD server applications run in a multitasking environment, but DOS is not a multitasking operating system.
Most 4.3BSD server applications use the fork() function to spawn processes, each of which handles an individual connection. This approach is not available on a DOS system. Instead, the toolkit uses the select() function to maintain multiple concurrent connections between a single server application and different clients. The TCPSERV.C sample program in Appendix D demonstrates one method of supporting multiple connections from a single server application.