ネットワークインタフェース

トランスポート選択

分散アプリケーションを各種のプロトコルに移植可能にするには、分散アプリケーションでトランスポートサービスの標準インタフェースを使用する必要があります。トランスポート選択サービスが提供するインタフェースを使用すると、アプリケーションは、使用するプロトコルを選択できます。これによって、アプリケーションは、「プロトコル」と「媒体」に依存しなくなります。

トランスポート選択機能を使用すると、クライアントアプリケーションは、サーバーとの通信を確立するまでに、どのトランスポートが使用できるかを簡単に試すことができます。一方、サーバーアプリケーションは、複数のトランスポートに関する要求を受け入れ、複数のプロトコルを経由して通信を行うことができます。どのトランスポートが使用できるかは、ローカルなデフォルトシーケンスで指定された順序、またはユーザーが指定した順序で試すことができます。

使用可能なトランスポートのうち、どれを選択するかを決定するのは、アプリケーションの役割です。トランスポート選択機構を使用すると、選択が統一的な方法で簡単に行えます。

トランスポート選択のしくみ

トランスポートの選択は、次に基づいて行われます。

環境変数 NETPATH は、ユーザーが設定します。この環境変数は、トランスポート識別子を順番に指定したリストと同じです。トランスポート識別子は、netconfig network ID フィールドに一致し、netconfig(4) ファイル内のレコードとリンクしています。netconfig(4) ファイルについては、/etc/netconfig ファイル」を参照してください。ネットワーク選択インタフェースは、ネットワーク構成データベースへの一連のアクセスルーチンから構成されます。

ライブラリルーチン一式は、環境変数 NETPATH で指定される /etc/netconfig のエントリにだけアクセスします。

setnetpath(3NSL) NETPATH の検索を初期化する
getnetpath(3NSL) NETPATH の次の要素に対応する netconfig(4) エントリへのポインタを返す
endnetpath(3NSL) 処理の完了時に NETPATH の要素へのデータベースポインタを解放する

これらのルーチンについては、NETPATH を経由した netconfig(4) データへのアクセス」および getnetpath(3NSL) を参照してください。これらのルーチンを使用すると、アプリケーションが使用するトランスポート選択にユーザーが影響を与えることができます。

トランスポート選択へのユーザーの影響を避けるには、netconfig(4) データベースに直接アクセスするルーチンを使用します。これらのルーチンについては、netconfig(4) へのアクセス」および getnetconfig(3NSL) を参照してください。

setnetconfig(3NSL)  データベースの最初のインデックスへのレコードポインタを初期化する
getnetconfig(3NSL) netconfig(4) データベース内の現在のレコードへのポインタを返し、次のレコードを指すようにポインタを 1 だけ増加する
endnetconfig(3NSL)  処理の完了時にデータベースポインタを解放する

次の 2 つのルーチンは、netconfig(4) エントリおよびそれが表すデータ構造体を操作します。これらのルーチンについては、netconfig(4) へのアクセス」を参照してください。

getnetconfigent(3NSL) netid に対応する netconfig 構造体へのポインタを返す
freenetconfigent(3NSL) getnetconfigent(3NSL) で返される構造体を解放する

/etc/netconfig ファイル

netconfig(4) ファイルには、ホスト上のすべてのトランスポートプロトコルが記述されています。表 4-1 で、netconfig(4) ファイルのエントリについて簡単に説明しています。詳細については、netconfig(4) のマニュアルページを参照してください。

表 4-1 netconfig(4) ファイル

エントリ 

説明 

network ID

tcp のようなトランスポート名のローカルな表現。このフィールドに tcpudp のようなよく知られた名前が設定されるとは限らない。また、同じトランスポートについて、2 つのシステムが同じ名前を使用するとも限らない

semantics

特定のトランスポートプロトコルの意味。指定できる意味は次のとおり

  • tpi_clts - コネクションレス

  • tpi_cots - コネクション型

  • tpi_cots_ord - 正常型解放機能を備えたコネクション型

flags

v またはハイフン (-) だけを指定できるが、(-v) という可視フラグだけが定義されている

protocol family

トランスポートプロバイダのプロトコルファミリ名 (たとえば、inet または loopback)

protocol name

トランスポートプロバイダのプロトコル名。たとえば、protocol familyinet の場合、protocal name は、tcpudp または icmp。それ以外の場合は、protocal name の値は、ハイフン (-)

network device

トランスポートプロバイダにアクセスする場合に開く、デバイスファイルの完全パス名 

name-to-address translation libraries

共有オブジェクトの名前。このフィールドには、名前からアドレスへのマッピングルーチンが格納されている共有オブジェクトのファイル名をコンマで区切って指定する。共有オブジェクトは、環境変数 LD_LIBRARY_PATH のパスに格納される。このフィールドに「-」を指定すると、ホストおよびサービスに関するネームサービス切り換えポリシーが使用されることを意味する

例 4-1 に、netconfig(4) ファイルのサンプルを示します。inet トランスポートについては、このサンプルファイルのコメント部分に示すように、netconfig(4) ファイルの使用方法が変更されました。この変更については、「名前からアドレスへのマッピング」も参照してください。


例 4-1 netconfig(4) サンプルファイル

# 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
#

ネットワーク選択ライブラリルーチンは、netconfig エントリへのポインタを返します。例 4-2 に、netconfig 構造体を示します。


例 4-2 netconfig 構造体

struct netconfig {
   char  *nc_netid;                /* ネットワーク識別子 */
   unsigned  int   nc_semantics;   /* プロトコルの意味 */
   unsigned  int   nc_flag;        /* プロトコルのフラグ */
   char *nc_protofmly;             /* ファミリ名 */
   char *nc_proto;                 /* プロトコル固有 */
   char *nc_device;                /* ネットワーク ID に相当するデバイス名 */
   unsigned  int   nc_nlookups;    /* nc_lookups 内のエントリ数 */
   char **nc_lookups;              /* ルックアップライブラリのリスト */
   unsigned  int   nc_unused[8];
};

有効なネットワーク ID は、システム管理者が定義します。システム管理者は、必ず、ネットワーク ID をローカルに一意にしなければなりません。一意でないと、一部のネットワーク選択ルーチンが正しく機能しません。たとえば、udp というネットワーク ID が指定された netconfig エントリが 2 つあると、getnetconfigent ("udp") がどちらのネットワークを使用するかがわかりません。

システム管理者は、netconfig(4) データベース内のエントリの順序も設定します。/etc/netconfig 内のエントリを見つけるルーチンは、ファイルの先頭から順番に走査し、エントリを返します。netconfig(4) ファイル内のトランスポートの記述順序は、ルーチンがトランスポートを検索する際のデフォルト順序になります。ループバックエントリは、ファイルの終わりに設定する必要があります。

netconfig(4) ファイルおよび netconfig 構造体については、netconfig(4) のマニュアルページでさらに詳細に説明しています。

環境変数 NETPATH

アプリケーションは、通常、システム管理者が設定したデフォルトのトランスポート検索パスを使用して、使用可能なトランスポートを検索します。ただし、ユーザーがアプリケーションのトランスポート選択に関与したい場合は、環境変数 NETPATH と、NETPATH を経由した netconfig(4) データへのアクセス」で説明するルーチンとを使用することによって、アプリケーションがインタフェースを変更できます。これらのルーチンは、環境変数 NETPATH に指定されているトランスポートにだけアクセスします。

NETPATH は、PATH 変数と同様に、トランスポート ID をコロンで区切ったリストです。環境変数 NETPATH 内の各トランスポート ID は、netconfig(4) ファイル内のレコードのネットワーク ID フィールドに対応します。NETPATH については、environ(4) のマニュアルページを参照してください。

デフォルトトランスポートセットは、環境変数 NETPATH (次の節で説明する) を経由して netconfig(4) にアクセスするルーチンと、netconfig(4) に直接アクセスするルーチンとで異なります。環境変数 NETPATH を介して netconfig(4) にアクセスするルーチンのデフォルトトランスポートセットは、netconfig(4) ファイルに定義された可視のトランスポートからなります。一方、netconfig(4) に直接アクセスするルーチンのデフォルトトランスポートセットは、netconfig(4) ファイル全体になります。トランスポートが可視になるのは、システム管理者がそのトランスポートの netconfig(4) エントリの flags フィールドに v フラグを設定した場合です。

NETPATH を経由した netconfig(4) データへのアクセス

環境変数 NETPATH を経由して間接的にネットワーク構成データベースにアクセスするルーチンは、3 つあります。この環境変数では、アプリケーションが使用するトランスポート (複数も可) と、使用できるトランスポートを試す順序とを指定します。NETPATH の構成要素は、左から右へと読み込まれます。これらの関数は、次のインタフェースを使用します。

#include <netconfig.h>

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

setnetpath(3NSL) の呼び出しは、NETPATH の検索を初期化します。また、環境変数 NETPATH で指定したエントリが含まれるデータベースへのポインタを返します。このポインタはハンドルと呼ばれ、getnetpath(3NSL) を使用してデータベース内を移動する際に使用します。setnetpath(3NSL) 関数は、getnetpath(3NSL) を最初に呼び出す前に呼び出しておく必要があります。

getnetpath(3NSL) は、最初に呼び出されると、環境変数 NETPATH の最初の構成要素に対応する netconfig(4) ファイル内のエントリへのポインタを返します。以降の getnetpath(3NSL) 呼び出しでは、環境変数 NETPATH の次の構成要素に対応する netconfig(4) ファイル内のエントリへのポインタを返します。NETPATH に構成要素がなくなると、getnetpath(3NSL)NULL を返します。setnetpath(3NSL) を最初に呼び出さずに getnetpath(3NSL) を呼び出すと、エラーが発生します。getnetpath(3NSL) には、setnetpath(3NSL) で返されたポインタを引数に指定する必要があります。

getnetpath(3NSL) は、無効な NETPATH 構成要素を無視するだけで、メッセージを出力しません。無効な NETPATH 構成要素とは、netconfig(4) データベースに対応するエントリがないものです。

環境変数 NETPATH が設定されていない場合、getnetpath(3NSL) は、netconfig(4) データベースのデフォルトトランスポートまたは可視トランスポートの順序が NETPATH に設定されているように振る舞います。

endnetpath(3NSL) は、処理の完了時に呼び出され、環境変数 NETPATH 内の要素へのデータベースポインタを解放します。setnetpath(3NSL) が事前に呼び出されていないと、endnetpath(3NSL) は失敗します。例 4-3 に、setnetpath(3NSL)getnetpath(3NSL)、および endnetpath(3NSL) の各ルーチンを示します。


例 4-3 setnetpath(3NSL)getnetpath(3NSL) および endnetpath(3NSL) の各関数

#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 がトランスポートプロバイダ情報を示す
    */
}
endnetpath(handlep);

getnetpath(3NSL) 経由で取得した netconfig(4) 構造体は、endnetpath(3NSL) の実行後無効になります。構造体内のデータを保持するには、getnetconfigent(nconf->nc_netid) を使用して、それらを新しいデータ構造体にコピーします。

netconfig(4) へのアクセス

/etc/netconfig にアクセスし、netconfig(4) 内のエントリを検索する関数は、3 つあります。これら 3 つのルーチンである setnetconfig(3NSL)getnetconfigent(3NSL) および endnetconfig(3NSL) は、次のインタフェースを使用します。

#include <netconfig.h>

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

setnetconfig(3NSL) 呼び出しは、データベースの最初のインデックスへのレコードポインタを初期化します。setnetconfig(3NSL) は、最初に getnetconfig(3NSL) を使用する前に使用する必要があります。setnetconfig(3NSL) は、getnetconfig(3NSL) ルーチンが使用する一意のハンドル (データベースへのポインタ) を返します。getnetconfig(3NSL) の各呼び出しは、netconfig(4) データベース内の現在のレコードへのポインタを返し、次のレコードを指すようにポインタを 1 だけ増加させます。また、getnetconfig(3NSL)netconfig(4) データベース全体の検索にも使用できます。getnetconfig(3NSL) は、ファイルの終わりに NULL を返します。

処理の完了時にデータベースポインタを解放するには、endnetconfig(3NSL) を使用する必要があります。endnetconfig(3NSL) は、setnetconfig(3NSL) の前に呼び出してはなりません。


例 4-4 setnetconfig(3NSL)getnetconfig(3NSL)、および endnetconfig(3NSL) の各関数

void *handlep;
struct netconfig *nconf;

if ((handlep = setnetconfig()) == (void *)NULL){
   nc_perror(argv[0]);
   exit(1);
}
/*
 * トランスポートプロバイダ情報は、nconf に記載されている。
 * process_transport は、ユーザーが提供するルーチンであり、
 * トランスポート nconf を経由してサーバーへの接続を試みる。
 */
while ((nconf = getnetconfig(handlep)) != (struct netconfig *)NULL){
	   if (process_transport(nconf) == SUCCESS)
      break;
}
endnetconfig(handlep);

getnetconfigent(3NSL) および freenetconfigent(3NSL) の各関数は、次のインタフェースを使用します。

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

getnetconfigent(3NSL) は、netid に対応した netconfig 構造体へのポインタを返します。netid が無効の場合は、NULL を返します。freenetconfigent(3NSL) は、getnetconfigent(3NSL) の前に呼び出してはなりません。

freenetconfigent(3NSL) は、getnetconfigent(3NSL) で返された構造体を解放します。例 4-5 に、getnetconfigent(3NSL)freenetconfigent(3NSL) の各ルーチンを示します。


例 4-5 getnetconfigent(3NSL)freenetconfigent(3NSL) の関数

/* udp がこのホストの netid と仮定する */
struct netconfig *nconf;

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

可視の全 netconfig(4) エントリ間のループ

setnetconfig(3NSL) 呼び出しを使用して、netconfig(4) データベースで可視とマークされたすべてのトランスポート (flags フィールドに v フラグが設定されているもの) 間を移動します。トランスポート選択ルーチンは、netconfig(4) ポインタを返します。

ユーザー定義の netconfig(4) エントリ間のループ

環境変数 NETPATH にコロンで区切ったトランスポート名のリストを設定することによって、ループを制御できます。NETPATH は、次のように設定します。


NETPATH=tcp:udp

ループは、最初に tcp エントリを返し、次に udp エントリを返します。NETPATH が定義されていないと、ループは、netconfig(4) ファイル内に存在するすべての可視エントリを格納順に返します。環境変数 NETPATH を使用すると、クライアント側アプリケーションがサービスに接続しようとする順番をユーザーが定義できるだけでなく、サービスが待機できるトランスポートの数をサーバーの管理者が制限できます。

getnetpath(3NSL)setnetpath(3NSL) を使用して、ネットワークパス変数を取得したり、変更したりします。例 4-6 では、その形式と使用方法を示します。これは、getnetconfig(3NSL)setnetconfig(3NSL) のルーチンに似ています。


例 4-6 可視のトランスポート間のループ

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);