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

第 4 章 トランスポート選択と名前からアドレスへのマッピング

この章では、トランスポートの選択およびネットワークアドレスの解決方法を示します。また、アプリケーションが使用できる通信プロトコルを指定できるようにするインタフェースについて説明します。さらに、名前をネットワークアドレスに直接マッピングする追加機能についても取り上げます。


注 -

この章で使用するネットワークおよびトランスポートという用語は、OSI 参照モデルのトランスポート層に準拠するプログラム可能なインタフェースを指す場合、同じ意味です。ネットワークという用語は、何らかの電子媒体を介して接続できるコンピュータの物理的な集まりを指す場合にも使用されます。


マルチスレッドに対して安全なトランスポート選択

この章で取り上げるインタフェースは、マルチスレッドに対して安全です。このことは、トランスポートの選択機能呼び出しを行うアプリケーションを、マルチスレッド対応アプリケーション内で自由に使用できることを意味します。ただし、アプリケーションの多重度は、特定されていません。

トランスポート選択

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

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

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

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

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

環境変数 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);

名前からアドレスへのマッピング

名前からアドレスへのマッピングによって、使用されるトランスポートに関係なく、アプリケーションは指定のホスト上で実行されるサービスのアドレスを取得できます。名前からアドレスへのマッピングでは、次の関数を使用します。

netdir_getbyname(3NSL) ホスト名およびサービス名を一連のアドレスに対応づける
netdir_getbyaddr(3NSL) アドレスを、ホスト名およびサービス名に対応づける
netdir_free(3NSL) 名前からアドレスへの変換ルーチンによって割り当てられた構造体を解放する
taddr2uaddr(3NSL) アドレスを変換し、トランスポートに依存しないアドレスの文字表現を返す
uaddr2taddr(3NSL)汎用アドレスを netbuf 構造体に変換する
netdir_options(3NSL) ブロードキャストアドレス、TCP や UDP の予約ポート機能など、トランスポートに固有の機能へのインタフェースをとる

各ルーチンの最初の引数では、トランスポートを示す netconfig(4) 構造体を指します。これらのルーチンは、netconfig(4) 構造体内にあるディレクトリルックアップ用のライブラリパスの配列を使用して、変換が正常終了するまで各パスを呼び出します。

表 4-2 で、ライブラリについて説明します。「名前からアドレスへのマッピングルーチンの使用」に示すルーチンは、netdir(3NSL) のマニュアルページに定義されています。


注 -

tcpip.soswitch.so および nis.so というライブラリは、Solaris 2 環境で廃止されました。この変更の詳細については、nsswitch.conf(4) のマニュアルページおよび gethostbyname(3NSL) マニュアルページの NOTES セクションを参照してください。


表 4-2 名前からアドレスへのマッピングを行うライブラリ

ライブラリ 

トランスポートファミリ 

説明 

-

inet

inet プロトコルファミリを使用するネットワークでは、名前からアドレスへのマッピングは、nsswitch.conf(4) ファイルに定義されている hostsservices の各エントリに基づくネームサービス切り換え機能が行う。inet 以外のファミリを使用するネットワークに「-」を指定すると、名前からアドレスへのマッピング機能が存在しないことを示す

straddr.so

loopback

ループバックトランスポートのように、文字列をアドレスとして受け入れるプロトコルの、名前からアドレスへのマッピングルーチンが含まれている 

straddr.so ライブラリ

straddr.so ライブラリで使用する名前からアドレスへの変換ファイルは、システム管理者が作成し、保守します。straddr.so ファイルには、/etc/net/transport-name/hosts/etc/net/transport-name/services があります。transport-name は、文字列アドレス (/etc/netconfig ファイルの network ID フィールドに指定したもの) を受け入れるトランスポートのローカル名です。たとえば、ticlts のホストファイルは、/etc/net/ticlts/hosts となり、ticlts のサービスファイルは、/etc/net/ticlts/services となります。

たいていの文字列アドレスは、ホストサービスを区別しませんが、文字列をホスト部分とサービス部分とに分けると、他のトランスポートとの間で一貫性が保てます。/etc/net/transport-name/hosts ファイルには、ホストアドレスと見なされるテキスト文字列に続いて、ホスト名を定義します。たとえば、次のように定義します。

joyluckaddr	joyluck
carpediemaddr	carpediem
thehopaddr	thehop
pongoaddr	pongo

ルックアップトランスポートの場合、他のホストを記述することには意味がありません。なぜなら、サービスは、それがインストールされているホスト以外で実行することはできないからです。

/etc/net/transport-name/services には、サービス名に続いて、サービスアドレスを特定する文字列を定義します。たとえば、次のように定義します。


rpcbind	rpc
listen	serve

ルーチンは、ホストアドレス、ピリオド (.)、およびサービスアドレスを結合して完全な文字列アドレスを作成します。たとえば、pongo での listen サービスのアドレスは、pongoaddr.serve になります。

このライブラリを使用するトランスポート上で、アプリケーションが特定のホスト上のサービスアドレスを要求する場合は、/etc/net/transport/hosts にホスト名が、/etc/net/transport/services にサービス名がそれぞれ定義されていなければなりません。どちらか一方でも欠けると、名前からアドレスへの変換が失敗します。

名前からアドレスへのマッピングルーチンの使用

この節では、どのようなルーチンが使用できるかについて簡単に説明します。ルーチンは、ネットワーク名を返すか、またはネットワーク名を対応するネットワークアドレスに変換します。なお、netdir_getbyname(3NSL)netdir_getbyaddr(3NSL)taddr2uaddr(3NSL) は、データへのポインタを返しますが、これらのポインタは、netdir_free(3NSL) 呼び出しで解放する必要があります。

	int netdir_getbyname(struct netconfig *nconf, 
			struct nd_hostserv *service, struct nd_addrlist **addrs);

netdir_getbyname(3NSL) は、service に指定されたホスト名とサービス名を、nconf で指定されたトランスポートに一致したアドレスセットに対応づけます。nd_hostservnd_addrlist の各構造体は、netdir(3NSL) のマニュアルページに定義されています。アドレスへのポインタは、addrs に返されます。

使用可能なすべてのトランスポート上で、ホストおよびサービスのすべてのアドレスを取得するには、getnetpath(3NSL) または getnetconfig(3NSL) のいずれかで返される各 netconfig(4) 構造体を使用して netdir_getbyname(3NSL) を呼び出します。

int netdir_getbyaddr(struct netconfig *nconf,
		struct nd_hostservlist **service, struct netbuf *netaddr);

netdir_getbyaddr(3NSL) は、アドレスをホスト名とサービス名に対応付けます。この関数は、netaddr に指定したアドレスを使用して呼び出され、ホスト名とサービス名のペアのリストを service に返します。nd_hostservlist 構造体は、netdir(3NSL) に定義されています。

void netdir_free(void *ptr, int struct_type);

netdir_free(3NSL) ルーチンは、名前からアドレスへの変換ルーチンによって割り当てられた構造体を解放します。表 4-3 に、引数がとる値を示します。

表 4-3 netdir_free(3NSL) ルーチン

struct_type 

ptr 

ND_HOSTSERV

nd_hostserv 構造体へのポインタ

ND_HOSTSERVLIST

nd_hostservlist 構造体へのポインタ

ND_ADDR

netbuf 構造体へのポインタ

ND_ADDRLIST

nd_addrlist 構造体へのポインタ

char *taddr2uaddr(struct netconfig *nconf, struct netbuf *addr);

taddr2uaddr(3NSL) は、addr が指すアドレスを変換し、トランスポートに依存しない文字列表現 (「汎用アドレス」) を返します。nconf には、アドレスが有効なトランスポートを指定します。汎用アドレスは、free(3C) で解放できます。

struct netbuf *uaddr2taddr(struct netconfig *nconf, char *uaddr);

uaddr が指す「汎用アドレス」は、netbuf 構造体に変換されます。nconf には、アドレスが有効なトランスポートを指定します。

int netdir_options(struct netconfig *nconf,
		 int option, int fd,
		 char *point_to_args);

netdir_options(3NSL) は、ブロードキャストアドレス、TCP や UDP の予約ポート機能など、トランスポートに固有の機能とインタフェースをとります。nconf にはトランスポートを、option にはトランスポート固有の動作をそれぞれ指定します。fd は、option の値次第で指定してもしなくてもかまいません。4 つ目の引数は、操作固有のデータを指します。

表 4-4 に、option に指定できる値を示します。

表 4-4 netdir_options に指定できる値

オプション 

説明 

ND_SET_BROADCAST

ブロードキャスト用のトランスポートを設定する (トランスポートがブロードキャスト機能をサポートしている場合) 

ND_SET_RESERVEDPORT

アプリケーションが予約ポートにバインドできるようにする (トランスポートがそのようなバインドを許可している場合) 

ND_CHECK_RESERVEDPORT

アドレスが予約ポートに対応しているかどうかを検証する (トランスポートが予約ポートをサポートしている場合) 

ND_MERGEADDR

ローカルに意味のあるアドレスを、クライアントホストが接続できるアドレスに変換する 

netdir_perror(3NSL) は、名前からアドレスへのマッピングルーチンの 1 つが失敗した場合に、その理由を示すメッセージを stderr に出力します。

void netdir_perror(char *s);

netdir_sperror(3NSL) は、名前からアドレスへのマッピングルーチンの 1 つが失敗した場合に、その理由を示すエラーメッセージが含まれた文字列を返します。

char *netdir_sperror(void);

例 4-7 に、ネットワーク選択および名前からアドレスへのマッピングを示します。


例 4-7 ネットワーク選択および名前からアドレスへのマッピング

#include <netconfig.h>
#include <netdir.h>
#include <sys/tiuser.h>

struct nd_hostserv nd_hostserv;   /* ホストとサービスの情報 */
struct nd_addrlist *nd_addrlistp; /* サービスのアドレスリスト */
struct netbuf *netbufp;           /* サービスのアドレス */
struct netconfig *nconf;          /* トランスポート情報 */
int i;                            /* アドレスの数 */
char *uaddr;                      /* サービスの汎用アドレス */
void *handlep;                    /* ネットワーク選択用のハンドル */
/*
 * 「gandalf」というホスト上の「日付」サービスを参照する
 * ホスト構造体の設定
 */
nd_hostserv.h_host = "gandalf";
nd_hostserv.h_serv = "date";
/*
 * ネットワーク選択機構の初期化
 */
if ((handlep = setnetpath()) == (void *)NULL) {
   nc_perror(argv[0]);
   exit(1);
}
/*
 * トランスポートプロバイダ間のループ
 */
while ((nconf = getnetpath(handlep)) != (struct netconfig *)NULL)
{
   /*
    * netconfig 構造体で指定したトランスポートプロバイダに
    * 関連付けられた情報を出力する。
    */
   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;
   }
   /*
    * netconfig 構造体で指定したトランスポートプロバイダ
    * を経由して、「gandalf」というホスト上の「日付」
    * サービスのアドレスの取得
    */
   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);
   /*
    * 現在のトランスポートプロバイダ上で、「gandalf」
    * というホスト上にある「日付」サービスの全アドレスの出力
    */
   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);