3. サーバーの動作
3. サーバーの動作
サーバーは、UPDATEリクエストを受信すると、UPDATEオペコードが認識されない場合、または認識されているが実装されていない場合、リクエスタにNOTIMPを通知します。それ以外の場合、処理は次のように続行されます。
3.1 ゾーンセクションの処理
3.1.1. Zoneセクションをチェックして、そこに正確に1つのRRがあり、RRのZTYPEがSOAであることを確認し、そうでない場合はリクエスタにFORMERRを通知します。次に、ZNAMEとZCLASSをチェックして、そのように名付けられたゾーンがこのサーバーの権威ゾーンの1つであることを確認し、そうでない場合はリクエスタにNOTAUTHを通知します。サーバーがゾーンスレーブである場合、リクエストはプライマリマスターに転送されます。
3.1.2 - ゾーンセクション処理の擬似コード
if (zcount != 1 || ztype != SOA)
return (FORMERR)
if (zone_type(zname, zclass) == SLAVE)
return forward()
if (zone_type(zname, zclass) == MASTER)
return update()
return (NOTAUTH)
セクション3.2から3.8は、プライマリマスターの動作を説明しますが、セクション6は転送者の動作を説明します。
3.2 前提条件セクションの処理
次に、Prerequisiteセクションをチェックして、すべての前提条件がゾーンの現在の状態によって満たされていることを確認します。セクション1.2で表現された定義を使用して、RRのNAMEがZoneセクションで指定されたゾーン内にない場合、リクエスタにNOTZONEを通知します。
3.2.1. このセクション内のCLASSがANYであるRRについて、TTLとRDLENGTHの両方がゼロ(0)であることをテストし、そうでない場合はリクエスタにFORMERRを通知します。TYPEがANYの場合、Prerequisite RRのNAMEと同じNAMEを持つ少なくとも1つのRRがゾーン内に存在することをテストし、そうでない場合はリクエスタにNXDOMAINを通知します。TYPEがANYでない場合、Prerequisite RRのNAMEとTYPEと同じNAMEとTYPEを持つ少なくとも1つのRRがゾーン内に存在することをテストし、そうでない場合はリクエスタにNXRRSETを通知します。
3.2.2. このセクション内のCLASSがNONEであるRRについて、TTLとRDLENGTHの両方がゼロ(0)であることをテストし、そうでない場合はリクエスタにFORMERRを通知します。TYPEがANYの場合、Prerequisite RRのNAMEと同じNAMEを持つRRがゾーン内に存在しないことをテストし、そうでない場合はリクエスタにYXDOMAINを通知します。TYPEがANYでない場合、Prerequisite RRのNAMEとTYPEと同じNAMEとTYPEを持つRRがゾーン内に存在しないことをテストし、そうでない場合はリクエスタにYXRRSETを通知します。
3.2.3. このセクション内のCLASSがZCLASSと同じであるRRについて、TTLがゼロ(0)であることをテストし、そうでない場合はリクエスタにFORMERRを通知します。次に、一意の<NAME,TYPE>ごとにRRsetを構築し、結果の各RRsetをゾーン内のRRsetとセットの等価性(同じメンバー、それ以上でもそれ以下でもない)で比較します。Prerequisite RRsetがゾーンRRsetによって完全かつ正確に一致しない場合、リクエスタにNXRRSETを通知します。このセクション内のRRのCLASSがZCLASSまたはNONEまたはANY以外の場合、リクエスタにFORMERRを通知します。
3.2.4 - 前提条件セクションで使用されるメタ値の表
| CLASS | TYPE | RDATA | 意味 |
|---|---|---|---|
| ANY | ANY | 空 | 名前が使用中 |
| ANY | rrset | 空 | RRsetが存在する(値非依存) |
| NONE | ANY | 空 | 名前が使用されていない |
| NONE | rrset | 空 | RRsetが存在しない |
| zone | rrset | rr | RRsetが存在する(値依存) |
3.2.5 - 前提条件セクション処理の擬似コード
for rr in prerequisites
if (rr.ttl != 0)
return (FORMERR)
if (zone_of(rr.name) != ZNAME)
return (NOTZONE);
if (rr.class == ANY)
if (rr.rdlength != 0)
return (FORMERR)
if (rr.type == ANY)
if (!zone_name<rr.name>)
return (NXDOMAIN)
else
if (!zone_rrset<rr.name, rr.type>)
return (NXRRSET)
if (rr.class == NONE)
if (rr.rdlength != 0)
return (FORMERR)
if (rr.type == ANY)
if (zone_name<rr.name>)
return (YXDOMAIN)
else
if (zone_rrset<rr.name, rr.type>)
return (YXRRSET)
if (rr.class == zclass)
temp<rr.name, rr.type> += rr
else
return (FORMERR)
for rrset in temp
if (zone_rrset<rrset.name, rrset.type> != rrset)
return (NXRRSET)
3.3 リクエスタの許可のチェック
3.3.1. 次に、Updateセクションで指定されたRRを更新するリクエスタの許可は、実装依存の方法で、または後続のセキュアDNS更新プロトコルで指定されたメカニズムを使用してテストされる可能性があります。リクエスタがこれらの更新を実行する許可を持っていない場合、サーバーはその操作ログに警告メッセージを書き込み、リクエスタにREFUSEDを通知するか、許可の問題を無視して更新を続行することができます。
3.3.2. 正確な処理は実装定義ですが、これらの検証活動が実行される場合、更新が部分的に適用された後にREFUSED条件に遭遇した場合、部分的な更新を元に戻し、ゾーンを元の状態に復元してからリクエスタに応答する必要があるため、これはサーバーの処理でそのようなパフォーマンスが行われるべきポイントです。
3.3.3 - 許可チェックの擬似コード
if (security policy exists)
if (this update is not permitted)
if (local option)
log a message about permission problem
if (local option)
return (REFUSED)
3.4 更新セクションの処理
次に、Updateセクションは次のように処理されます。
3.4.1 - プレスキャン
Updateセクションはに解析され、各RRのCLASSがANY、NONE、またはZone Classと同じであることがチェックされ、そうでない場合はリクエスタにFORMERRを通知します。セクション1.2の定義を使用して、各RRのNAMEは、Zoneセクションで指定されたゾーン内にある必要があり、そうでない場合はリクエスタにNOTZONEを通知します。
3.4.1.2. CLASSがANYでないRRについて、TYPEをチェックし、それがANY、AXFR、MAILA、MAILB、またはその他のQUERYメタタイプ、または認識されないタイプの場合、リクエスタにFORMERRを通知します。CLASSがANYまたはNONEであるRRについて、TTLをチェックしてゼロ(0)であることを確認し、そうでない場合はリクエスタにFORMERRを通知します。CLASSがANYであるRRについて、RDLENGTHをチェックしてゼロ(0)であること(つまり、RDATAフィールドが空)を確認し、TYPEがAXFR、MAILA、MAILB、またはANY以外のその他のQUERYメタタイプ、または認識されないタイプでないことを確認し、そうでない場合はリクエスタにFORMERRを通知します。
3.4.1.3 - 更新セクションプレスキャンの擬似コード
[rr] for rr in updates
if (zone_of(rr.name) != ZNAME)
return (NOTZONE);
if (rr.class == zclass)
if (rr.type & ANY|AXFR|MAILA|MAILB)
return (FORMERR)
elsif (rr.class == ANY)
if (rr.ttl != 0 || rr.rdlength != 0
|| rr.type & AXFR|MAILA|MAILB)
return (FORMERR)
elsif (rr.class == NONE)
if (rr.ttl != 0 || rr.type & ANY|AXFR|MAILA|MAILB)
return (FORMERR)
else
return (FORMERR)
3.4.2 - 更新
Updateセクションはに解析され、これらのRRは順番に処理されます。
3.4.2.1. このセクションの処理中にシステム障害(メモリ不足条件や永続ストレージのハードウェアエラーなど)が発生した場合、リクエスタにSERVFAILを通知し、このトランザクション中にゾーンに適用されたすべての更新を元に戻します。
3.4.2.2. CLASSがZCLASSと同じUpdate RRはゾーンに追加されます。重複するRDATA(SOA RRの場合は常にそうであり、WKS RRの場合はADDRESSおよびPROTOCOLフィールドの両方が一致する場合)の場合、Zone RRはUpdate RRに置き換えられます。TYPEがSOAで、Zone SOA RRが存在しない場合、または新しいSOA.SERIALが現在のZone SOA RRのSOA.SERIALよりも低い([RFC1982]によると)か等しい場合、Update RRは無視されます。CNAME Update RRと非CNAME Zone RRsetの場合、またはその逆の場合、CNAME Update RRを無視し、そうでない場合はCNAME Zone RRをCNAME Update RRに置き換えます。
3.4.2.3. CLASSがANYでTYPEがANYであるUpdate RRについて、同じNAMEを持つすべてのZone RRが削除されますが、NAMEがZNAMEと同じ場合は、TYPEがSOAまたはNS以外のRRのみが削除されます。CLASSがANYでTYPEがANYでないUpdate RRについて、同じNAMEとTYPEを持つすべてのZone RRが削除されますが、NAMEがZNAMEと同じ場合は、SOAまたはNS RRは削除されません。
3.4.2.4. クラスがNONEであるUpdate RRについて、NAME、TYPE、RDATA、およびRDLENGTHがUpdate RRと等しいZone RRが削除されますが、NAMEがZNAMEと同じで、TYPEがSOAであるか、TYPEがNSで一致するZone RRがRRsetに残る唯一のNSである場合を除き、この場合、このUpdate RRは無視されます。
3.4.2.5. リクエスタにNOERRORを通知します。
3.4.2.6 - 更新セクションで使用されるメタ値の表
| CLASS | TYPE | RDATA | 意味 |
|---|---|---|---|
| ANY | ANY | 空 | 名前からすべてのRRsetを削除 |
| ANY | rrset | 空 | RRsetを削除 |
| NONE | rrset | rr | RRsetからRRを削除 |
| zone | rrset | rr | RRsetに追加 |
3.4.2.7 - 更新セクション処理の擬似コード
[rr] for rr in updates
if (rr.class == zclass)
if (rr.type == CNAME)
if (zone_rrset<rr.name, ~CNAME>)
next [rr]
elsif (zone_rrset<rr.name, CNAME>)
next [rr]
if (rr.type == SOA)
if (!zone_rrset<rr.name, SOA> ||
zone_rr<rr.name, SOA>.serial > rr.soa.serial)
zone_rr<rr.name, SOA> = rr
elsif (rr.type == WKS)
if (zone_rrset<rr.name, WKS, rr.proto, rr.address>)
zone_rr<rr.name, WKS, rr.proto, rr.address> = rr
else
zone_rrset<rr.name, WKS> += rr
else
zone_rrset<rr.name, rr.type> += rr
elsif (rr.class == ANY)
if (rr.type == ANY)
if (rr.name == zname)
zone_rrset<rr.name, ~(SOA|NS)> = Nil
else
zone_rrset<rr.name, *> = Nil
elsif (rr.name == zname &&
(rr.type == SOA || rr.type == NS))
next [rr]
else
zone_rrset<rr.name, rr.type> = Nil
elsif (rr.class == NONE)
if (rr.type == SOA)
next [rr]
if (rr.type == NS && zone_rrset<rr.name, NS> == rr)
next [rr]
zone_rr<rr.name, rr.type, rr.data> = Nil
return (NOERROR)
3.5 追加データセクションの処理
Additional Data処理はこのメモでは説明されていません。サーバーは、UPDATE処理に関連するAdditional Dataセクション内のRRを黙って無視する必要があります。ただし、Additional Dataセクションに、更新を有用にするためにサーバーが必要とするRR(新しいNS RRのターゲットのグルーA RRなど)が含まれている場合、このセクションを処理する必要があります。
3.6 トランザクションログへの変更の追加
ゾーンにトランザクションログがある場合、ゾーンに加えられた変更は、おそらく最小限のUPDATEメッセージの形式で、それに追加される可能性があります。SOA SERIALは、SOA RRがUPDATEメッセージの一部であった場合、またはサーバーポリシーがSOA SERIALの自動インクリメントを指示する場合にのみ更新されることに注意してください。
3.7 リクエスタへの応答の送信
この時点で、応答メッセージを組み立て、リクエスタに送り返す必要があります。ヘッダーには特別なオプションは含まれず、Zoneセクション(Queryの質問セクション)はリクエストの対応するセクションからコピーされます。PRCOUNT、UPCOUNT、およびADCOUNTはすべてゼロ(0)に設定されます。応答コードはNOERRORですが、処理または許可エラーが発生した場合を除き、この場合、適切なRCODEが送信されます。ゾーンの現在のSOA RRのコピーは、SOAパラメータを変更するためにUPDATEを使用しており、実際のステータスに関するフィードバックを必要とするリクエスタの利益のために、応答のAnswerセクションに送信される必要があります(エラーの場合でも)。
3.8 スレーブへの通知
プライマリマスターは、DNS NOTIFY([RFC1996]を参照)などのメカニズムを使用して、ゾーンが更新されたことを既知のスレーブに通知する必要があります。この通知は、ポリシーまたはUPDATEコンテンツのためにSOA SERIALがインクリメントされなかった場合でも送信される必要があることに注意してください。