ユーザプロセス (あるいは複数の共同プロセス) は、 特殊なソケットを通してメッセージを送ることによって このデータベースを管理します。 これは、初期のリリースで使われていた固定サイズの ioctl(2) での管理にとって代わったものです。 ルーティングテーブルの変更はスーパユーザによってのみ行なわれます。
オペレーティングシステムは、リダイレクトを受け取ったとか、 要求に対して適当な経路を設定することに失敗したというような 外部イベントに対する反応として、 自発的にルーティングメッセージを出すかもしれません。 このメッセージタイプの詳細は以下に記述されています。
ルーティングデータベースのエントリは 2 種類からなります。 1 つは特定のホスト向け、もう 1 つは (ビットマスクとマスク後に残る値によって指定される) 一般的なサブネットワーク内の全てのホスト向けです。 ワイルドカードやデフォルト経路の効果は、 すべてのビットが 0 のマスクを使用することによって 生じます。 それは階層的な経路になっているかもしれません。
システムが起動してネットワークインタフェースにアドレスが割り当てられる時、 各プロトコルファミリは、トラフィックに対して準備ができた時点で 各インタフェースにルーティングテーブルエントリをインストールします。 通常プロトコルは、各インタフェースを通して 宛先となるホストまたはネットワークへ ``直接'' 接続するものとして経路を指定します。 もし経路が直接であれば、 パケット内で指定されているのと同じホストへそれが送られるよう プロトコルファミリのトランスポート層が要求します。 そうでなければ、 ルーティングエントリにリストされたゲートウェイに 該当パケットを送るようにインタフェースが要求されます (即ち、パケットは転送されます)。
パケットがルーティングされる時、 カーネルは宛先に最も明確に一致する経路を見付けようと試みます。 (もし 2 つの異なるマスクがあって、マスクをかけた後の値が 一致しているペアがあるなら、 より明確に一致するというのはマスクの中のビットがより多く 立っている方です。 ホストへの経路は、宛先中のビットが最も多く 1 になっている マスクを持っているとみなされます)。 エントリが見つからなければ、宛先には到達不能であると宣言され、 以下で記述される経路制御ソケット上でメッセージ待ちをしている リスナがいれば routing-miss メッセージが生成されます。
ワイルドカードルーティングエントリは、宛先アドレスが 0 で マスクもすべて 0 で指定されます。 ワイルドカード経路は、システムが宛先に一致する経路を見つけるのに 失敗した時に使用されます。 ワイルドカード経路とルーティングリダイレクトとを 組み合わせて使用すると、ルーティングにかかるトラフィックを 合理的に軽減できる機構を提供できます。
上の書式で示されるソケットコールを使って経路制御メッセージを やりとりするとめのチャネルをオープンします。
Fa 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 */