totofugaのブログ

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

unboundのCNAME処理

処理内容

権威からCNAMEが返ってきた場合、 キャッシュサーバーでは別名を引きに行かなくてはいけない。

仮に下記のような登録があった場合、キャッシュサーバーにて cname.jp.への問い合わせとanswer.jpへの問い合わせを行い、 それらのレコードを合成して結果を返す必要がある

[cname.jp]
cname.jp. CNAME IN answer.jp.
[answer.jp]
answer.jp. A IN 1.1.1.1
[クライアントに返す必要があるレスポンス]
cname.jp. CNAME IN answer.jp.
answer.jp. A IN 1.1.1.1

権威からのCNAME受信

process_response(権威サーバーからのメッセージをparse)
    processQueryResponse(レスポンス処理)
        iter_handle
            iter_dns_store(rrsetのみをキャッシュ)
            handle_name_response
                iter_add_prepend_answer(クライアントへのレスポンスで必要なのでストアしておく)
            iter_qstateのqchase入れ替えしてqstateを初期化
            next_state(iq, INIT_REQUEST_STATE)

CNAMEで返ってきたrrsetを iter_qstateのan_prepend_listに追加しておき、 qchaseをCNAMEから取り出した内容で置き換えて (元の問い合わせはmodule_qstateのqinfoに入っている) 再度リクエスト処理を行う。

INIT_REQUEST_STATEからリクエストを開始するので、 キャッシュがあれば通常通りキャッシュが使用される。

クライアントへのレスポンス

iter_handle
    processFinishded
        iter_prepend(an_prepend_listにストアしていたものを取り出し、dns_msgを作り直す)
        iter_dns_store(msgとrrset両方キャッシュする)

CNAME先の問い合わせとan_prepend_listにストアしていたものを 合成してレスポンスを作成する

合成したものをキャッシュにストアしておく。

まとめ

CNAMEでのリクエストがあった場合には Aレコードをストアしておき問い合わせ名を変えて再度リクエスト。 クライアントに返せる状態になってからAレコードを取り出し合成する。 合成した情報をキャッシュに入れて次回のリクエストに備えている。

おまけ

CNAMEの無限ループを抑えるため、MAX_RESTART_COUNT以上CNAMEを辿らないようになっている MAX_RESTART_COUNTは8となっている。