Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ bpf(4) — NEWS-os 4.2.1R

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

tcpdump(8)

intro(4)

BPF(4)  —  NEWS-OS Programmer’s Manual

名称

bpf − バークレー版パケットフィルタ

形式

pseudo-device bpfilter 16

解説

バークレー版パケットフィルタは、 プロトコル独立型でデータリンク層へ直接的なインターフェース を提供します。 ネットワーク上の全てのパケット、 他のホストへのものも含めて、 この方法でアクセスが可能です。 ただし FDDI インターフェース fn では、自ホストあてのパケットのみが参照可能です。

パケットフィルタはキャラクタ特殊 デバイス /dev/bpf0、 /dev/bpf1 等々 として現われます。 このようなファイルを開いた後、 ファイル記述子は BIOSETIF ioctl によって 特定のインターフェースに結合されます。 インターフェースは一つ以上のファイル記述子と結合されることができ、 各記述子のフィルタは 同一のパケットストリームを参照します。 オープンするファイルの総数はカーネル構成時の値に制限されています。 上記の形式の項での例では、 制限を 16 に設定してあります。

BSD システムでは、 デバイスクローニングをサポートしていません。 そのため、個別のマイナーデバイスとして それぞれデバイスファイルが必要となります。 ファイルが使用中の場合、 オープンは失敗となり errno が EBUSY に設定されます。

ユーザ設定可能なパケットフィルタが bpf ファイルのオープン実体と関連づけられます。 パケットがインターフェースから受信されると、 そのインターフェースを参照する全てのファイル記述子 はそのフィルタを適用します。 パケットを受け入れる各記述子は それぞれのコピーを受信します。

これらのファイルを読みだすことで、 フィルタに合致する次のパケットのグループ を返します。 性能を向上するために、 受信バッファは bpf で内部的に使用されているバッファと同じサイズでなければなりません。 このサイズは BIOCGBLEN ioctl (下記参照) で返されます。 このサイズよりも大きいパケットは必ず切り捨てなければなりません。

パケットフィルタは ヘッダ長が固定の全てのリンクレベルプロトコル をサポートするつもりです。 現在は イーサネット、SLIP、ISDN、X.25、専用線、および FDDI ドライバで bpf と相互に作用するように変更されています。

パケットデータはネットワークのバイト順になっているので、 アプリケーションでマルチバイト値を取り出すためには byteorder(3N) マクロを使用すべきです。

パケットは bpf ファイル記述子に書き込むことで ネットワーク上に送出できます。 書き込みはバッファリングされず、 write コール毎に一つのパケットのみが処理されます。 現在、 イーサネット、SLIP、ISDN、X.25、専用線、および FDDI への 書き込みがサポートされています。

IOCTL コール

下記に示す ioctl コマンドコードは、<net/bpf.h> に定義されています。 全てのコマンドは下記のインクルードファイルが必要です。

 #include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <net/bpf.h>
 

さらに、BIOCGETIF および BIOCSETIF では <net/if.h> が必要です。
 
FIONREAD および SIOCGIFADDR に加え、以下のコマンドが どのオープン bpf ファイルにも適応されます。 ioctl に対する (3 番目の) 引数が指定されたタイプへのポインタ になるようにします。

BIOCGFLEN (u_int)
パケットフィルタプログラムの最大長を 構造体 bpf_insn の単位で返します (下記の BIOCSETF 参照)。 この値よりも長いフィルタをセットすると、 エラーになります。

BIOCGBLEN (u_int)
bpf ファイルを読む際の必要なバッファ長を返します。 このサイズと異なるバッファが渡されると、 読みだしコールは EIO となります。

BIOCDEVP (struct bpf_devp)
オープンファイルに関するネットワークインターフェース へのデバイスパラメータを持つ以下の構造体を返します。

 struct bpf_devp {
u_short bdev_type;
u_short bdev_hdrlen;
};

各フィールドは:

bdev_type デバイスタイプ。タイプは <net/bpf.h> に定義されています。現在、 DLT_EN10MB、DLT_SLIP、DLT_BISDN および DLT_FDDI がサポートされています。

bdev_hdrlen ヘッダ長の合計(バイト数。Ethernet なら 14、SLIP なら 16)

BIOCPROMISC
インターフェースを プロミスキュアスモード (自ホストあてだけではなく、全てのパケットを受信する状態) にします。 2 つ以上のファイルがある一つのインターフェースを 参照できるので、プロミスキュアスモードではないように インターフェースをオープンしても 無差別にパケットを受信することがあります。 この問題は適切なフィルタによって矯正できます。

プロミスキュアスモードで参照を行っている全てのファイル がクローズされるまで、インターフェースはプロミスキュアスモード のままとなります。

BIOCFLUSH
入力パケットのバッファをフラッシュし、 BIOCGSTATS によって返される統計データをリセットします。

BIOCGETIF (struct ifreq)
ファイルが参照しているハードウェアインターフェース名を 返します。 ifr の if_name フィールドに返されます。 その他のフィールドは未定義です。

BIOCSETIF (struct ifreq)
ファイルに関連するハードウェアインターフェースをセットします。 このコマンドはパケットを読む前に行わなければなりません。 デバイスは ifreq の if_name フィールドで示します。 さらに、BIOCFLUSH の動作を行います。

BIOCSRTIMEOUT, BIOCGRTIMEOUT (struct timeval)
読み込みタイムアウトパラメータをセット又は獲得します。 timeval で、読みだし要求時のタイムアウトまでの 待ち時間の長さを指定します。 このパラメータは open(2) によってゼロに初期設定され、これはタイムアウト無しを表します。

BIOCGSTATS (struct bpf_stat)
以下に示すパケットの統計情報の構造体を 返します。

 struct bpf_stat {
u_int bs_recv;
u_int bs_drop;
};

各フィールドは:

bs_recv オープン又はリセット後、記述子によって受信したパケット の数。 (最後の読みだしコール後のバッファされたものを含む)

bs_drop フィルタには受け入れられたが、 バッファがオーバフローしたため カーネル内でドロップ されたパケットの数。 (例えば、アプリケーションの読み出しがパケットの通信量に追い付かない場合)

BIOCIMMEDIATE (u_int)
引数の真理値によって、“即時モード” の可、不可を指定します。 即時モードが有効の場合、read コールはパケット受信直後に戻ります。 即時モードでない場合には、 カーネルバッファが満杯又はタイムアウトが発生するまで read コールは ブロックします。 これは rarpd(8) など、リアルタイムでメッセージに応える必要があるプログラムに有効です。 新規ファイルに対するデフォルトは off です。

BIOCSETF (struct bpf_program)
関心の無いパケットを破棄する為にカーネル によって使用されるフィルタプログラムをセットします。 一連の命令およびその長さを以下の構造体によって指定します。

 struct bpf_program {
int bf_len;
struct bpf_insn ∗bf_insns;
};

フィルタプログラムは bf_insns フィールドによって示され、その長さは ‘struct bpf_insn’ の単位で bf_len フィールドによって与えられます。 さらに、BIOCFLUSH の動作が行われます。

フィルタリングマシンについては、 bpf および tcpdump(1) と共に提供されるテクニカルレポート“The Berkeley Packet Filter”を 参照してください。

BPF ヘッダ

以下の構造体は read(2) コールによって返される各パケットに先行します。

 struct bpf_hdr {
struct timeval bh_tstamp;
u_long bh_caplen;
u_long bh_datalen;
u_short bh_hdrlen;
};

各フィールドの値はホストオーダーで格納されます。

bh_tstamp パケットがパケットフィルタによって処理された時刻。

bh_caplen パケットの獲得した部分の長さ。 これはフィルタによって指定した切り捨ての長さと パケット長の最小値になります。

bh_datalen 回線から受信したパケットの長さ。 この値はフィルタによって指定する切り捨て量とは独立しています。

bh_hdrlen BPF ヘッダの長さ。 sizeof(struct bpf_hdr) とは異なることがあります。 詳細を以下に示します。

bh_hdrlen フィールドはヘッダとリンクレベルプロトコル間に パディングがなされていることを示します。 ここでの目的は、パケットデータ構造体の適切なアライメントを保障するためにあり、 ある RISC アーキテクチャにおいて必要で、 その他多くのアーキテクチャにおいても性能を良くします。 パケットフィルタは、 bpf_hdr および network layer ヘッダがワード単位でアラインされることを保障します。 アライメントに制限のあるマシン上で、 リンクレイヤプロトコルフィールドにアクセスする際には、 適切な注意が必要です。 (イーサネットでは、 タイプフィールドが short 型で、偶数オフセットに置かれ、 アドレスはバイト単位でアクセスされるため、 問題とはならないでしょう。)

また、個々のパケットはワード境界で始まるようにパディングされます。 このため、アプリケーションはパケットの境界を知る必要があります。 この処理を容易にするために、 マクロ BPF_WORDALIGN が <net/bpf.h> に定義されています。 それは最も近いワード境界 (ワードが BPF_ALIGNMENT バイト幅であるところ) に引数を切り上げます。

例えば、‘p’ がパケットの先頭を示している場合、 この式は次のパケットに進めます。

p = (char ∗)p + BPF_WORDALIGN(p−>bh_hdrlen + p−>bh_caplen)

アライメントメカニズムが適切に動作するためには、 read(2) に渡されたバッファはそれ自身がワード境界になければなりません。 malloc(3) は常に調整されたバッファを返します。

関連事項

tcpdump(8), intro(4)

関連ファイル

/dev/bpf0, /dev/bpf1, ... 

バグ

読みだしバッファのサイズは固定 (BIOCGBLEN ioctl で返される) でなければなりません。

プロミスキュアスモードを要求しないファイルでも、 同じハードウェアインターフェースでプロミスキュアスモードを要求する別のファイルの 副作用として、受信パケットを無差別に受信することがあります。 これは、さらに処理を増やせばカーネル内で対策することができます。 しかし、すべてのファイルが インターフェースをプロミスキュアスモードにするようなモデルが便利であり、 必要であれば無関係のパケットを拒否するフィルタ を活用して下さい。

可変長ヘッダを持つデータリンクプロトコルは、 現在サポートされておりません。

歴史

Enet パケットフィルタは 1980 年、 カーネギーメロン大学の Mike Accetta と Rick Rashid によって作られました。 そして、スタンフォードの Jeffrey Mogul は BSD にコード を移植し、1983 年以降その開発を続けています。 その後、DEC の Ultrix Packet Filter、 SunOS 4.1 の STREAMS NIT モジュール、 BPF に引き継がれました。 1990 年の夏には、 Lawrence Berkeley 研究所の Steven McCanne によって BPF が完成しました。 その設計の多くの部分は Van Jacobson によるものです。

NEWS-OSRelease 4.2.1R

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026