ROUTE(4) | FreeBSD Kernel Interfaces Manual | 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);
解説
FreeBSD は、いくつかのパケットルーティング機能を提供します。カーネルは、ルーティング情報データベースを保守します。それは、パケットを送信するときに適切なネットワークインタフェースを選択するのに使用されます。ユーザプロセス (または場合により複数の協同プロセス) は、特別な種類のソケット上にメッセージを送信することによって、このデータベースを保守します。これは、初期のリリースで使用されていた固定サイズの ioctl(2) に取って代わります。ルーティングテーブルの変更は、スーパユーザによってのみ実行することができます。
オペレーティングシステムは、リダイレクトの受け取りか、または要求に対して適切なルートを見つけることを失敗するような、外部のイベントに応答するルーティングメッセージを自然に発信することができます。メッセージタイプは、より詳細に以下に説明されています。
ルーティングデータベースエントリは、次の 2 つの特色の形式があります: 特定のホストのため、または、 (ビットマスクとマスクされた値によって指定されるような) 一般的なサブネットワークですべてのホストのためにです。ワイルドカードかデフォルトルートの効果は、すべて 0 のマスクを使用することによって達成することができます。そして、それらは、階層的なルートになっているかもしれません。
システムが起動されて、アドレスがネットワークインタフェースに割り当てられるとき、各プロトコルファミリは、トラフィックの準備ができるとき、各インタフェースのためにルーティングテーブルエントリをインストールします。通常、プロトコルは、宛先ホストかネットワークへ“直接”接続するような各インタフェースを通してルートを指定します。ルートが直接であるなら、プロトコルファミリのトランスポートレイヤは、通常、パケット内で指定された同じホストへ送信されるパケットを要求します。そうでなければ、ルーティングエントリにリストされたゲートウェイへのパケットにアドレスを指定するようにインタフェースが要求されます (すなわち、パケットは、転送されます)。
パケットをルーティングするとき、カーネルは、宛先に一致する最も明確なルートを見つけようと試みます。 (2 つの異なったマスクとマスクされた値 (value-under-the-mask) のペアがあるなら、より多くのビットがマスクにあるもが特定されます。ホストへのルートは、宛先中のビットがあるのと同数のマスクが供給されると見なされます)。エントリが見つけられないなら、宛先が到達不能であると宣言され、以下に説明されるルーティング制御ソケット上でいくらかのリスナがいればルーティングミス (routing-miss) メッセージが生成されます。
ワイルドカードルーティングエントリは、0 の宛先アドレス値とすべて 0 のマスクで指定されます。ワイルドカードルートは、システムが宛先に一致する他のルートを見つけるのに失敗したときに使用されます。ワイルドカードルートとルーティングリダイレクトの組み合わせは、ルーティングトラフィックを削減できる仕組みを提供することができます。
上記の概要で示されるソケットコールを使用してルーティング制御メッセージを渡すためにチャネルをオープンします。
family パラメータは、すべてのアドレスファミリのためのルーティング情報を提供する AF_UNSPEC であるかもしれません。または、どのアドレスファミリが望まれているかを指定することによって特定のアドレスファミリに制限することができます。 1 つのシステムあたり 1 つ以上のルーティングソケットをオープンすることができます。
メッセージは、ヘッダとそれに続く小数の sockaddrs (現在、特に ISO の場合における可変長) によって形成されます。そしてそれは、位置によって解釈され、 sockaddr の新しい length (長さ) エントリによって区切られます。 4 つのアドレスがあるメッセージの例は、 ISO リダイレクトになるかもしれません: 宛先、ネットマスク、ゲートウェイ、およびリダイレクトの作者です。どのアドレスが存在しているかの解釈は、ヘッダ内のビットマスクで与えられます。順序は、ベクタ内の最下位ビットから最上位ビットです。
カーネルに送られたどんなメッセージも返され、すべての関係があるリスナにコピーを送ります。カーネルは、送信者のプロセス ID を提供し、送信者は、未解決のメッセージを区別するために付加シーケンスフィールドを使用することができます。しかしながら、カーネルバッファが使い尽くされるとき、メッセージの返信は、失われるかもしれません。
カーネルは、特定のメッセージを拒絶することができ、 rtm_errno フィールドに記入することによってこれを示します。ルーティングコードは、存在するエントリをコピーするように要求されるなら EEXIST を返し、実在しないエントリを削除するように要求されるなら ESRCH を返し、新しいルートを導入するために利用可能なリソースが不足しているならば、 ENOBUFS を返します。現在の実装では、すべてのルーティングプロセスは、ローカルに動作し、 rtm_errno のための値は、ルーティング返信メッセージが失われても、通常の errno メカニズムを通して利用可能です。
プロセスは、 SOL_SOCKET レベルにおいて SO_USELOOPBACK オプションがオフにされることを示す setsockopt(2) 呼び出しを発行することによって、それ自身のメッセージへの返信を読み込むコストを避けることができます。プロセスは、さらなる入力のために shutdown(2) システムコールを行なうことによって、ルーティングソケットからのすべてのメッセージを無視することができます。
ルートが削除されるとき、それが使用中であるなら、ルーティングエントリは、ダウン (停止中) とマークされルーティングテーブルから削除されます。しかし、それに関連しているリソースは、すべての参照が解除されるまで再利用されません。ユーザプロセスは、 RTM_GET メッセージを使用するか、 sysctl(3) を呼び出すことによって、特定の宛先へのルーティングエントリに関する情報を取得できます。
メッセージは、次のものを含んでいます:
#define RTM_ADD 0x1 /* ルート追加 */ #define RTM_DELETE 0x2 /* ルート削除 */ #define RTM_CHANGE 0x3 /* メトリックかフラグかゲートウェイを変更 */ #define RTM_GET 0x4 /* 情報報告 */ #define RTM_LOSING 0x5 /* カーネル容疑分割 */ #define RTM_REDIRECT 0x6 /* 異なったルートを使用するように伝える */ #define RTM_MISS 0x7 /* このアドレスで検索失敗 */ #define RTM_LOCK 0x8 /* 指定されたメトリックを修正 */ #define RTM_OLDADD 0x9 /* SIOCADDRT によって引き起こされる */ #define RTM_OLDDEL 0xa /* SIOCDELRT によって引き起こされる */ #define RTM_RESOLVE 0xb /* 宛先を LL アドレスに解決要求 - 未使用 */ #define RTM_NEWADDR 0xc /* iface に追加されるアドレス */ #define RTM_DELADDR 0xd /* iface から削除されるアドレス */ #define RTM_IFINFO 0xe /* iface を up/down するその他 */ #define RTM_NEWMADDR 0xf /* if に追加される mcast グループ メンバシップ */ #define RTM_DELMADDR 0x10 /* 削除される mcast グループメンバシップ */ #define RTM_IFANNOUNCE 0x11 /* iface 到着/出発 */ #define RTM_IEEE80211 0x12 /* IEEE80211 無線イベント */
メッセージヘッダは、次の 1 つから成ります:
struct rt_msghdr { u_short rtm_msglen; /* 理解されないメッセージをスキップ するため */ u_char rtm_version; /* 将来のバイナリ互換性 */ u_char rtm_type; /* メッセージタイプ */ u_short rtm_index; /* 関連する ifp のインデックス */ int rtm_flags; /* フラグ、incl. kern & message, 例えば DONE */ int rtm_addrs; /* メッセージ中のビットマスク識別 sockaddrs */ pid_t rtm_pid; /* 送信者識別 */ int rtm_seq; /* 送信者に対して動作を識別 */ int rtm_errno; /* 何故失敗したか */ int rtm_fmask; /* RTM_CHANGE メッセージで使用される ビットマスク */ u_long rtm_inits; /* どのメトリックを初期化しているか */ struct rt_metrics rtm_rmx; /* メトリック自体 */ }; struct if_msghdr { u_short ifm_msglen; /* 理解されないメッセージをスキップ するため */ u_char ifm_version; /* 将来のバイナリ互換性 */ u_char ifm_type; /* メッセージタイプ */ int ifm_addrs; /* rtm_addrs に似たもの */ int ifm_flags; /* if_flags の値 */ u_short ifm_index; /* 関連する ifp のインデックス */ struct if_data ifm_data; /* if に関する統計と他のデータ */ }; struct ifa_msghdr { u_short ifam_msglen; /* 理解されないメッセージをスキップ するため */ u_char ifam_version; /* 将来のバイナリ互換性 */ u_char ifam_type; /* メッセージタイプ */ int ifam_addrs; /* rtm_addrs に似たもの */ int ifam_flags; /* ifa_flags の値 */ u_short ifam_index; /* 関連する ifp のインデックス */ int ifam_metric; /* ifa_metric の値 */ }; struct ifma_msghdr { u_short ifmam_msglen; /* 理解されないメッセージをスキップ するため */ u_char ifmam_version; /* 将来のバイナリ互換性 */ u_char ifmam_type; /* メッセージタイプ */ int ifmam_addrs; /* rtm_addrs に似たもの */ int ifmam_flags; /* ifa_flags の値 */ u_short ifmam_index; /* 関連する ifp のインデックス */ }; struct if_announcemsghdr { u_short ifan_msglen; /* 理解されないメッセージをスキップ するため */ u_char ifan_version; /* 将来のバイナリ互換性 */ u_char ifan_type; /* メッセージタイプ */ u_short ifan_index; /* 関連する ifp のインデックス */ char ifan_name[IFNAMSIZ]; /* 名前があれば、例えば "en0" */ u_short ifan_what; /* どんなタイプのナウンス */ };
RTM_IFINFO メッセージは、 if_msghdr ヘッダを使用し、 RTM_NEWADDR と RTM_DELADDR メッセージは、 ifa_msghdr ヘッダを使用し、 RTM_NEWMADDR と RTM_DELMADDR メッセージは、 ifma_msghdr ヘッダを使用し、 RTM_IFANNOUNCE メッセージは、 if_announcemsghdr ヘッダを使用し、そして、他のすべてのメッセージは、 rt_msghdr ヘッダを使用します。
“ struct rt_metrics
”とフラグビットは、 rtentry(9) で定義されています。
rmx_locks と rtm_inits におけるメトリック値の指定子は、次の通りです:
#define RTV_MTU 0x1 /* _mtu の初期化またはロック */ #define RTV_HOPCOUNT 0x2 /* _hopcount の初期化またはロック */ #define RTV_EXPIRE 0x4 /* _expire の初期化またはロック */ #define RTV_RPIPE 0x8 /* _recvpipe の初期化またはロック */ #define RTV_SPIPE 0x10 /* _sendpipe の初期化またはロック */ #define RTV_SSTHRESH 0x20 /* _ssthresh の初期化またはロック */ #define RTV_RTT 0x40 /* _rtt の初期化またはロック */ #define RTV_RTTVAR 0x80 /* _rttvar の初期化またはロック */ #define RTV_WEIGHT 0x100 /* _weight を init または lock */
メッセージに提示されたアドレスの指定子は、次の通りです:
#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 */ #define RTA_BRD 0x80 /* NEWADDR のための、ブロードキャストまたは p-p 宛先アドレス */
歴史
PF_ROUTE プロトコルファミリは、 4.3BSD-Reno ではじめて登場しました。November 4, 2004 | FreeBSD |