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

名称

pfパケットフィルタ

書式

device pf
options PF_DEFAULT_TO_DROP

解説

パケットフィルタリングは、カーネルで行われます。疑似デバイス /dev/pf は、ユーザランドプロセスで ioctl(2) インタフェースを通るパケットフィルタの振る舞いを制御できるようにします。フィルタを有効にして無効にする、ルールセットのロード、個別の規則か状態テーブルエントリの追加と削除、統計値の検索するコマンドがあります。最も一般的に使用される関数は、 pfctl(8) によってカバーされています。

一つの ioctl(2) 呼び出し以上に影響を及ぼすルールセットをロードするような操作は、複数の並列操作の発生を防ぐ、いわゆる チケット を必要とします。

(アドレスとポートのような) パケットデータを参照する ioctl(2) パラメータ構造のフィールドは、一般的にネットワークバイト順が期待されます。

規則とアドレステーブルは、いわゆる anchor (アンカ) に含まれています。 ioctl(2) 要求をサービスするとき、引数構造体のアンカフィールドが空であるなら、カーネルは、作動中にデフォルトのアンカ (すなわち、メインルールセット) を使用します。アンカは、名前によって指定され、ファイルシステム階層構造がどのように配置されているかと同様に、‘/’文字で分離された構成要素で、入れ子にされるかもしれません。アンカパスの最終的な構成要素は、操作が実行されるアンカです。

SYSCTL 変数とローダ調整変数

次の loader(8) 調整変数が利用可能です。
net.pf.states_hashsize
状態を格納するハッシュテーブルのサイズ。 2 のべき乗であるべきです。デフォルト値は、32768 です。
net.pf.source_nodes_hashsize
ソースノードを格納するハッシュテーブルのサイズ。 2 のべき乗であるべきです。デフォルト値は、8192 です。

一致する名前がある読み込み専用の sysctl(8) 変数は、実行時に現在の値を得るために提供されています。

カーネルオプション

カーネル設定ファイルの次のオプションは、 pf 操作と関連しています:

PF_DEFAULT_TO_DROP
デフォルトでデフォルトポリシをドロップ (drop) に変更します

IOCTL インタフェース

pf は、< net/pfvar.h>を通して利用可能な、次の ioctl(2) コマンドをサポートします:
DIOCSTART
パケットフィルタを開始する。
DIOCSTOP
パケットフィルタを停止する。
DIOCSTARTALTQ
ALTQ バンド (帯域) 幅制御システムを開始する ( altq(9) 参照)。
DIOCSTOPALTQ
ALTQ バンド (帯域) 幅制御システムを停止する。
DIOCBEGINADDRS struct pfioc_pooladdr *pp

struct pfioc_pooladdr { 
 u_int32_t  action; 
 u_int32_t  ticket; 
 u_int32_t  nr; 
 u_int32_t  r_num; 
 u_int8_t  r_action; 
 u_int8_t  r_last; 
 u_int8_t  af; 
 char   anchor[MAXPATHLEN]; 
 struct pf_pooladdr addr; 
};

バッファアドレスプールをクリアし、その後の DIOCADDADDR, DIOCADDRULEDIOCCHANGERULE DIOCADDADDR、呼び出しのための ticket を取得します。

DIOCADDADDR struct pfioc_pooladdr *pp

次の DIOCADDRULE または DIOCCHANGERULE 呼び出しに使用されるバッファアドレスプールにプールアドレス addr を追加します。他のすべての構造体のメンバは、無視されます。

DIOCADDRULE struct pfioc_rule *pr

struct pfioc_rule { 
 u_int32_t action; 
 u_int32_t ticket; 
 u_int32_t pool_ticket; 
 u_int32_t nr; 
 char  anchor[MAXPATHLEN]; 
 char  anchor_call[MAXPATHLEN]; 
 struct pf_rule rule; 
};

不活発なルールセットの終りに rule を追加します。この呼び出しは、以前の DIOCXBEGIN 呼び出しで取得された ticketDIOCBEGINADDRS 呼び出しで取得された pool_ticket を必要とします。また、プールアドレスが必要であるなら、 DIOCADDADDR を呼び出さなければなりません。オプションの anchor 名は、規則を追加する anchor (アンカ) を示します。 nraction は、無視されます。

DIOCADDALTQ struct pfioc_altq *pa
ALTQ 制御規則またはキューを追加します。

struct pfioc_altq { 
 u_int32_t action; 
 u_int32_t ticket; 
 u_int32_t nr; 
 struct pf_altq  altq; 
};
DIOCGETRULES struct pfioc_rule *pr
その後の DIOCGETRULE 呼び出しのための ticket と、アクティブなルールセット中の規則の番号 nr を取得します。
DIOCGETRULE struct pfioc_rule *pr
以前の DIOCGETRULES 呼び出しで得られた ticket を使用して、その番号 nr によって rule を取得します。 actionPF_GET_CLR_CNTR に設定されるなら、要求された規則で規則毎の統計値は、クリアされます。
DIOCGETADDRS struct pfioc_pooladdr *pp
以前の DIOCGETADDR 呼び出しのための ticket と、 r_action, r_numanchor で指定された規則中のプールアドレスの番号 nr を取得します。
DIOCGETADDR struct pfioc_pooladdr *pp
以前の DIOCGETADDRS 呼び出しで得られた ticket を使用して、 r_action, r_numanchor で指定された規則からその番号 nr によってプールアドレス addr を取得します。
DIOCGETALTQS struct pfioc_altq *pa
以前の DIOCGETALTQ のための ticket と、アクティブリスト中のキューの番号 nr を取得します。
DIOCGETALTQ struct pfioc_altq *pa
以前の DIOCGETALTQS 呼び出しで得られた ticket を使用して、その番号 nr によってキュー制御規則 altq を取得します。
DIOCGETQSTATS struct pfioc_qstats *pq
キューおける統計値を取得します。

struct pfioc_qstats { 
 u_int32_t  ticket; 
 u_int32_t  nr; 
 void  *buf; 
 int   nbytes; 
 u_int8_t  scheduler; 
};

この呼び出しは、 nr によって指定されたキューのための長さ nbytes の統計値 buf のバッファへのポインタに書き込みます。

DIOCGETRULESETS struct pfioc_ruleset *pr

struct pfioc_ruleset { 
 u_int32_t  nr; 
 char   path[MAXPATHLEN]; 
 char   name[PF_ANCHOR_NAME_SIZE]; 
};

その後の DIOCGETRULESET 呼び出しでの使用のために path によって指定されたアンカに直接アタッチされたルールセット (すなわち、アンカ) の番号 nr を取得します。入れ子にされたアンカは、それらが与えられたアンカに直接アタッチされないので、含まれません。与えられたアンカが存在しないなら、この ioctl は、 EINVAL を返します。

DIOCGETRULESET struct pfioc_ruleset *pr
与えられたアンカ path から、その番号 nr によってルールセット (すなわち、アンカ) name と、以前の DIOCGETRULESETS 呼び出しで得ることができる最大数を取得します。この ioctl は、与えられたアンカが存在しないなら、 EINVAL を返すか、または別のプロセスが同時にルールセットを更新するなら、 EBUSY を返します。
DIOCADDSTATE struct pfioc_state *ps
状態エントリを追加します。

struct pfioc_state { 
 struct pfsync_state state; 
};
DIOCGETSTATE struct pfioc_state *ps
状態テーブルから state 構造体の idcreatorid フィールドによって特定されるエントリを抽出します。
DIOCKILLSTATES struct pfioc_state_kill *psk
状態テーブルから一致するエントリを削除します。 psk_killed 中の kill された状態の数を返します。

struct pfioc_state_kill { 
 struct pf_state_cmp psk_pfcmp; 
 sa_family_t  psk_af; 
 int   psk_proto; 
 struct pf_rule_addr psk_src; 
 struct pf_rule_addr psk_dst; 
 char   psk_ifname[IFNAMSIZ]; 
 char   psk_label[PF_RULE_LABEL_SIZE]; 
 u_int   psk_killed; 
};
DIOCCLRSTATES struct pfioc_state_kill *psk
すべての状態をクリアします。それは、 DIOCKILLSTATES のように動作しますが、 pfioc_state_kill 構造体の psk_af, psk_proto, psk_srcpsk_dst フィールドを無視します。
DIOCSETSTATUSIF struct pfioc_if *pi
統計値が累算されるインタフェースを指定します。

struct pfioc_if { 
 char   ifname[IFNAMSIZ]; 
};
DIOCGETSTATUS struct pf_status *s
内部のパケットフィルタの統計値を取得します。

struct pf_status { 
 u_int64_t counters[PFRES_MAX]; 
 u_int64_t lcounters[LCNT_MAX]; 
 u_int64_t fcounters[FCNT_MAX]; 
 u_int64_t scounters[SCNT_MAX]; 
 u_int64_t pcounters[2][2][3]; 
 u_int64_t bcounters[2][2]; 
 u_int32_t running; 
 u_int32_t states; 
 u_int32_t src_nodes; 
 u_int32_t since; 
 u_int32_t debug; 
 u_int32_t hostid; 
 char  ifname[IFNAMSIZ]; 
 u_int8_t pf_chksum[MD5_DIGEST_LENGTH]; 
};
DIOCCLRSTATUS
内部のパケットフィルタの統計値をクリアします。
DIOCNATLOOK struct pfioc_natlook *pnl
発信元 (始点) と宛先 (終点) とポートで状態テーブルエントリを検索します。

struct pfioc_natlook { 
 struct pf_addr  saddr; 
 struct pf_addr  daddr; 
 struct pf_addr  rsaddr; 
 struct pf_addr  rdaddr; 
 u_int16_t  sport; 
 u_int16_t  dport; 
 u_int16_t  rsport; 
 u_int16_t  rdport; 
 sa_family_t  af; 
 u_int8_t  proto; 
 u_int8_t  direction; 
};
DIOCSETDEBUG u_int32_t *level
デバッグレベルを設定します。

enum { PF_DEBUG_NONE, PF_DEBUG_URGENT, PF_DEBUG_MISC, 
   PF_DEBUG_NOISY };
DIOCGETSTATES struct pfioc_states *ps

struct pfioc_states { 
 int ps_len; 
 union { 
  caddr_t   psu_buf; 
  struct pf_state *psu_states; 
 } ps_u; 
#define ps_buf  ps_u.psu_buf 
#define ps_states ps_u.psu_states 
};

ps_len がエントリで 0 以外であるなら、このサイズに収まるできるだけ多くの状態は、供給されたバッファ ps_states にコピーされます。終了時に、 ps_len は、常にすべての状態テーブルエントリを保持するために必要な合計のサイズに設定されます (すなわち、それは、 sizeof(struct pf_state) * nr に設定されます)。

DIOCCHANGERULE struct pfioc_rule *pcr
rule.action によって指定された ruleset 中の rule を追加するか、または削除します。

実行される操作のタイプは、次のいずれかで指定できる、 action 示されます:

enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL, 
   PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER, 
   PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET };

ticket は、 PF_CHANGE_GET_TICKET 以外のすべての動作 (action) のために PF_CHANGE_GET_TICKET で得られる値を設定しなければなりません。 pool_ticket は、 PF_CHANGE_REMOVEPF_CHANGE_GET_TICKET 以外のすべての動作 (action) のための DIOCBEGINADDRS 呼び出しで得られる値を設定しなければなりません。 anchor は、どのアンカの操作が適用されるかを示します。 nr は、 PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER または PF_CHANGE_REMOVE 動作が適用されている規則番号を示します。

DIOCCHANGEADDR struct pfioc_pooladdr *pca
r_action, r_numanchor によって指定された規則から、プールアドレス addr を追加するか、または削除します。
DIOCSETTIMEOUT struct pfioc_tm *pt

struct pfioc_tm { 
 int   timeout; 
 int   seconds; 
};

timeout の状態タイムアウトを seconds に設定します。古い値は、 seconds に置かれます。 timeout に指定可能な値は、< net/pfvar.h>の PFTM_* 値を調べてください。

DIOCGETTIMEOUT struct pfioc_tm *pt
timeout の状態タイムアウトを取得します。値は、 seconds フィールドに置かれます。
DIOCCLRRULECTRS
規則毎の統計値をクリアします。
DIOCSETLIMIT struct pfioc_limit *pl
パケットフィルタで使用されるメモリプールにおけるハードの制限を設定します。

struct pfioc_limit { 
 int  index; 
 unsigned limit; 
}; 
 
enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS, 
   PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_MAX };
DIOCGETLIMIT struct pfioc_limit *pl
index によって示されたメモリプールのためのハードの limit を取得します。
DIOCRCLRTABLES struct pfioc_table *io
すべてのテーブルをクリアします。同じ構造体を使用する基数テーブルを操作するすべての ioctl は、以下に説明されます。 DIOCRCLRTABLES に関して、 pfrio_ndel は、終了時に削除されたテーブルの数を含んでいます。

struct pfioc_table { 
 struct pfr_table  pfrio_table; 
 void   *pfrio_buffer; 
 int    pfrio_esize; 
 int    pfrio_size; 
 int    pfrio_size2; 
 int    pfrio_nadd; 
 int    pfrio_ndel; 
 int    pfrio_nchange; 
 int    pfrio_flags; 
 u_int32_t   pfrio_ticket; 
}; 
#define pfrio_exists    pfrio_nadd 
#define pfrio_nzero     pfrio_nadd 
#define pfrio_nmatch    pfrio_nadd 
#define pfrio_naddr     pfrio_size2 
#define pfrio_setflag   pfrio_size2 
#define pfrio_clrflag   pfrio_nadd
DIOCRADDTABLES struct pfioc_table *io
1 つ以上のテーブルを作成します。登録時に、 pfrio_buffer は、少なくとも pfrio_size 要素を含む struct pfr_table の配列を指さなければなりません。 pfrio_esize は、 struct pfr_table のサイズでなければなりません。終了時に、 pfrio_nadd は、事実上作成されたテーブルの数を含んでいます。

struct pfr_table { 
 char  pfrt_anchor[MAXPATHLEN]; 
 char  pfrt_name[PF_TABLE_NAME_SIZE]; 
 u_int32_t pfrt_flags; 
 u_int8_t pfrt_fback; 
};
DIOCRDELTABLES struct pfioc_table *io
1 つ以上のテーブルを削除します。登録時に、 pfrio_buffer は、少なくとも pfrio_size 要素を含む struct pfr_table の配列を指さなければなりません。 pfrio_esize は、 struct pfr_table のサイズでなければなりません。終了時に、 pfrio_ndel は、事実上削除されたテーブルの数を含んでいます。
DIOCRGETTABLES struct pfioc_table *io
すべてのテーブルのリストを取得します。登録時に、 pfrio_buffer[pfrio_size] は、 pfr_table 構造体のための有効な書き込み可能なバッファを含んでいます。終了時に、 pfrio_size は、バッファの中に書き込まれたテーブルの数を含んでいます。バッファが小さ過ぎるなら、カーネルは、何も格納しませんが、エラーを除いて、単に必要なバッファサイズを返します。
DIOCRGETTSTATS struct pfioc_table *io
この呼び出しは、 DIOCRGETTABLES に似ていますが、 pfr_tstats 構造体の配列を取得するために使用されます。

struct pfr_tstats { 
 struct pfr_table pfrts_t; 
 u_int64_t  pfrts_packets 
        [PFR_DIR_MAX][PFR_OP_TABLE_MAX]; 
 u_int64_t  pfrts_bytes 
        [PFR_DIR_MAX][PFR_OP_TABLE_MAX]; 
 u_int64_t  pfrts_match; 
 u_int64_t  pfrts_nomatch; 
 long   pfrts_tzero; 
 int   pfrts_cnt; 
 int   pfrts_refcnt[PFR_REFCNT_MAX]; 
}; 
#define pfrts_name  pfrts_t.pfrt_name 
#define pfrts_flags  pfrts_t.pfrt_flags
DIOCRCLRTSTATS struct pfioc_table *io
1 つ以上のテーブルの統計値をクリアします。登録時に、 pfrio_buffer は、少なくとも pfrio_size 要素を含む struct pfr_table の配列を指さなければなりません。 pfrio_esize は、 struct pfr_table のサイズでなければなりません。終了時に、 pfrio_nzero は、事実上クリアされたテーブルの数を含んでいます。
DIOCRCLRADDRS struct pfioc_table *io
テーブル中のすべてのアドレスをクリアします。登録時に、 pfrio_table は、クリアされるテーブルを含んでいます。終了時に、 pfrio_ndel は、削除されたアドレスの数を含んでいます。
DIOCRADDADDRS struct pfioc_table *io
テーブルに 1 つ以上のアドレスを追加します。登録時に、 pfrio_table は、テーブル ID を含み、 pfrio_buffer は、テーブルに追加するために少なくとも pfrio_size 要素を含む struct pfr_addr の配列を指さなければなりません。 pfrio_esize は、 struct pfr_addr のサイズでなければなりません。終了時に、 pfrio_nadd は、事実上追加されたアドレスの数を含んでいます。

struct pfr_addr { 
 union { 
  struct in_addr  _pfra_ip4addr; 
  struct in6_addr  _pfra_ip6addr; 
 }   pfra_u; 
 u_int8_t  pfra_af; 
 u_int8_t  pfra_net; 
 u_int8_t  pfra_not; 
 u_int8_t  pfra_fback; 
}; 
#define pfra_ip4addr    pfra_u._pfra_ip4addr 
#define pfra_ip6addr    pfra_u._pfra_ip6addr
DIOCRDELADDRS struct pfioc_table *io
テーブルから 1 つ以上のアドレスを削除します。登録時に、 pfrio_table は、テーブル ID を含み、 pfrio_buffer は、テーブルから削除するために少なくとも pfrio_size 要素を含む struct pfr_addr の配列を指さなければなりません。 pfrio_esize は、 struct pfr_addr のサイズでなければなりません。終了時に、 pfrio_ndel は、事実上削除されたアドレスの数を含んでいます。
DIOCRSETADDRS struct pfioc_table *io
新しいアドレスリストによってテーブルの内容を置き換えます。これは、すべての構造メンバを使用する、最も複雑なコマンドです。

登録時に、 pfrio_table は、テーブル ID を含み、 pfrio_buffer は、テーブルの新しい内容となる少なくとも pfrio_size 要素を含む struct pfr_addr の配列を指さなければなりません。 pfrio_esize は、 struct pfr_addr のサイズでなければなりません。さらに、 pfrio_size2 が 0 でなければ、 pfrio_buffer[pfrio_size..pfrio_size2] は、カーネルが、置き換え操作の間に削除されたアドレスをコピーすることができように、書き込み可能なバッファでなければなりません。終了時に、 pfrio_ndel, pfrio_naddpfrio_nchange は、カーネルによって削除され、追加され、変更されたアドレスの数を含んでいます。 pfrio_size2 がエントリに設定されたなら、 pfrio_size2 は、まさに DIOCRGETADDRS のように使用されるバッファのサイズを指します。

DIOCRGETADDRS struct pfioc_table *io
テーブルのすべてのアドレスを取得します。登録時に、 pfrio_table は、テーブル ID を含み、 pfrio_buffer[pfrio_size] は、 pfr_addr 構造体のための有効な書き込み可能なバッファを含んでいます。終了時に、 pfrio_size は、バッファ中に書き込まれたアドレスの数を含んでいます。バッファが小さ過ぎたなら、カーネルは、何も格納しませんが、エラーリターンを除いて、単に必要なバッファサイズを返します。
DIOCRGETASTATS struct pfioc_table *io
この呼び出しは、 DIOCRGETADDRS に似ていますが、 pfr_astats 構造体の配列を返します。

struct pfr_astats { 
 struct pfr_addr  pfras_a; 
 u_int64_t  pfras_packets 
        [PFR_DIR_MAX][PFR_OP_ADDR_MAX]; 
 u_int64_t  pfras_bytes 
        [PFR_DIR_MAX][PFR_OP_ADDR_MAX]; 
 long   pfras_tzero; 
};
DIOCRCLRASTATS struct pfioc_table *io
1 つ以上のアドレスの統計値をクリアします。登録時に、 pfrio_table は、テーブル ID を含み、 pfrio_buffer は、テーブルからクリアされるために少なくとも pfrio_size 要素を含む struct pfr_addr の配列を指さなければなりません。 pfrio_esize は、 struct pfr_addr のサイズでなければなりません。終了時に、 pfrio_nzero は、事実上クリアされたアドレスの数を含んでいます。
DIOCRTSTADDRS struct pfioc_table *io
与えられたアドレスがテーブルに一致するか、テストします。登録時に、 pfrio_table は、テーブル ID を含み、 pfrio_buffer は、それぞれがテーブルでマッチがないかテストされる、少なくとも pfrio_size 要素を含む struct pfr_addr の配列を指さなければなりません。 pfrio_esize は、 struct pfr_addr のサイズでなければなりません。終了時に、カーネルは、適切に pfra_fback メンバを設定することによって pfr_addr 配列を更新します。
DIOCRSETTFLAGS struct pfioc_table *io
テーブルの PFR_TFLAG_CONST または PFR_TFLAG_PERSIST フラグを変更します。登録時に、 pfrio_buffer は、少なくとも pfrio_size 要素を含む struct pfr_table の配列を指さなければなりません。 pfrio_esize は、 struct pfr_table のサイズでなければなりません。 pfrio_setflag は、追加するフラグを含まなければなりません、一方 pfrio_clrflag は、削除されるフラグを含まなければなりません。終了時に、 pfrio_nchangepfrio_ndel は、カーネルによって変更されるか、または削除されたテーブルの数を含んでいます。はい、参照されないテーブルの PFR_TFLAG_PERSIST フラグを取り除かれるなら、テーブルは、削除することができます。
DIOCRINADEFINE struct pfioc_table *io
アクティブでない集合 (セット) でテーブルを定義します。登録時に、 pfrio_table は、テーブル ID を含み、 pfrio_buffer[pfrio_size] は、テーブルに置く pfr_addr 構造体の配列を含んでいます。また、有効なチケットは、 pfrio_ticket に供給しなければなりません。終了時に、 pfrio_nadd は、既にテーブルがアクティブでないリストで定義されているなら、0 を含み、新しいテーブルが作成してあるなら 1 を含んでいます。 pfrio_naddr は、事実上テーブルに置かれるアドレスの数を含んでいます。
DIOCXBEGIN struct pfioc_trans *io

struct pfioc_trans { 
 int   size; /* 要素の数 */ 
 int   esize; /* 各要素のバイト単位のサイズ */ 
 struct pfioc_trans_e { 
  int  rs_num; 
  char  anchor[MAXPATHLEN]; 
  u_int32_t ticket; 
 }  *array; 
};

pfioc_trans_e 配列で指定されたすべてのアクティブでない ruleset をクリアします。各 ruleset に関しては、 DIOCXCOMMITDIOCXROLLBACK 呼び出しと同様に、その後の "add rule" ioctl のためにチケットが返されます。

rs_num によって識別されるルールセットのタイプは、次に含まれます:

PF_RULESET_SCRUB
scrub (延期する) (パケット正規化) 規則。
PF_RULESET_FILTER
フィルタ規則。
PF_RULESET_NAT
NAT (Network Address Translation) 規則。
PF_RULESET_BINAT
双方向の NAT 規則。
PF_RULESET_RDR
リダイレクト規則。
PF_RULESET_ALTQ
ALTQ 制御規則。
PF_RULESET_TABLE
アドレステーブル。
DIOCXCOMMIT struct pfioc_trans *io
アクティブでない ruleset のベクトルをアクティブな ruleset に不可分に (atomically) 切り換えます。この呼び出しは、すべてのルールセットが失敗するか、または完全に成功するかのいずれかである、標準の二相コミットとして実装されます。この ioctl は、別のプロセスが同じルールセットのいくつかを同時に更新するなら、 EBUSY を返します。
DIOCXROLLBACK struct pfioc_trans *io
最後の DIOCXBEGIN 以後にアクティブでない ruleset で起こるすべての変更を元に戻すことによって、カーネルをクリーンアップします。 DIOCXROLLBACK は、静かに、チケットが無効である ruleset を無視します。
DIOCSETHOSTID u_int32_t *hostid
どのホストが状態テーブルエントリを作成したか識別するために pfsync(4) によって使用される、ホスト ID を設定します。
DIOCOSFPFLUSH
パッシブ OS 指紋テーブルをフラッシュします。
DIOCOSFPADD struct pf_osfp_ioctl *io

struct pf_osfp_ioctl { 
 struct pf_osfp_entry { 
  SLIST_ENTRY(pf_osfp_entry) fp_entry; 
  pf_osfp_t  fp_os; 
  char   fp_class_nm[PF_OSFP_LEN]; 
  char   fp_version_nm[PF_OSFP_LEN]; 
  char   fp_subtype_nm[PF_OSFP_LEN]; 
 }    fp_os; 
 pf_tcpopts_t  fp_tcpopts; 
 u_int16_t  fp_wsize; 
 u_int16_t  fp_psize; 
 u_int16_t  fp_mss; 
 u_int16_t  fp_flags; 
 u_int8_t  fp_optcnt; 
 u_int8_t  fp_wscale; 
 u_int8_t  fp_ttl; 
 int   fp_getnum; 
};

テーブルにパッシブ OS 指紋を追加します。 fp_os.fp_os にパックされた指紋を、 fp_os.fp_class_nm にクラス (Linux、Windows など) の名前を、 fp_os.fp_version_nm にバージョン (NT、95、98) の名前を、そして fp_os.fp_subtype_nm にサブタイブまたはパッチレベルの名前を設定します。メンバ fp_mss, fp_wsize, fp_psize, fp_ttl, fp_optcntfp_wscale は、それぞれ TCP MSS、TCP ウィンドウサイズ、IP の長さ、 IP TTL、TCP オプションの数と TCP SYN パケットの TCP ウィンドウのスケーリング定数が設定されます。

fp_flags メンバは、 PF_OSFP_* を定義している< net/pfvar.h>インクルードファイルに従って満たされます。 fp_tcpopts メンバは、パックされた TCP オプションを含みます。各オプションは、パックされた値の PF_OSFP_TCPOPT_BITS ビットを使用します。オプションは、 PF_OSFP_TCPOPT_NOP, PF_OSFP_TCPOPT_SACK, PF_OSFP_TCPOPT_WSCALE, PF_OSFP_TCPOPT_MSS または PF_OSFP_TCPOPT_TS のいずれかを含みます。

fp_getnum メンバは、この ioctl では使用されません。

構造体の使用していない領域は、適格な操作 memset で 0 にしなければなりません。 memset(3) を使用して書き込まれる前にすべての構造体を 0 にして、カーネルに送ります。

DIOCOSFPGET struct pf_osfp_ioctl *io
カーネルの指紋リストからパッシブ OS 指紋番号 fp_getnum を取得します。構造体のメンバの残りは、書き込まれた状態で戻ります。 ioctl が EBUSY を返すまで、 fp_getnum 番号を増加することを繰り返すことによって、全体のリストを取得できます。
DIOCGETSRCNODES struct pfioc_src_nodes *psn

struct pfioc_src_nodes { 
 int psn_len; 
 union { 
  caddr_t  psu_buf; 
  struct pf_src_node *psu_src_nodes; 
 } psn_u; 
#define psn_buf  psn_u.psu_buf 
#define psn_src_nodes psn_u.psu_src_nodes 
};

sticky address と source 追跡によってソースノード保管リストを取得します。 ioctl は、0 に設定された psn_len で一度呼び出されなければなりません。 ioctl がエラーなしで返るなら、 psn_len は、テーブルに保持されているすべての pf_src_node 構造体を保持するために要求されるバッファのサイズに設定されます。次に、このサイズのバッファが割り付けられるべきで、このバッファへのポインタは、 psn_buf に置かれます。そして、実際のソースノードデータでこのバッファを満たすために再び ioctl を呼び出さなければなりません。その呼び出しの後に、 psn_len は、実際に使用されたバッファの長さに設定されます。

DIOCCLRSRCNODES
ソース追跡ノードのツリーをクリアします。
DIOCIGETIFACES struct pfioc_iface *io
pf に知られているインタフェースとインタフェースドライバのリストを取得します。インタフェースを操作するすべての ioctl は、以下に記述された同じ構造を使用します:

struct pfioc_iface { 
 char    pfiio_name[IFNAMSIZ]; 
 void   *pfiio_buffer; 
 int    pfiio_esize; 
 int    pfiio_size; 
 int    pfiio_nzero; 
 int    pfiio_flags; 
};

空でなければ、 pfiio_name は、特定のインタフェースまたはドライバの検索を制限するために使用することができます。 pfiio_buffer[pfiio_size] は、データを返すためのユーザによって供給されたバッファです。登録時に、 pfiio_size は、バッファに適合することができる pfi_kif エントリの数を含みます。カーネルは、返さなければならないエントリの実際の数でこの値を置き換えます。 pfiio_esize は、 sizeof(struct pfi_kif) に設定されるべきです。

以下に記述された pfi_kif 構造体にデータは、返されます:

struct pfi_kif { 
 RB_ENTRY(pfi_kif)   pfik_tree; 
 char     pfik_name[IFNAMSIZ]; 
 u_int64_t    pfik_packets[2][2][2]; 
 u_int64_t    pfik_bytes[2][2][2]; 
 u_int32_t    pfik_tzero; 
 int     pfik_flags; 
 struct pf_state_tree_lan_ext  pfik_lan_ext; 
 struct pf_state_tree_ext_gwy  pfik_ext_gwy; 
 TAILQ_ENTRY(pfi_kif)   pfik_w_states; 
 void    *pfik_ah_cookie; 
 struct ifnet   *pfik_ifp; 
 struct ifg_group  *pfik_group; 
 int     pfik_states; 
 int     pfik_rules; 
 TAILQ_HEAD(, pfi_dynaddr)  pfik_dynaddrs; 
};
DIOCSETIFFLAG struct pfioc_iface *io
pf の内部のインタフェース記述のユーザ設定可能なフラグ (以下に説明される) を設定します。フィルタリングプロセスは、 DIOCIGETIFACES に対するものと同じです。

#define PFI_IFLAG_SKIP 0x0100 /* インタフェースのスキップフィルタリング */
DIOCCLRIFFLAG struct pfioc_iface *io
上記の DIOCSETIFFLAG として動作しますが、フラグをクリアします。
DIOCKILLSRCNODES struct pfioc_iface *io
明示的にソースの追跡ノードを削除します。

関連ファイル

/dev/pf
パケットフィルタリングデバイス

使用例

次の例は、NAT 接続の内部のホスト/ポートを見つけためにどのように DIOCNATLOOK コマンドを使用するかを示しています。

#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <sys/fcntl.h> 
#include <net/if.h> 
#include <netinet/in.h> 
#include <net/pfvar.h> 
#include <err.h> 
#include <stdio.h> 
#include <stdlib.h> 
 
u_int32_t 
read_address(const char *s) 
{ 
 int a, b, c, d; 
 
 sscanf(s, "%i.%i.%i.%i", &a, &b, &c, &d); 
 return htonl(a << 24 | b << 16 | c << 8 | d); 
} 
 
void 
print_address(u_int32_t a) 
{ 
 a = ntohl(a); 
 printf("%d.%d.%d.%d", a >> 24 & 255, a >> 16 & 255, 
     a >> 8 & 255, a & 255); 
} 
 
int 
main(int argc, char *argv[]) 
{ 
 struct pfioc_natlook nl; 
 int dev; 
 
 if (argc != 5) { 
  printf("%s <gwy addr> <gwy port> <ext addr> <ext port>\n", 
      argv[0]); 
  return 1; 
 } 
 
 dev = open("/dev/pf", O_RDWR); 
 if (dev == -1) 
  err(1, "open(\"/dev/pf\") failed"); 
 
 memset(&nl, 0, sizeof(struct pfioc_natlook)); 
 nl.saddr.v4.s_addr = read_address(argv[1]); 
 nl.sport  = htons(atoi(argv[2])); 
 nl.daddr.v4.s_addr = read_address(argv[3]); 
 nl.dport  = htons(atoi(argv[4])); 
 nl.af   = AF_INET; 
 nl.proto  = IPPROTO_TCP; 
 nl.direction  = PF_IN; 
 
 if (ioctl(dev, DIOCNATLOOK, &nl)) 
  err(1, "DIOCNATLOOK"); 
 
 printf("internal host "); 
 print_address(nl.rsaddr.v4.s_addr); 
 printf(":%u\n", ntohs(nl.rsport)); 
 return 0; 
}

歴史

pf パケットフィルタリングメカニズムは、 OpenBSD 3.0 ではじめて登場し、次に、 FreeBSD 5.2 で登場しました。

この実装は、 OpenBSD 4.5 に由来します。それは、マルチスレッド化された FreeBSD カーネルで実行することができ、複数の CPU で性能を計ることができるように大幅に修正されました。

November 14, 2013 FreeBSD