最近,あるBlogサイトで,「Linuxカーネルのドキュメントは少ないし,あったとしても古い」とか「一般に告知されずにシステム・コールなどが変更される」といった問題が指摘されているのを目にしました。

 確かに,Linuxはドキュメント整備が不十分で,カーネルについてもそれが言えます。ソース・コードに当たれば良いという部分もあるのですが(私はしばしばそうします),手間がかかりますし,なぜその変更が加えられたかの経緯などは読み取れない場合がほとんどです。最終的にメーリング・リストのアーカイブを調べなければならないことも多く,ドキュメント整備の重要性を痛感します。

 付属文書の整備に直接つながるわけではありませんが,微力なりとも本連載が,カーネルに興味を持たれる方の力になれれば幸いです。

 さて,前回はLinuxのネットワーク機能の概要について解説しました。そこでは,ソケットという仕組みにより,ファイルと共通のインタフェースで,データをネットワーク越しにやり取りできることを示しました。

 ファイル・システムに多様なローカル・ファイル・システムが存在するように,ネットワークにもさまざまなネットワーク・プロトコルが存在します。カーネルは,ext2やiso9660などのローカル・ファイル・システムの違いを吸収し,統一したアクセス手段を提供するのと同じように,ネットワーク・プロトコルの違いを吸収して統一したソケット・インタフェースを提供します。カーネルが各ネットワーク・プロトコルを処理する部分を「プロトコル・スタック」と呼びます。今回は,Linuxで最も利用されているイーサネットとTCP/IPのプロトコル・スタックに関して解説します。

IPアドレスとルーティング

 プロトコル・スタックの解説の前に,TCP/IPネットワークについて復習しておきましょう。

 TCP/IPネットワークを理解する際,最も重要なのは,IPアドレスとルーティングです。

 IPアドレスは通信する相手や通信元を特定する情報で,同一の通信環境ではユニーク(唯一無二)である必要があります。32ビットの数値データですが,通常は人間に分かりやすいように8ビットずつ区切り,それぞれを10進数で「192.168.0.1」のように記述します。

 IPアドレスは無作為に割り当てられているわけではありません。基本的には,各通信機器(ホスト)が接続されているネットワークごとに割り当てられており,同一ネットワーク内のホストにはある決められた範囲のIPアドレスが割り振られます。そのためIPアドレスは,ネットワークを示す「ネットワーク部」と,ホストを示す「ホスト部」に分かれています。

 IPアドレスのどの部分がネットワーク部で,どの部分がホスト部かを示すのが「ネット・マスク」という情報です。ネット・マスクもIPアドレスと同じ 32ビットの数値で,最上位ビットから「1」が連続した部分がネットワーク部,それ以降の「0」が連続した部分がホスト部を示しています。ネット・マスクにより,IPアドレスからネットワークを特定する「ネットワーク・アドレス」を簡単に算出できます。

 例えば,192.168.0.1というIPアドレスと,255.255.255.0というネット・マスクがあった場合,この両者から 192.168.0.0というネットワーク・アドレスが算出できます(図1)。下位8ビットがホスト部になりますので,このネットワークには, 192.168.0.0~192.168.0.255の256個のホストを接続できます。このうち,ホスト部がすべて0のIPアドレス(192.168.10.0)は前述の通りネットワーク・アドレスとして使われます。また,ホスト部がすべて1のIPアドレス(192.168.10.255)は,ネットワーク内の全ホストを示す「ブロードキャスト・アドレス」として使われます。そのため,実際にホストに割り当て可能なIPアドレスは254個になります。

図1●ネットワーク・アドレスの算出
図1●ネットワーク・アドレスの算出
IPアドレスとネット・マスクの論理積がネットワーク・アドレスになります。論理積とはすべての入力が1となる場合にだけ1を,その他の場合は0を出力する論理演算です。

 同一のネットワーク内のホストは,(接続が正常であれば)直接通信できます。しかし,異なるネットワークに接続されているホストには直接通信できません。ネットワーク同士を接続する「ルーター」にデータの転送を依頼する必要があります。転送を依頼されたルーターは,IPアドレスを基に,あて先に近い(と思われる)ルーターに転送を依頼します。こうしてルーターを次々に経由し,データは目的のホストまで届けられます。

 あて先ホストが,同一ネットワークに所属するかどうかは,ネットワーク・アドレスで簡単に調べられます。調査の結果,他のネットワークに所属すると分かった場合は,上述するようにルーターに転送を依頼します。場合によっては,あて先ネットワークによって異なるルーターに転送を依頼することもあります。

 あて先などの情報に応じて通信経路を選択する処理を「ルーティング」と呼びます。各通信機器は,ルーティングを実現するため「ルーティング・テーブル」(経路表)と呼ばれる情報を保持しています。このルーティング・テーブルには,特定のアドレスあてのパケット(データ)をどこのホスト(ルーター)に送信すれば良いかという情報が登録されています。

 Linuxホストも当然ルーティング・テーブルを持っています。登録情報は,routeコマンドで調べられます(図2)。

% route -n
Kernel IP routing table
Destination Gateway       Genmask       Flags Metric Ref Use Iface
192.168.0.0 0.0.0.0       255.255.255.0 U     0      0     0 eth0
192.168.1.0 192.168.0.2   255.255.255.0 UG    0      0     0 eth0
0.0.0.0     192.168.0.254 0.0.0.0       UG    0      0     0 eth0
図2●routeコマンドによるルーティング・テーブルの参照
-nオプションを指定して,ホスト名ではなくIPアドレスで情報を出力させています。

 図2の「Destination」(パケットのあて先)と「Gateway」(パケットを転送するルーター)に注目してください。まず簡単に分かるのが,ネットワーク「192.168.1.0」あてのパケットを,「192.168.0.2」というIPアドレスを持つルーターに転送するよう設定されていることです。

 では,ネットワーク「192.168.0.0」あてのパケットはどうでしょう。この場合,Gatewayが「0.0.0.0」となっています。このIP アドレスは,あて先に使われた場合,自分自身を表します。つまり,これをGatewayに設定するとルーティングは無効になります。無効にするのは,この Linuxホストがネットワーク「192.168.0.0」に接続していて,ネットワーク内のホストと直接通信できるからです。

 Destinationが「0.0.0.0」,Genmask「0.0.0.0」の設定行は,標準のパケット転送先を示しています。この設定は,他の設定に該当しないすべてのパケットに適用されます。この行で設定されているGatewayは,標準で使われるゲートウエイという意味で「デフォルト・ゲートウエイ」と呼ばれます。