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.
The transport selection component is built around:
A network configuration database (the /etc/netconfig file), which contains an entry for each network on the system
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) |
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
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".
# 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.
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 VariableAn 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.
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.
#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.
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).
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.
/* 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);
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.
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.
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);