スポンサーリンク

ROUTE(4) FreeBSD カーネルインタフェースマニュアル ROUTE(4)

名称

route − カーネルパケット転送データベース

書式

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/route.h>

int

socket(PF_ROUTE, SOCK_RAW, int family);

解説

UNIX はパケットルーティング装置を提供します。カーネルはルーティング情報 データベースを管理しています。そして、ルーティング情報データベースは、パ ケットを転送する際に適当なネットワークインタフェースを選択するのに使用さ れます。

ユーザプロセス (あるいは複数の共同プロセス) は、特殊なソケットを通して メッセージを送ることによってこのデータベースを管理します。これは、初期の リリースで使われていた固定サイズの ioctl(2) での管理にとって代わったもの です。ルーティングテーブルの変更はスーパユーザによってのみ行なわれます。

オペレーティングシステムは、リダイレクトを受け取ったとか、要求に対して適 当な経路を設定することに失敗したというような外部イベントに対する反応とし て、自発的にルーティングメッセージを出すかもしれません。このメッセージタ イプの詳細は以下に記述されています。

ルーティングデータベースのエントリは 2 種類からなります。 1 つは特定のホ スト向け、もう 1 つは (ビットマスクとマスク後に残る値によって指定される) 一般的なサブネットワーク内の全てのホスト向けです。ワイルドカードやデフォ ルト経路の効果は、すべてのビットが 0 のマスクを使用することによって生じま す。それは階層的な経路になっているかもしれません。

システムが起動してネットワークインタフェースにアドレスが割り当てられる 時、各プロトコルファミリは、トラフィックに対して準備ができた時点で各イン タフェースにルーティングテーブルエントリをインストールします。通常プロト コルは、各インタフェースを通して宛先となるホストまたはネットワークへ ‘‘直 接’’ 接続するものとして経路を指定します。もし経路が直接であれば、パケット 内で指定されているのと同じホストへそれが送られるようプロトコルファミリの トランスポート層が要求します。そうでなければ、ルーティングエントリにリス トされたゲートウェイに該当パケットを送るようにインタフェースが要求されま す (即ち、パケットは転送されます)。

パケットがルーティングされる時、カーネルは宛先に最も明確に一致する経路を 見付けようと試みます。 (もし 2 つの異なるマスクがあって、マスクをかけた後 の値が一致しているペアがあるなら、より明確に一致するというのはマスクの中 のビットがより多く立っている方です。ホストへの経路は、宛先中のビットが最 も多く 1 になっているマスクを持っているとみなされます)。エントリが見つか らなければ、宛先には到達不能であると宣言され、以下で記述される経路制御ソ ケット上でメッセージ待ちをしているリスナがいれば routing−miss メッセージ が生成されます。

ワイルドカードルーティングエントリは、宛先アドレスが 0 でマスクもすべて 0 で指定されます。ワイルドカード経路は、システムが宛先に一致する経路を見つ けるのに失敗した時に使用されます。ワイルドカード経路とルーティングリダイ レクトとを組み合わせて使用すると、ルーティングにかかるトラフィックを合理 的に軽減できる機構を提供できます。

上の書式で示されるソケットコールを使って経路制御メッセージをやりとりする とめのチャネルをオープンします。

family パラメータは、すべてのアドレスファミリについての経路情報を提供する AF_UNSPEC をとることができます。あるいは、どのアドレスファミリを希望する か指定することによって特定のアドレスファミリだけに限定することも出来ま す。 1 つのシステムで 1 つ以上のルーティングソケットをオープンすることが 出来ます。

メッセージはヘッダとそれに続くいくつかの sockaddr (特に ISO の場合、可変 長) によって構成され、位置によって解釈され、 sockaddr の新しい length エ ントリによって区切られます。例えば、4 つのアドレスをもったメッセージは ISO リダイレクトかもしれません。つまり宛先、ネットマスク、ゲートウェイ、 リダイレクトの作者です。どのアドレスが表されているかの解釈はヘッダ内の ビットマスクで与えられます。順序は、vector 内の最下位ビットから最上位ビッ トへの順になります。

カーネルに送られるメッセージはすべて返され、メッセージ待ちをしているすべ てのリスナにはそのコピーが送られます。カーネルはメッセージを送るプロセス のプロセス ID を提供します。そして、メッセージを送るプロセスは、未解決の メッセージ同士を区別するための付加シーケンスフィールドを用いるかもしれま せん。しかし、カーネルバッファが一杯であるとメッセージの返答は失われるか もしれません。

カーネルは特定のメッセージを拒否し、 rtm_errno フィールドを埋めることに よってそれを示します。ルーティングコードは、もしすでに存在するエントリを 複写しようとすると EEXIST を、存在しないエントリを削除しようとすると ESRCH を、新しい経路を導入するために必要な資源が足りない場合は ENOBUFS を 返します。現在の実装では、すべてのルーティングプロセスはローカルで動作し ているので、ルーティング返答メッセージが失われたとしても rtm_errno の値 は、通常の errno 機構から入手可能です。

プロセスは、 SOL_SOCKET レベルでの SO_USELOOPBACK オプションをオフにする ことを示す setsockopt(2) コールを発行することで、自分自身のメッセージに対 する返答を読む負荷を回避することができます。プロセスは更に shutdown(2) シ ステムコールを行なうことによってルーティングソケットからのすべてのメッ セージを無視することができます。

もし経路が使用中に削除されると、そのルーティングエントリにはダウンとマー クされ、経路表から除かれます。しかしそれに関連づけられた資源は、経路への 参照がすべて解放されるまで返還されません。ユーザプロセスは、 RTM_GET メッ セージを使うか、 /dev/kmem デバイスを読むか、あるいは getkerninfo(2) シス テムコールを発行することによって特定の宛先へのルーティングエントリに関す る情報を取得することができます。

メッセージは次のものを含んでいます:

#define

RTM_ADD

0x1 /* 経路追加 */

#define

RTM_DELETE

0x2 /* 経路削除 */

#define

RTM_CHANGE

0x3 /* メトリックやフラグやゲートウェイを変更 */

#define

RTM_GET

0x4 /* 情報報告 */

#define

RTM_LOOSING

0x5 /* カーネルは partitioning を疑っている */

#define

RTM_REDIRECT

0x6 /* 別の経路を使うように言っている */

#define

RTM_MISS

0x7 /* アドレス照合に失敗した */

#define

RTM_RESOLVE

0xb /* 宛先を LL addr に解決する要求 */

1 つのメッセージヘッダは以下から成ります:

struct rt_msghdr {
    u_short rmt_msglen;  /* 分からないメッセージをスキップするため */
    u_char  rtm_version; /* 将来のバイナリ互換性 */
    u_char  rtm_type;    /* メッセージタイプ */
    u_short rmt_index;   /* 関連のある ifp のインデックス */
    int     rtm_flags;   /* フラグ、incl kern & message, 例えば DONE */
    int     rtm_addrs;   /* msg 中の sockaddr を識別するビットマスク */
    pid_t   rmt_pid;     /* 送信者を識別する */
    int     rtm_seq;     /* 送信者に対して動作を識別する */
    int     rtm_errno;   /* 何故失敗したか */
    int     rtm_use;     /* rtentry から */
    u_long  rtm_inits;   /* どの値を初期化するか */

struct rt_metrics rtm_rmx;

/* メトリック自身 */

};

ここで ‘‘struct rt_metrics’’ およびフラグビットは rtentry(9) で定義されて います。

rms_locks と rms_inits のメトリック値の指定子は次の通りです:

#define RTV_SSTHRESH  0x1    /* _ssthresh の初期化あるいはロック */

#define

RTV_RPIPE 0x2 /* _recvpipe の初期化あるいはロック */

#define

RTV_SPIPE 0x4 /* _sendpipe の初期化あるいはロック */

#define

RTV_HOPCOUNT 0x8 /* _hopcount の初期化あるいはロック */

#define

RTV_RTT 0x10 /* _rtt の初期化あるいはロック */

#define

RTV_RTTVAR 0x20 /* _rttvar の初期化あるいはロック */

#define

RTV_MTU 0x40 /* _mtu の初期化あるいはロック */

メッセージ中でどのアドレスが渡されたかの指定子は次の通りです:

#define RTA_DST       0x1    /* 宛先 sockaddr が渡された */
#define RTA_GATEWAY   0x2    /* ゲートウェイ sockaddr が渡された */
#define RTA_NETMASK   0x4    /* ネットマスク sockaddr が渡された */
#define RTA_GENMASK   0x8    /* クローニング sockaddr が渡された */
#define RTA_IFP       0x10   /* インタフェース名 sockaddr が渡された */
#define RTA_IFA       0x20   /* インタフェースアドレス sockaddr が渡された */
#define RTA_AUTHOR    0x40   /* リダイレクトの作者の sockaddr */

関連項目

route(8), rtentry(9)

歴史

PF_ROUTE プロトコルファミリは 4.3BSD−Reno で最初に現れました。

FreeBSD 10.0 October 8, 1996 FreeBSD 10.0

スポンサーリンク