totofugaのブログ

ネットワークとかc言語、perlの話。

Unboundのtarget_fetch_policy

target-fetch-policyについて

マニュアルを見ても「ターゲット アドレスを日和見的に取ってくる」 となってよくわからなかったのでソースから調べてみた。

結果

設定値

デフォルトは”3 2 1 0 0" 数字の並びは左から深度に対応している 深度は委任レコードを返された時に外部名だった場合外部名をたどる回数となる 外部名探索中にさらに外部名が見つかった場合には深度2となり左から2番目の数値が参照される。

数字はいくつの外部名を同時に探すかに対応する。 Unboundでは複数の外部名があった場合同時に問い合わせを行い、レスポンスが速いものが使用される。

0と1の違い

外部名しか存在しない場合は0と1に違いはない 外部名と内部名が混在していた場合、0では内部名のアドレスに対して問い合わせるのと同時に 外部名に対しても1つ問い合わせを行う

-1

-1が指定されていた場合にはすべての外部名の探索が行われる

深度より多い問い合わせ

深度 -1以上の問い合わせは行わないようになっている 例えば”3 1”と指定された場合始めの外部名では3つに対して問い合わせを行うが さらに外部名に出会った時には処理を終了する。

何故-1なのかはわからなかった。

ソースコード

コンフィグから値の設定

iter_init
    iter_apply_cfg
        read_fetch_policy

max_dependency_depthとtarget_fetch_policyに使用している max_dependency_depthには設定した個数-1が入る

使用場所

processQueryTargets
    query_for_targets

processQueryTargetsの中はだいたい以下のようになっている

// 現在の深度の問い合わせ個数取得
tf_policy = ie->target_fetch_policy[iq->depth]; 
if(iq->caps_fallback) {
    // 0x20エンコードの時は強制的に全ての外部名をたどる
    query_for_targets(qstate, iq, ie, id, -1, &extra) 
    ....
} else if(tf_policy != 0) {
    // それ以外の場合には問い合わせ個数分取得
    query_for_targets(qstate, iq, ie, id, tf_policy, &extra); 
    ....
}
// すでにアドレスが分かっている問い合わせ先を取得(内部名やキャッシュされている場合ここで見つけられる)
target = iter_server_selection(...) 

if ( !target ) {
    // 問い合わせ先がなければ一つだけ問い合わせる 
    query_for_targets(qstate, iq, ie, id, 1, &extra); 
}

実験

unboundに付属しているtestboundで試すことができる

server:
    target-fetch-policy: "2 0"
    do-ip6: no

stub-zone:
    name: "."
    stub-addr: 0.0.0.1

CONFIG_END

SCENARIO_BEGIN my test

    RANGE_BEGIN 0 100
        ADDRESS 0.0.0.1

        ENTRY_BEGIN
            MATCH opcode qtype qname
            ADJUST copy_id
            REPLY QR NOERROR
            SECTION QUESTION
                . IN NS
            SECTION ANSWER
                . IN NS A.ROOTSERVERS.NET.
            SECTION ADDITIONAL
                A.ROOTSERVERS.NET. IN A 0.0.0.1
        ENTRY_END

        ENTRY_BEGIN
            MATCH opcode qtype qname
            ADJUST copy_id
            REPLY QR NOERROR
            SECTION QUESTION
                test.jp. IN A
            SECTION AUTHORITY
                jp. IN NS b.jp
                jp. IN NS a.jp
                jp. IN NS c.jp
                jp. IN NS d.jp
            SECTION ADDITIONAL
                d.jp IN A 1.1.1.1
        ENTRY_END
    RANGE_END

    STEP 1 QUERY
        ENTRY_BEGIN
            REPLY RD
            SECTION QUESTION
                test.jp. IN A
        ENTRY_END

    STEP 10 NOTHING

SCENARIO_END

実行結果の一部

[0] unbound[43053:0] info: pending msg;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 0
;; flags: cd ; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 
;; QUESTION SECTION:
b.jp.   IN      A

;; ANSWER SECTION:

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:
; EDNS: version: 0; flags: do ; udp: 4096
;; MSG SIZE  rcvd: 33

[0] unbound[43053:0] debug: pending to 1.1.1.1 port 53
[0] unbound[43053:0] info: pending msg;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 0
;; flags: cd ; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 
;; QUESTION SECTION:
a.jp.   IN      A

;; ANSWER SECTION:

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:
; EDNS: version: 0; flags: do ; udp: 4096
;; MSG SIZE  rcvd: 33

[0] unbound[43053:0] debug: pending to 1.1.1.1 port 53
[0] unbound[43053:0] info: pending msg;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 0
;; flags: ; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 
;; QUESTION SECTION:
test.jp.        IN      A

;; ANSWER SECTION:

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:
; EDNS: version: 0; flags: do ; udp: 4096
;; MSG SIZE  rcvd: 36

設定が深度1の設定が2なので2件の外部名問い合わせと内部名のアドレス(1.1.1.1)に問い合わせているのが確認できる。