EN JA
NG_PATCH(4)
NG_PATCH(4) FreeBSD Kernel Interfaces Manual NG_PATCH(4)

名称

ng_patchnetgraph ノードタイプを変更する普通の (trivial) mbuf データ

書式

#include < netgraph/ng_patch.h>

解説

patch ノードは、それを通り抜けるパケットのデータ変更を実行します。変更は、8、16、32 または 64 ビットサイズの符号なし整数での C 言語の操作の部分集合に制限されます。これらは、次の通りです: 新しい値への設定 (=)、追加 (+=)、引き算 (-=)、乗算 (*=)、除算 (/=)、否定 (= -)、ビット単位の AND (&=)、ビット単位の OR (|=)、ビット単位の排他的論理 OR (^=)、左シフト (<<=)、右シフト (>>=) です。否定操作は、1 つの例外です: 整数は、符号付きとして扱われ、2 番目のオペランド ( value) は、使用されません。ユーザによって指定された順序で、連続的にパケットにすべて適用される、いくつかの変更操作があります。パケットのデータペイロードは、パケットヘッダの本当に最初のバイトに対応する 0 のオフセットで、バイトの配列として見え、そして、 offset から始まる length バイトは、ネットワークのバイト順に単一の整数として取られます。

フック

このノードタイプには、2 つのフックがあります:
in
このフックで受信されたパケットは、config で指定された規則に従って変更され、次に、 out フックが存在していて、接続されているなら、それに転送されます。そうでければ、それらは、元の in フックに反映されます。
out
このフックで受信されたパケットは、少しの変更なしで in フックに転送されます。

コントロールメッセージ

このノードタイプは、次を加えて、一般的なコントロールメッセージをサポートします:
NGM_PATCH_SETCONFIG ( setconfig)
このコマンドは、フックで着信データに適用される変更操作のシーケンスを設定します。次の struct ng_patch_config は、引数として供給されなければなりません:

struct ng_patch_op { 
 uint64_t value; 
 uint32_t offset; 
 uint16_t length; /* 1,2,4 または 8 バイト */ 
 uint16_t mode; 
}; 
/* Patching modes */ 
#define NG_PATCH_MODE_SET 1 
#define NG_PATCH_MODE_ADD 2 
#define NG_PATCH_MODE_SUB 3 
#define NG_PATCH_MODE_MUL 4 
#define NG_PATCH_MODE_DIV 5 
#define NG_PATCH_MODE_NEG 6 
#define NG_PATCH_MODE_AND 7 
#define NG_PATCH_MODE_OR 8 
#define NG_PATCH_MODE_XOR 9 
#define NG_PATCH_MODE_SHL 10 
#define NG_PATCH_MODE_SHR 11 
 
struct ng_patch_config { 
 uint32_t count; 
 uint32_t csum_flags; 
 struct ng_patch_op ops[]; 
};

出力インタフェースでパケットを転送する前に対応するチェックサムを再計算するための IP スタックに指示するために、 csum_flags を CSUM_IP, CSUM_TCP, CSUM_SCTP と CSUM_UDP (他の値は、無視される) の任意の組み合わせで設定することができます。 ng_patch ノードは、それ自体で少しのチェックサムの修正も行いません。

NGM_PATCH_GETCONFIG ( getconfig)
このコントロールメッセージは、 struct ng_patch_config として返された、変更操作の現在のセットを取得します。
NGM_PATCH_GET_STATS ( getstats)
struct ng_patch_stats としてノードの統計を返します。
NGM_PATCH_CLR_STATS ( clrstats)
ノード統計をクリアします。
NGM_PATCH_GETCLR_STATS ( getclrstats)
このコマンドは、統計も不可分にクリアされることを除いて、 NGM_PATCH_GET_STATS と同じです。

シャットダウン

このノードは、 NGM_SHUTDOWN コントロールメッセージを受け取るか、すべてのフックが切断されている時、シャットダウンします。

使用例

ng_patch ノードによって IP パケットの TTL と TOS/DSCP フィールドを変更することができます。リモートネットワーク (例えば、衛星) への 2 つの隣接しているシンプレックス (片方向への送信のみ可能な) リンクがあると仮定すると、中間で期限が切れるパケットが望まれていない出て行かなければならない ICMP 応答を生成することができるように、戻りません。したがって、利用者は、TTL が 0 に到達しないことを保証するために 2 によってリンクに入るあらゆるパケットの TTL を上げる必要があります。それで、あなたは、次の ngctl(8) スクリプトによってシンプレックスリンクの他の終りまで行くパケットを注入するために netgraph 動作がある ipfw(8) 規則をセットアップします:

/usr/sbin/ngctl -f- <<-SEQ 
 mkpeer ipfw: patch 200 in 
 name ipfw:200 ttl_add 
 msg ttl_add: setconfig { count=1 csum_flags=1 ops=[ \ 
  { mode=2 value=3 length=1 offset=8 } ] } 
SEQ 
/sbin/ipfw add 150 netgraph 200 ip from any to simplex.remote.net

ここで、タイプ ng_patch の“ ttl_add”ノードは、IP パケットのヘッダの 9 番目のバイトである 1 バイトの TTL フィールドに 3 の value (モード NG_PATCH_MODE_ADD) を追加するために設定されました。

他の例は、パケット TOS フィールドの 2 つの連続した変更となるでしょう: 例えば、利用者は、 IPTOS_THROUGHPUT ビットをクリアし、 IPTOS_MINCOST ビットを設定する必要があります。それで、利用者は、次のことを行います:

/usr/sbin/ngctl -f- <<-SEQ 
 mkpeer ipfw: patch 300 in 
 name ipfw:300 tos_chg 
 msg tos_chg: setconfig { count=2 csum_flags=1 ops=[ \ 
  { mode=7 value=0xf7 length=1 offset=1 }  \ 
  { mode=8 value=0x02 length=1 offset=1 } ] } 
SEQ 
/sbin/ipfw add 160 netgraph 300 ip from any to any not dst-port 80

これは、最初に 4 番目のビット NG_PATCH_MODE_AND をクリアして、次に 3 番目のビット NG_PATCH_MODE_OR を設定します。

両方の例では、 csum_flags フィールドは、IP チェックサム (しかし、TCP または UDP チェックサムでない) が転送する前に再計算されるべきであることを示すします。

注意: パケットが適切な sysctl(8) 変数を設定することによって netgraph(4) の中で処理された後に ipfw に返されることを確実にするべきです:

sysctl net.inet.ip.fw.one_pass=0

歴史

ng_patch ノードタイプは、 FreeBSD 8.1 で実装されました。

作者

Maxim Ignatenko <gelraen.ua@gmail.com>。このマニュアルページは、 Vadim Goncharov <vadimnuclight@tpu.ru>によって書かれました。

バグ

ノードは、(パケットの長さより大きいなら、相殺されるものを除いて) 各パケットへのあらゆるパッチ操作を盲目的に適用しようとするので、正しいパケットだけをノードに供給することを必ず行います (例えば、IP ヘッダにあることになっている ARP パケットの変更バイトは、それらを壊して、利用者のマシンがネットワークから到達できなくなるかもしれません)。

!!! 警告 !!!

IP スタックの出力パスは、パケットの正しいフィールドと長さを仮定します - 間違えてそれらを不正確な値に変更すると、カーネルパニックを含む予測できない結果が引き起こされるかもしれません。

March 5, 2012 FreeBSD