内に含まその他のドキュメントサポート リソース | PDF 文書ファイルをダウンロードする (337 KB)
Chapter 4 Transport Selection and Name-to-Address MappingThis chapter describes selecting transports and resolving network addresses. It further describes interfaces that enable you to specify the available communication protocols for an application. The chapter also explains additional functions that provide direct mapping of names to network addresses. Note - In this chapter the terms network and transport are used interchangeably to refer to the programmatic interface that conforms to the transport layer of the OSI Reference Mode. The term network is also used to refer to the physical collection of computers connected through some electronic medium. Transport Selection Is Multithread SafeThe interface described in this chapter is multithread safe. This means that applications that contain transport selection function calls can be used freely in a multithreaded application. Note, however, that the degree of concurrency available to applications is not specified. Transport SelectionA 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 WorksThe transport selection component is built around:
The One set of library routines accesses only the /etc/netconfig entries identified by the
These routines are described in " To avoid user influence on transport selection, use the routines that access the netconfig database directly. These routines are described in "Accessing netconfig" and in getnetconfig(3N):
The following two routines manipulate netconfig entries and the data structures they represent. These routines are described in "Accessing netconfig":
/etc/netconfig FileThe netconfig file describes all transport protocols on a host. The entries in the netconfig file are explained briefly in Table 4-1 and in more detail in the netconfig(4) man page. Table 4-1 The netconfig File
Example 4-1 shows a sample netconfig file. Use of the netconfig 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 File
Network selection library routines return pointers to netconfig entries. The netconfig structure is shown in Example 4-2. Example 4-2 The netconfig StructureValid 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 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 file is the default transport search sequence of the routines. Loopback entries should be at the end of the file. The netconfig file and the netconfig structure are described in greater detail in the netconfig(4) man page.
|
#include <netconfig.h> void *setnetpath(void); struct netconfig *getnetpath(void *); int endnetpath(void *); |
A call to setnetpath() 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(). The setnetpath() function must be called before the first call to getnetpath().
When first called, getnetpath() returns a pointer to the netconfig file entry that corresponds to the first component of the NETPATH variable. On each subsequent call, getnetpath() returns a pointer to the netconfig entry that corresponds to the next component of the NETPATH variable; getnetpath() returns NULL if there are no more components in NETPATH. A call to getnetpath() without an initial call to setnetpath() causes an error; getnetpath() requires the pointer returned by setnetpath() as an argument.
getnetpath() silently ignores invalid NETPATH components. A NETPATH component is invalid if there is no corresponding entry in the netconfig database.
If the NETPATH variable is unset, getnetpath() behaves as if NETPATH were set to the sequence of default or visible transports in the netconfig database, in the order in which they are listed.
endnetpath() is called to release the database pointer to elements in the NETPATH variable when processing is complete. endnetpath() fails if setnetpath() was not called previously. Example 4-3 shows the setnetpath(), getnetpath(), and endnetpath() routines.
The netconfig structures obtained through getnetpath() become invalid after the execution of endnetpath(). 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 entries. The routines setnetconfig(), getnetconfig(), and endnetconfig() have the following interfaces:
#include <netconfig.h> void *setnetconfig(void); struct netconfig *getnetconfig(void *); int endnetconfig(void *); |
A call to setnetconfig() initializes the record pointer to the first index in the database; setnetconfig() must be used before the first use of getnetconfig(). setnetconfig() returns a unique handle (a pointer into the database) to be used by the getnetconfig() routine. Each call to getnetconfig() returns the pointer to the current record in the netconfig database and increments its pointer to the next record. It can be used to search the entire netconfig database. getnetconfig() returns a NULL at the end of file.
You must use endnetconfig() to release the database pointer when processing is complete. endnetconfig() must not be called before setnetconfig().
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() returns a pointer to the struct netconfig structure corresponding to netid. It returns NULL if netid is invalid. setnetconfig() need not be called before getnetconfigent().
freenetconfigent() frees the structure returned by getnetconfigent(). Example 4-5 shows the getnetconfigent() and freenetconfigent() 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() call is used to step through all the transports marked visible (by a v flag in the flags field) in the netconfig database. The transport selection routine returns a netconfig 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 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() and setnetpath() to obtain or modify the network path variable. Example 4-6 shows the form and use, which are similar to the getnetconfig() and setnetconfig() 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);
|
Name-to-address mapping lets an application obtain the address of a service on a specified host, independent of the transport used. Name-to-address mapping consists of the following functions:
| netdir_getbyname() | Maps the host and service name to a set of addresses |
| netdir_getbyaddr() | Maps addresses into host and service names |
| netdir_free() | Frees structures allocated by the name-to-address translation routines |
| taddr2uaddr() | Translates an address and returns a transport-independent character representation of the address |
| uaddr2taddr() | The universal address is translated into a netbuf structure |
| netdir_options() | Interfaces to transport-specific capabilities (such as the broadcast address and reserved port facilities of TCP and UDP) |
The first argument of each routine points to a netconfig structure that describes a transport. The routine uses the array of directory-lookup library paths in the netconfig structure to call each path until the translation succeeds.
The libraries are described in Table 4-2. The routines described in the section, "Using the Name-to-Address Mapping Routines", are defined in the netdir(3N) man page.
The following libraries no longer exist in the Solaris 2 environment: tcpip.so, switch.so, and nis.so. For more information on this change, see the nsswitch.conf(4) man page and the NOTES section of the gethostbyname(3N) man page.
|
Library |
Transport Family |
Description |
|---|---|---|
|
inet |
For networks of the protocol family inet, its name-to-address mapping is provided by the name service switch based on the entries for hosts and services in the file nsswitch.conf. For networks of other families, the "-" indicates a non-functional name-to-address mapping. |
|
|
loopback |
Contains the name-to-address mapping routines of any protocol that accepts strings as addresses, such as the loopback transports. |
Name-to-address translation files for the library are created and maintained by the system administrator. The straddr.so files are /etc/net/transport-name/hosts and /etc/net/transport-name/services. transport-name is the local name of the transport that accepts string addresses (specified in the network ID field of the /etc/netconfig file). For example, the host file for ticlts would be /etc/net/ticlts/hosts, and the service file for ticlts would be /etc/net/ticlts/services.
Even though most string addresses do not distinguish between host and service, separating the string into a host part and a service part is consistent with other transports. The /etc/net/transport-name/hosts file contains a text string that is assumed to be the host address, followed by the host name. For example:
joyluckaddr joyluck carpediemaddr carpediem thehopaddr thehop pongoaddr pongo |
For loopback transports, it makes no sense to list other hosts because the service cannot go outside the containing host.
The /etc/net/transport-name/services file contains service names followed by strings identifying the service address. For example:
rpcbind rpc listen serve |
The routines create the full-string address by concatenating the host address, a period (.), and the service address. For example, the address of the listen service on pongo is pongoaddr.serve.
When an application requests the address of a service on a particular host on a transport that uses this library, the host name must be in /etc/net/transport/hosts, and the service name must be in /etc/net/transport/services. If either is missing, the name-to-address translation fails.
This section provides an overview of what routines are available to use. The routines return or convert the network names to their respective network addresses. Note that netdir_getbyname(), netdir_getbyaddr(), and taddr2uaddr() return pointers to data that must be freed by calls to netdir_free().
int netdir_getbyname(struct netconfig *nconf, struct nd_hostserv *service, struct nd_addrlist **addrs); |
netdir_getbyname() maps the host and service name specified in service to a set of addresses consistent with the transport identified in nconf. The nd_hostserv and nd_addrlist structures are defined in the netdir(3N) man page. A pointer to the addresses is returned in addrs.
To find all addresses of a host and service (on all available transports), call netdir_getbyname() with each netconfig structure returned by either getnetpath() or getnetconfig().
int netdir_getbyaddr(struct netconfig *nconf, struct nd_hostservlist **service, struct netbuf *netaddr); |
netdir_getbyaddr() maps addresses into host and service names. The function is called with an address in netaddr and returns a list of host-name and service-name pairs in service. The nd_hostservlist structure is defined in netdir(3N).
void netdir_free(void *ptr, int struct_type); |
The netdir_free() routine frees structures allocated by the name-to-address translation routines. The parameters can take the values shown in Table 4-3.
Table 4-3 netdir_free() Routines|
struct_type |
ptr |
|---|---|
|
ND_HOSTSERV |
Pointer to an nd_hostserv structure |
|
ND_HOSTSERVLIST |
Pointer to an nd_hostservlist structure |
|
ND_ADDR |
Pointer to a netbuf structure |
|
ND_ADDRLIST |
Pointer to an nd_addrlist structure |
char *taddr2uaddr(struct netconfig *nconf, struct netbuf *addr); |
taddr2uaddr() translates the address pointed to by addr and returns a transport-independent character representation of the address ("universal address"). nconf specifies the transport for which the address is valid. The universal address can be freed by free().
struct netbuf *uaddr2taddr(struct netconfig *nconf, char *uaddr); |
The "universal address" pointed to by uaddr is translated into a netbuf structure; nconf specifies the transport for which the address is valid.
int netdir_options(struct netconfig *nconf, int option, int fd, char *point_to_args); |
netdir_options() interfaces to transport-specific capabilities (such as the broadcast address and reserved port facilities of TCP and UDP). nconf specifies a transport. option specifies the transport-specific action to take. fd might or might not be used depending upon the value of option. The fourth argument points to operation-specific data.
Table 4-4 shows the values used for option:
Table 4-4 Values for netdir_options|
Option |
Description |
|---|---|
|
ND_SET_BROADCAST |
Sets the transport for broadcast (if the transport supports broadcast) |
|
ND_SET_RESERVEDPORT |
Lets the application bind to a reserved port (if allowed by the transport) |
|
ND_CHECK_RESERVEDPORT |
Verifies that an address corresponds to a reserved port (if the transport supports reserved ports) |
|
ND_MERGEADDR |
Transforms a locally meaningful address into an address to which client hosts can connect |
netdir_perror() displays the message stating why one of the name-to-address mapping routines failed on stderr.
void netdir_perror(char *s); |
netdir_sperror() returns a string containing the error message stating why one of the name-to-address mapping routines failed.
char *netdir_sperror(void); |
Example 4-7 shows network selection and name-to-address mapping.
#include <netconfig.h>
#include <netdir.h>
#include <sys/tiuser.h>
struct nd_hostserv nd_hostserv; /* host and service information */
struct nd_addrlist *nd_addrlistp; /* addresses for the service */
struct netbuf *netbufp; /* the address of the service */
struct netconfig *nconf; /* transport information*/
int i; /* the number of addresses */
char *uaddr; /* service universal address */
void *handlep; /* a handle into network selection */
/*
* Set the host structure to reference the "date"
* service on host "gandalf"
*/
nd_hostserv.h_host = "gandalf";
nd_hostserv.h_serv = "date";
/*
* Initialize the network selection mechanism.
*/
if ((handlep = setnetpath()) == (void *)NULL) {
nc_perror(argv[0]);
exit(1);
}
/*
* Loop through the transport providers.
*/
while ((nconf = getnetpath(handlep)) != (struct netconfig *)NULL)
{
/*
* Print out the information associated with the
* transport provider described in the "netconfig"
* structure.
*/
printf("Transport provider name: %s\n", nconf->nc_netid);
printf("Transport protocol family: %s\n", nconf->nc_protofmly);
printf("The transport device file: %s\n", nconf->nc_device);
printf("Transport provider semantics: ");
switch (nconf->nc_semantics) {
case NC_TPI_COTS:
printf("virtual circuit\n");
break;
case NC_TPI_COTS_ORD:
printf("virtual circuit with orderly release\n");
break;
case NC_TPI_CLTS:
printf("datagram\n");
break;
}
/*
* Get the address for service "date" on the host
* named "gandalf" over the transport provider
* specified in the netconfig structure.
*/
if (netdir_getbyname(nconf, &nd_hostserv, &nd_addrlistp) != ND_OK) {
printf("Cannot determine address for service\n");
netdir_perror(argv[0]);
continue;
}
printf("<%d> addresses of date service on gandalf:\n",
nd_addrlistp->n_cnt);
/*
* Print out all addresses for service "date" on
* host "gandalf" on current transport provider.
*/
netbufp = nd_addrlistp->n_addrs;
for (i = 0; i < nd_addrlistp->n_cnt; i++, netbufp++) {
uaddr = taddr2uaddr(nconf,netbufp);
printf("%s\n",uaddr);
free(uaddr);
}
netdir_free( nd_addrlistp, ND_ADDRLIST );
}
endnetconfig(handlep);
|