Network Interface Guide

Transport Selection

A distributed application must use a standard interface to the transport services to be portable to different protocols. Transport selection services provide an interface that allows an application to select which protocols to use. This makes an application "protocol" and "medium" independent.

Transport selection makes it easy for a client application to try each available transport until it establishes communication with a server. Transport selection lets server applications accept requests on multiple transports, and in doing so, communicate over a number of protocols. Transports can be tried in either the order specified by the local default sequence or in an order specified by the user.

Choosing from the available transports is the responsibility of the application. The transport selection mechanism makes that selection uniform and simple.

How Transport Selection Works

The transport selection component is built around:

The NETPATH variable is set by the user; it contains an ordered list of transport identifiers. The transport identifiers match the netconfig network ID field and are links to records in the netconfig(4) file. The netconfig(4) file is described in "/etc/netconfig File". The network selection interface is a set of access routines for the network-configuration database.

One set of library routines accesses only the /etc/netconfig entries identified by the NETPATH environment variable:

setnetpath(3NSL)Initializes the search of NETPATH
getnetpath(3NSL)Returns a pointer to the netconfig(4) entry that corresponds to the next component of the NETPATH variable
endnetpath(3NSL)Releases the database pointer to elements in the NETPATH variable when processing is complete

These routines are described in "NETPATH Access to netconfig(4) Data" and in getnetpath(3NSL). They let the user influence the selection of transports used by the application.

To avoid user influence on transport selection, use the routines that access the netconfig(4) database directly. These routines are described in "Accessing netconfig(4)" and in getnetconfig(3NSL):

setnetconfig(3NSL) Initializes the record pointer to the first index in the database
getnetconfig(3NSL)Returns a pointer to the current record in the netconfig(4) database and increments the pointer to the next record
endnetconfig(3NSL) Releases the database pointer when processing is complete

The following two routines manipulate netconfig(4) entries and the data structures they represent. These routines are described in "Accessing netconfig(4)":

getnetconfigent(3NSL)Returns a pointer to the struct netconfig structure corresponding to netid
freenetconfigent(3NSL)Frees the structure returned by getnetconfigent(3NSL)

/etc/netconfig File

The netconfig(4) file describes all transport protocols on a host. The entries in the netconfig(4) file are explained briefly in Table 4-1 and in more detail in the netconfig(4) man page.

Table 4-1 netconfig(4) File

Entries 

Description 

network ID

A local representation of a transport name (such as tcp). Do not assume that this field contains a well-known name (such as tcp or udp) or that two systems use the same name for the same transport.

semantics

The semantics of the particular transport protocol. Valid semantics are:

  • tpi_clts - connectionless

  • tpi_cots - connection oriented

  • tpi_cots_ord - connection oriented with orderly release

flags

Can take only the values, v, or hyphen (-). Only the visible flag (-v) is defined.

protocol family

The protocol family name of the transport provider (for example, inet or loopback).

protocol name

The protocol name of the transport provider. For example, if protocol family is inet, then protocol name is tcp, udp, or icmp. Otherwise, the value of protocol name is a hyphen (-).

network device

The full path name of the device file to open when accessing the transport provider 

name-to-address translation libraries

Names of the shared objects. This field contains the comma-separated file names of the shared objects that contain name-to-address mapping routines. Shared objects are located through the path in the LD_LIBRARY_PATH variable. A "-" in this field indicates redirection to the name service switch policies for hosts and services.

Example 4-1 shows a sample netconfig(4) file. Use of the netconfig(4) file has been changed for the inet transports, as described in the commented section in the sample file. This change is also described in "Name-to-Address Mapping".


Example 4-1 Sample netconfig(4) File

# The "Network Configuration" File.
#
# Each entry is of the form:
#
#<net <semantics>  <flags> <proto    <proto   <device>    	<nametoaddr_libs>
# id>                       family>   name>
#
# The "-" in <nametoaddr_libs> for inet family transports indicates redirection
# to the name service switch policies for "hosts" and "services. The "-" may be
# replaced by nametoaddr libraries that comply with the SVR4 specs, in which
# case the name service switch will be used for netdir_getbyname, netdir_
# getbyaddr, gethostbyname, gethostbyaddr, getservbyname, and getservbyport.
# There are no nametoaddr_libs for the inet family in Solaris anymore.
#
udp       tpi_clts     v   inet       udp      /dev/udp        -
#
tcp       tpi_cots_ord v   inet       tcp      /dev/tcp        -
#
icmp      tpi_raw      -   inet       icmp     /dev/icmp       -
#
rawip     tpi_raw      -   inet       -        /dev/rawip      -
#
ticlts    tpi_clts     v   loopback   -        /dev/ticlts     straddr.so
#
ticots    tpi_cots     v   loopback   -        /dev/ticots     straddr.so
#
ticotsord tpi_cots_ord v   loopback   -        /dev/ticotsord  straddr.so
#

Network selection library routines return pointers to netconfig entries. The netconfig structure is shown in Example 4-2.


Example 4-2 netconfig Structure

struct netconfig {
   char  *nc_netid;                /* network identifier */
   unsigned  int   nc_semantics;   /* semantics of protocol */
   unsigned  int   nc_flag;        /* flags for the protocol */
   char *nc_protofmly;             /* family name */
   char *nc_proto;                 /* proto specific */
   char *nc_device;                /* device name for network id */
   unsigned  int   nc_nlookups;    /* # entries in nc_lookups */
   char **nc_lookups;              /* list of lookup libraries */
   unsigned  int   nc_unused[8];
};

Valid network IDs are defined by the system administrator, who must ensure that network IDs are locally unique. If they are not, some network selection routines can fail. For example, it is not possible to know which network getnetconfigent("udp") will use if there are two netconfig entries with the network ID udp.

The system administrator also sets the order of the entries in the netconfig(4) database. The routines that find entries in /etc/netconfig return them in order, from the beginning of the file. The order of transports in the netconfig(4) file is the default transport search sequence of the routines. Loopback entries should be at the end of the file.

The netconfig(4) file and the netconfig structure are described in greater detail in the netconfig(4) man page.

NETPATH Environment Variable

An application usually uses the default transport search path set by the system administrator to locate an available transport. However, when a user wants to influence the choices made by an application, the application can modify the interface by using the environment variable NETPATH and the routines described in the section, "NETPATH Access to netconfig(4) Data". These routines access only the transports specified in the NETPATH variable.

NETPATH is similar to the PATH variable. It is a colon-separated list of transport IDs. Each transport ID in the NETPATH variable corresponds to the network ID field of a record in the netconfig(4) file. NETPATH is described in the environ(4) man page.

The default transport set is different for the routines that access netconfig(4) through the NETPATH environment variable (described in the next section) and the routines that access netconfig(4) directly. The default transport set for routines that access netconfig(4) via NETPATH consists of the visible transports in the netconfig(4) file. For routines that access netconfig(4) directly, the default transport set is the entire netconfig(4) file. A transport is visible if the system administrator has included a v flag in the flags field of that transport's netconfig(4) entry.

NETPATH Access to netconfig(4) Data

Three routines access the network configuration database indirectly through the NETPATH environment variable. The variable specifies the transport or transports an application is to use and the order to try them. NETPATH components are read from left to right. The functions have the following interfaces:

#include <netconfig.h>

void *setnetpath(void);
struct netconfig *getnetpath(void *);
int endnetpath(void *);

A call to setnetpath(3NSL) initializes the search of NETPATH. It returns a pointer to a database that contains the entries specified in a NETPATH variable. The pointer, called a handle, is used to traverse this database with getnetpath(3NSL). The setnetpath(3NSL) function must be called before the first call to getnetpath(3NSL).

When first called, getnetpath(3NSL) returns a pointer to the netconfig(4) file entry that corresponds to the first component of the NETPATH variable. On each subsequent call, getnetpath(3NSL) returns a pointer to the netconfig(4) entry that corresponds to the next component of the NETPATH variable; getnetpath(3NSL) returns NULL if there are no more components in NETPATH. A call to getnetpath(3NSL) without an initial call to setnetpath(3NSL) causes an error; getnetpath(3NSL) requires the pointer returned by setnetpath(3NSL) as an argument.

getnetpath(3NSL) silently ignores invalid NETPATH components. A NETPATH component is invalid if there is no corresponding entry in the netconfig(4) database.

If the NETPATH variable is unset, getnetpath(3NSL) behaves as if NETPATH were set to the sequence of default or visible transports in the netconfig(4) database, in the order in which they are listed.

endnetpath(3NSL) is called to release the database pointer to elements in the NETPATH variable when processing is complete. endnetpath(3NSL) fails if setnetpath(3NSL) was not called previously. Example 4-3 shows the setnetpath(3NSL), getnetpath(3NSL), and endnetpath(3NSL) routines.


Example 4-3 setnetpath(3NSL), getnetpath(3NSL), and endnetpath(3NSL) Functions

#include <netconfig.h>

void *handlep;
struct netconfig *nconf;

if ((handlep = setnetpath()) == (void *)NULL) {
   nc_perror(argv[0]);
   exit(1);
}

while ((nconf = getnetpath(handlep)) != (struct netconfig *)NULL)
{
   /*
    * nconf now describes a transport provider.
    */
}
endnetpath(handlep);

The netconfig(4) structures obtained through getnetpath(3NSL) become invalid after the execution of endnetpath(3NSL). To preserve the data in the structure, use getnetconfigent(nconf->nc_netid) to copy them into a new data structure.

Accessing netconfig(4)

Three functions access /etc/netconfig and locate netconfig(4) entries. The routines setnetconfig(3NSL), getnetconfigent(3NSL), and endnetconfig(3NSL) have the following interfaces:

#include <netconfig.h>

void *setnetconfig(void);
struct netconfig *getnetconfig(void *);
int endnetconfig(void *);

A call to setnetconfig(3NSL) initializes the record pointer to the first index in the database; setnetconfig(3NSL) must be used before the first use of getnetconfig(3NSL). setnetconfig(3NSL) returns a unique handle (a pointer into the database) to be used by the getnetconfig(3NSL) routine. Each call to getnetconfig(3NSL) returns the pointer to the current record in the netconfig(4) database and increments its pointer to the next record. It can be used to search the entire netconfig(4) database. getnetconfig(3NSL) returns a NULL at the end of file.

You must use endnetconfig(3NSL) to release the database pointer when processing is complete. endnetconfig(3NSL) must not be called before setnetconfig(3NSL).


Example 4-4 setnetconfig(3NSL), getnetconfig(3NSL), and endnetconfig(3NSL) Functions

void *handlep;
struct netconfig *nconf;

if ((handlep = setnetconfig()) == (void *)NULL){
   nc_perror(argv[0]);
   exit(1);
}
/*
 * transport provider information is described in nconf.
 * process_transport is a user-supplied routine that
 * tries to connect to a server over transport nconf.
 */
while ((nconf = getnetconfig(handlep)) != (struct netconfig *)NULL){
	   if (process_transport(nconf) == SUCCESS)
      break;
}
endnetconfig(handlep);

The last two functions have the following interface:

#include <netconfig.h>
struct netconfig *getnetconfigent(char *);
int freenetconfigent(struct netconfig *);

getnetconfigent(3NSL) returns a pointer to the struct netconfig structure corresponding to netid. It returns NULL if netid is invalid. setnetconfig(3NSL) need not be called before getnetconfigent(3NSL).

freenetconfigent(3NSL) frees the structure returned by getnetconfigent(3NSL). Example 4-5 shows the getnetconfigent(3NSL) and freenetconfigent(3NSL) routines.


Example 4-5 getnetconfigent(3NSL) and freenetconfigent(3NSL) Functions

/* assume udp is a netid on this host */
struct netconfig *nconf;

if ((nconf = getnetconfigent("udp")) == (struct netconfig *)NULL){
   nc_perror("no information about udp");
   exit(1);
}
process_transport(nconf);
freenetconfigent(nconf);

Loop Through All Visible netconfig(4) Entries

The setnetconfig(3NSL) call is used to step through all the transports marked visible (by a v flag in the flags field) in the netconfig(4) database. The transport selection routine returns a netconfig(4) pointer.

Looping Through User-Defined netconfig(4) Entries

Users can control the loop by setting the NETPATH environment variable to a colon-separated list of transport names. If NETPATH is set as follows:


NETPATH=tcp:udp

The loop first returns the tcp entry, then the udp entry. If NETPATH is not defined, the loop returns all visible entries in the netconfig(4) file in the order in which they are stored. The NETPATH environment variable lets users define the order in which client-side applications try to connect to a service. It also lets the server administrator limit transports on which a service can listen.

Use getnetpath(3NSL) and setnetpath(3NSL) to obtain or modify the network path variable. Example 4-6 shows the form and use, which are similar to the getnetconfig(3NSL) and setnetconfig(3NSL) routines.


Example 4-6 Looping Through Visible Transports

void *handlep;
struct netconfig *nconf;

if ((handlep = setnetconfig() == (void *) NULL) {
	   nc_perror("setnetconfig");
   exit(1);
}
while (nconf = getnetconfig(handlep))
	   if (nconf->nc_flag & NC_VISIBLE)
      doit(nconf);
(void) endnetconfig(handlep);